From fa75154737d5de62f66587b50b33910412d2745a Mon Sep 17 00:00:00 2001 From: Jeff Peck Date: Fri, 12 May 2023 18:18:29 -0400 Subject: [PATCH] be more forgiving when fileDirectory.SampleFormat does not have all values populated, such as in bioformats ome tif files --- src/geotiffimage.js | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/src/geotiffimage.js b/src/geotiffimage.js index 21994643..12281d42 100644 --- a/src/geotiffimage.js +++ b/src/geotiffimage.js @@ -1,12 +1,12 @@ /** @module geotiffimage */ -import { getFloat16 } from '@petamoriken/float16'; +import {getFloat16} from '@petamoriken/float16'; import getAttribute from 'xml-utils/get-attribute.js'; import findTagsByName from 'xml-utils/find-tags-by-name.js'; -import { photometricInterpretations, ExtraSamplesValues } from './globals.js'; -import { fromWhiteIsZero, fromBlackIsZero, fromPalette, fromCMYK, fromYCbCr, fromCIELab } from './rgb.js'; -import { getDecoder } from './compression/index.js'; -import { resample, resampleInterleaved } from './resample.js'; +import {photometricInterpretations, ExtraSamplesValues} from './globals.js'; +import {fromWhiteIsZero, fromBlackIsZero, fromPalette, fromCMYK, fromYCbCr, fromCIELab} from './rgb.js'; +import {getDecoder} from './compression/index.js'; +import {resample, resampleInterleaved} from './resample.js'; /** * @typedef {Object} ReadRasterOptions @@ -295,8 +295,8 @@ class GeoTIFFImage { } getReaderForSample(sampleIndex) { - const format = this.fileDirectory.SampleFormat - ? this.fileDirectory.SampleFormat[sampleIndex] : 1; + const format = this.getSampleFormat(sampleIndex); + const bitsPerSample = this.fileDirectory.BitsPerSample[sampleIndex]; switch (format) { case 1: // unsigned integer data @@ -339,7 +339,8 @@ class GeoTIFFImage { getSampleFormat(sampleIndex = 0) { return this.fileDirectory.SampleFormat - ? this.fileDirectory.SampleFormat[sampleIndex] : 1; + ? (this.fileDirectory.SampleFormat[sampleIndex] ?? Math.max.apply(null, this.fileDirectory.SampleFormat)) + : 1; } getBitsPerSample(sampleIndex = 0) { @@ -366,7 +367,7 @@ class GeoTIFFImage { const numTilesPerRow = Math.ceil(this.getWidth() / this.getTileWidth()); const numTilesPerCol = Math.ceil(this.getHeight() / this.getTileHeight()); let index; - const { tiles } = this; + const {tiles} = this; if (this.planarConfiguration === 1) { index = (y * numTilesPerRow) + x; } else if (this.planarConfiguration === 2) { @@ -382,11 +383,11 @@ class GeoTIFFImage { offset = this.fileDirectory.StripOffsets[index]; byteCount = this.fileDirectory.StripByteCounts[index]; } - const slice = (await this.source.fetch([{ offset, length: byteCount }], signal))[0]; + const slice = (await this.source.fetch([{offset, length: byteCount}], signal))[0]; let request; if (tiles === null || !tiles[index]) { - // resolve each request by potentially applying array normalization + // resolve each request by potentially applying array normalization request = (async () => { let data = await poolOrDecoder.decode(this.fileDirectory, slice); const sampleFormat = this.getSampleFormat(); @@ -415,7 +416,7 @@ class GeoTIFFImage { } // cache the tile request - return { x, y, sample, data: await request }; + return {x, y, sample, data: await request}; } /** @@ -434,7 +435,7 @@ class GeoTIFFImage { * @returns {Promise} */ async _readRaster(imageWindow, samples, valueArrays, interleave, poolOrDecoder, width, - height, resampleMethod, signal) { + height, resampleMethod, signal) { const tileWidth = this.getTileWidth(); const tileHeight = this.getTileHeight(); const imageWidth = this.getWidth(); @@ -466,7 +467,7 @@ class GeoTIFFImage { } const promises = []; - const { littleEndian } = this; + const {littleEndian} = this; for (let yTile = minYTile; yTile < maxYTile; ++yTile) { for (let xTile = minXTile; xTile < maxXTile; ++xTile) { @@ -517,7 +518,7 @@ class GeoTIFFImage { await Promise.all(promises); if ((width && (imageWindow[2] - imageWindow[0]) !== width) - || (height && (imageWindow[3] - imageWindow[1]) !== height)) { + || (height && (imageWindow[3] - imageWindow[1]) !== height)) { let resampled; if (interleave) { resampled = resampleInterleaved( @@ -558,9 +559,9 @@ class GeoTIFFImage { * @returns {Promise} the decoded arrays as a promise */ async readRasters({ - window: wnd, samples = [], interleave, pool = null, - width, height, resampleMethod, fillValue, signal, - } = {}) { + window: wnd, samples = [], interleave, pool = null, + width, height, resampleMethod, fillValue, signal, + } = {}) { const imageWindow = wnd || [0, 0, this.getWidth(), this.getHeight()]; // check parameters @@ -638,8 +639,10 @@ class GeoTIFFImage { * to be aborted * @returns {Promise} the RGB array as a Promise */ - async readRGB({ window, interleave = true, pool = null, width, height, - resampleMethod, enableAlpha = false, signal } = {}) { + async readRGB({ + window, interleave = true, pool = null, width, height, + resampleMethod, enableAlpha = false, signal + } = {}) { const imageWindow = window || [0, 0, this.getWidth(), this.getHeight()]; // check parameters @@ -697,7 +700,7 @@ class GeoTIFFImage { resampleMethod, signal, }; - const { fileDirectory } = this; + const {fileDirectory} = this; const raster = await this.readRasters(subOptions); const max = 2 ** this.fileDirectory.BitsPerSample[0];