@giro3d/giro3d
Version:
A JS/WebGL framework for 3D geospatial data visualization
96 lines (92 loc) • 3.6 kB
JavaScript
/*
* Copyright (c) 2015-2018, IGN France.
* Copyright (c) 2018-2026, Giro3D team.
* SPDX-License-Identifier: MIT
*/
import { DataTexture, FloatType, LinearFilter, RGFormat } from 'three';
import WorkerPool from '../utils/WorkerPool';
import { decodeRaster } from './bilWorker';
import ImageFormat from './ImageFormat';
let workerPool = null;
function createWorker() {
return new Worker(URL.createObjectURL(new Blob([atob('InVzZSBzdHJpY3QiOygoKT0+e2Z1bmN0aW9uIGEodCxlKXtyZXR1cm57cmVxdWVzdElkOnQsZXJyb3I6ZSBpbnN0YW5jZW9mIEVycm9yP2UubWVzc2FnZToidW5rbm93biBlcnJvciJ9fWZ1bmN0aW9uIGModCxlKXtsZXQgcj0xLzAsbz0tMS8wLG49bmV3IEZsb2F0MzJBcnJheSh0Lmxlbmd0aCoyKTtmb3IobGV0IHM9MDtzPHQubGVuZ3RoO3MrKyl7bGV0IGk9dFtzXTtlIT1udWxsJiZpPD1lPyhuW3MqMiswXT0wLG5bcyoyKzFdPTApOihuW3MqMiswXT1pLG5bcyoyKzFdPTEscj1NYXRoLm1pbihpLHIpLG89TWF0aC5tYXgoaSxvKSl9cmV0dXJue2RhdGE6bi5idWZmZXIsbWluOnIsbWF4Om99fW9ubWVzc2FnZT1mdW5jdGlvbih0KXtsZXQgZT10LmRhdGE7dHJ5e2lmKGUudHlwZT09PSJEZWNvZGVCaWxUZXJyYWluTWVzc2FnZSIpe2xldCByPWMobmV3IEZsb2F0MzJBcnJheShlLnBheWxvYWQuYnVmZmVyKSxlLnBheWxvYWQubm9EYXRhKSxvPXtyZXF1ZXN0SWQ6ZS5pZCxwYXlsb2FkOnJ9O3RoaXMucG9zdE1lc3NhZ2Uobyx7dHJhbnNmZXI6W28ucGF5bG9hZC5kYXRhXX0pfX1jYXRjaChyKXt0aGlzLnBvc3RNZXNzYWdlKGEoZS5pZCxyKSl9fTt9KSgpOwo=')], {type: "text/javascript"})), {
type: 'module',
name: 'bil'
});
}
/**
* Decoder for [BIL](https://desktop.arcgis.com/en/arcmap/10.3/manage-data/raster-and-images/bil-bip-and-bsq-raster-files.htm) images.
*
* At the moment, only single band BIL files are supported and it is tested only on IGN elevation
* WMS and WMTS layers.
*
* ```js
* // Create an elevation source
* const source = new WmsSource({
* url: 'https://data.geopf.fr/wms-r',
* projection: 'EPSG:2154',
* layer: 'ELEVATION.ELEVATIONGRIDCOVERAGE.HIGHRES',
* imageFormat: 'image/x-bil;bits=32',
* format: new BilFormat(),
* });
*
* const elevationLayer = new ElevationLayer({ source });
*
* map.addLayer(elevationLayer);
*
* ```
* [See it in action](/examples/ign-data.html).
*
*/
class BilFormat extends ImageFormat {
isBilFormat = true;
type = 'BilFormat';
_enableWorkers = true;
/**
* @param options - Decoder options.
*/
constructor(options) {
super(true, FloatType);
this._enableWorkers = options?.enableWorkers ?? true;
this._workerConcurrency = options?.workerConcurrency ?? undefined;
}
/**
* Decode a Bil blob into a
* [DataTexture](https://threejs.org/docs/?q=texture#api/en/textures/DataTexture) containing
* the elevation data. At the moment only one band BIL is supported.
*
* @param blob - the data to decode
* @param options - the decoding options
*/
async decode(blob, options) {
const buffer = await blob.arrayBuffer();
const floatArray = new Float32Array(buffer);
const noData = options?.noDataValue;
let result;
if (this._enableWorkers) {
if (workerPool == null) {
workerPool = new WorkerPool({
createWorker,
concurrency: this._workerConcurrency
});
}
result = await workerPool.queue('DecodeBilTerrainMessage', {
buffer,
noData
});
} else {
result = decodeRaster(floatArray, noData);
}
const texture = new DataTexture(new Float32Array(result.data), options.width, options.height, RGFormat, FloatType);
texture.needsUpdate = true;
texture.generateMipmaps = false;
texture.magFilter = LinearFilter;
texture.minFilter = LinearFilter;
return {
texture,
min: result.min,
max: result.max
};
}
}
export default BilFormat;