Add support for auto conversion to RGB
This commit is contained in:
@@ -5,6 +5,7 @@ import DataTile from './DataTile.js';
|
|||||||
import TileGrid from '../tilegrid/TileGrid.js';
|
import TileGrid from '../tilegrid/TileGrid.js';
|
||||||
import {
|
import {
|
||||||
Pool,
|
Pool,
|
||||||
|
globals as geotiffGlobals,
|
||||||
fromBlob as tiffFromBlob,
|
fromBlob as tiffFromBlob,
|
||||||
fromUrl as tiffFromUrl,
|
fromUrl as tiffFromUrl,
|
||||||
fromUrls as tiffFromUrls,
|
fromUrls as tiffFromUrls,
|
||||||
@@ -31,6 +32,31 @@ function isMask(image) {
|
|||||||
return (type & 4) === 4;
|
return (type & 4) === 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {true|false|'auto'} preference The convertToRGB option.
|
||||||
|
* @param {GeoTIFFImage} image The image.
|
||||||
|
* @return {boolean} Use the `image.readRGB()` method.
|
||||||
|
*/
|
||||||
|
function readRGB(preference, image) {
|
||||||
|
if (!preference) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (preference === true) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (image.getSamplesPerPixel() !== 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const interpretation = image.fileDirectory.PhotometricInterpretation;
|
||||||
|
const interpretations = geotiffGlobals.photometricInterpretations;
|
||||||
|
return (
|
||||||
|
interpretation === interpretations.CMYK ||
|
||||||
|
interpretation === interpretations.YCbCr ||
|
||||||
|
interpretation === interpretations.CIELab ||
|
||||||
|
interpretation === interpretations.ICCLab
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} SourceInfo
|
* @typedef {Object} SourceInfo
|
||||||
* @property {string} [url] URL for the source GeoTIFF.
|
* @property {string} [url] URL for the source GeoTIFF.
|
||||||
@@ -320,9 +346,10 @@ function getMaxForDataType(array) {
|
|||||||
* another with 1 band, the resulting data tiles will have 5 bands: 3 from the first source, 1 alpha
|
* another with 1 band, the resulting data tiles will have 5 bands: 3 from the first source, 1 alpha
|
||||||
* band from the first source, and 1 band from the second source.
|
* band from the first source, and 1 band from the second source.
|
||||||
* @property {GeoTIFFSourceOptions} [sourceOptions] Additional options to be passed to [geotiff.js](https://geotiffjs.github.io/geotiff.js/module-geotiff.html)'s `fromUrl` or `fromUrls` methods.
|
* @property {GeoTIFFSourceOptions} [sourceOptions] Additional options to be passed to [geotiff.js](https://geotiffjs.github.io/geotiff.js/module-geotiff.html)'s `fromUrl` or `fromUrls` methods.
|
||||||
* @property {boolean} [convertToRGB = false] By default, bands from the sources are read as-is. When
|
* @property {true|false|'auto'} [convertToRGB=false] By default, bands from the sources are read as-is. When
|
||||||
* reading GeoTIFFs with the purpose of displaying them as RGB images, setting this to `true` will
|
* reading GeoTIFFs with the purpose of displaying them as RGB images, setting this to `true` will
|
||||||
* convert other color spaces (YCbCr, CMYK) to RGB.
|
* convert other color spaces (YCbCr, CMYK) to RGB. Setting the option to `'auto'` will make it so CMYK, YCbCr,
|
||||||
|
* CIELab, and ICCLab images will automatically be converted to RGB.
|
||||||
* @property {boolean} [normalize=true] By default, the source data is normalized to values between
|
* @property {boolean} [normalize=true] By default, the source data is normalized to values between
|
||||||
* 0 and 1 with scaling factors based on the raster statistics or `min` and `max` properties of each source.
|
* 0 and 1 with scaling factors based on the raster statistics or `min` and `max` properties of each source.
|
||||||
* If instead you want to work with the raw values in a style expression, set this to `false`. Setting this option
|
* If instead you want to work with the raw values in a style expression, set this to `false`. Setting this option
|
||||||
@@ -424,9 +451,9 @@ class GeoTIFFSource extends DataTile {
|
|||||||
this.error_ = null;
|
this.error_ = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {'readRasters' | 'readRGB'}
|
* @type {true|false|'auto'}
|
||||||
*/
|
*/
|
||||||
this.readMethod_ = options.convertToRGB ? 'readRGB' : 'readRasters';
|
this.convertToRGB_ = options.convertToRGB || false;
|
||||||
|
|
||||||
this.setKey(this.sourceInfo_.map((source) => source.url).join(','));
|
this.setKey(this.sourceInfo_.map((source) => source.url).join(','));
|
||||||
|
|
||||||
@@ -747,7 +774,7 @@ class GeoTIFFSource extends DataTile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
requests[sourceIndex] = image[this.readMethod_]({
|
const readOptions = {
|
||||||
window: pixelBounds,
|
window: pixelBounds,
|
||||||
width: sourceTileSize[0],
|
width: sourceTileSize[0],
|
||||||
height: sourceTileSize[1],
|
height: sourceTileSize[1],
|
||||||
@@ -755,7 +782,12 @@ class GeoTIFFSource extends DataTile {
|
|||||||
fillValue: fillValue,
|
fillValue: fillValue,
|
||||||
pool: pool,
|
pool: pool,
|
||||||
interleave: false,
|
interleave: false,
|
||||||
});
|
};
|
||||||
|
if (readRGB(this.convertToRGB_, image)) {
|
||||||
|
requests[sourceIndex] = image.readRGB(readOptions);
|
||||||
|
} else {
|
||||||
|
requests[sourceIndex] = image.readRasters(readOptions);
|
||||||
|
}
|
||||||
|
|
||||||
// requests after `sourceCount` are for mask data (if any)
|
// requests after `sourceCount` are for mask data (if any)
|
||||||
const maskIndex = sourceCount + sourceIndex;
|
const maskIndex = sourceCount + sourceIndex;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import TileState from '../../../../../src/ol/TileState.js';
|
|||||||
|
|
||||||
describe('ol/source/GeoTIFF', function () {
|
describe('ol/source/GeoTIFF', function () {
|
||||||
describe('constructor', function () {
|
describe('constructor', function () {
|
||||||
it('configures readMethod_ to read rasters', function () {
|
it('sets convertToRGB false by default', function () {
|
||||||
const source = new GeoTIFFSource({
|
const source = new GeoTIFFSource({
|
||||||
sources: [
|
sources: [
|
||||||
{
|
{
|
||||||
@@ -11,10 +11,10 @@ describe('ol/source/GeoTIFF', function () {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
expect(source.readMethod_).to.be('readRasters');
|
expect(source.convertToRGB_).to.be(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('configures readMethod_ to read RGB', function () {
|
it('respects the convertToRGB option', function () {
|
||||||
const source = new GeoTIFFSource({
|
const source = new GeoTIFFSource({
|
||||||
convertToRGB: true,
|
convertToRGB: true,
|
||||||
sources: [
|
sources: [
|
||||||
@@ -23,7 +23,19 @@ describe('ol/source/GeoTIFF', function () {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
expect(source.readMethod_).to.be('readRGB');
|
expect(source.convertToRGB_).to.be(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('accepts auto convertToRGB', function () {
|
||||||
|
const source = new GeoTIFFSource({
|
||||||
|
convertToRGB: 'auto',
|
||||||
|
sources: [
|
||||||
|
{
|
||||||
|
url: 'spec/ol/source/images/0-0-0.tif',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
expect(source.convertToRGB_).to.be('auto');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('defaults to wrapX: false', function () {
|
it('defaults to wrapX: false', function () {
|
||||||
|
|||||||
BIN
test/rendering/cases/cog-rgb-auto/expected.png
Normal file
BIN
test/rendering/cases/cog-rgb-auto/expected.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 79 KiB |
22
test/rendering/cases/cog-rgb-auto/main.js
Normal file
22
test/rendering/cases/cog-rgb-auto/main.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import GeoTIFF from '../../../../src/ol/source/GeoTIFF.js';
|
||||||
|
import Map from '../../../../src/ol/Map.js';
|
||||||
|
import TileLayer from '../../../../src/ol/layer/WebGLTile.js';
|
||||||
|
|
||||||
|
const source = new GeoTIFF({
|
||||||
|
convertToRGB: 'auto',
|
||||||
|
sources: [{url: '/data/raster/masked.tif'}],
|
||||||
|
});
|
||||||
|
|
||||||
|
new Map({
|
||||||
|
layers: [
|
||||||
|
new TileLayer({
|
||||||
|
source: source,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
target: 'map',
|
||||||
|
view: source.getView(),
|
||||||
|
});
|
||||||
|
|
||||||
|
render({
|
||||||
|
message: 'automatically converts to rgb',
|
||||||
|
});
|
||||||
BIN
test/rendering/cases/cog-rgb-no-auto/expected.png
Normal file
BIN
test/rendering/cases/cog-rgb-no-auto/expected.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 51 KiB |
22
test/rendering/cases/cog-rgb-no-auto/main.js
Normal file
22
test/rendering/cases/cog-rgb-no-auto/main.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import GeoTIFF from '../../../../src/ol/source/GeoTIFF.js';
|
||||||
|
import Map from '../../../../src/ol/Map.js';
|
||||||
|
import TileLayer from '../../../../src/ol/layer/WebGLTile.js';
|
||||||
|
|
||||||
|
const source = new GeoTIFF({
|
||||||
|
convertToRGB: false,
|
||||||
|
sources: [{url: '/data/raster/masked.tif'}],
|
||||||
|
});
|
||||||
|
|
||||||
|
new Map({
|
||||||
|
layers: [
|
||||||
|
new TileLayer({
|
||||||
|
source: source,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
target: 'map',
|
||||||
|
view: source.getView(),
|
||||||
|
});
|
||||||
|
|
||||||
|
render({
|
||||||
|
message: 'can be overridden to read raw YCbCr',
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user