From 6d1c20ac50c29239c3c709927801584aa3152fc0 Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Fri, 4 Nov 2022 15:09:17 -0400 Subject: [PATCH] feat(readImageArrayBuffer): Support componentType, pixelType options --- src/io/ReadImageArrayBufferOptions.ts | 7 +++ src/io/browser/index.ts | 1 + src/io/readImageArrayBuffer.ts | 21 ++++++- test/browser/io/readImageTest.js | 80 ++++++++++++++++----------- test/node/io/image/PNGTest.js | 7 +-- 5 files changed, 77 insertions(+), 39 deletions(-) create mode 100644 src/io/ReadImageArrayBufferOptions.ts diff --git a/src/io/ReadImageArrayBufferOptions.ts b/src/io/ReadImageArrayBufferOptions.ts new file mode 100644 index 000000000..8602ff814 --- /dev/null +++ b/src/io/ReadImageArrayBufferOptions.ts @@ -0,0 +1,7 @@ +import CastImageOptions from '../core/CastImageOptions.js' + +interface ReadImageArrayBufferOptions extends CastImageOptions { + mimeType: string +} + +export default ReadImageArrayBufferOptions \ No newline at end of file diff --git a/src/io/browser/index.ts b/src/io/browser/index.ts index 57b72c7e7..11b5fd6c6 100644 --- a/src/io/browser/index.ts +++ b/src/io/browser/index.ts @@ -4,6 +4,7 @@ export { default as getFileExtension } from './../getFileExtension.js' export { default as extensionToImageIO } from './../extensionToImageIO.js' export { default as extensionToMeshIO } from './../extensionToMeshIO.js' +export { default as ReadImageArrayBufferOptions } from './../ReadImageArrayBufferOptions.js' export { default as readImageArrayBuffer } from './../readImageArrayBuffer.js' export { default as readMeshArrayBuffer } from './../readMeshArrayBuffer.js' export { default as readArrayBuffer } from './../readArrayBuffer.js' diff --git a/src/io/readImageArrayBuffer.ts b/src/io/readImageArrayBuffer.ts index ff6d326b5..05d2c0462 100644 --- a/src/io/readImageArrayBuffer.ts +++ b/src/io/readImageArrayBuffer.ts @@ -2,12 +2,14 @@ import createWebWorkerPromise from '../core/internal/createWebWorkerPromise.js' import Image from '../core/Image.js' import InterfaceTypes from '../core/InterfaceTypes.js' import PipelineInput from '../pipeline/PipelineInput.js' +import castImage from '../core/castImage.js' import config from '../itkConfig.js' import ReadImageResult from './ReadImageResult.js' +import ReadImageArrayBufferOptions from './ReadImageArrayBufferOptions.js' -async function readImageArrayBuffer (webWorker: Worker | null, arrayBuffer: ArrayBuffer, fileName: string, mimeType: string): Promise { +async function readImageArrayBuffer (webWorker: Worker | null, arrayBuffer: ArrayBuffer, fileName: string, options?: ReadImageArrayBufferOptions | string): Promise { let worker = webWorker const { webworkerPromise, worker: usedWorker } = await createWebWorkerPromise(worker) worker = usedWorker @@ -27,6 +29,16 @@ async function readImageArrayBuffer (webWorker: Worker | null, arrayBuffer: Arra stderr: string outputs: any[] } + let mimeType = undefined + if (typeof options === 'undefined') { + } else if (typeof options === 'string') { + // backwards compatibility + mimeType = options + } else if (typeof options === 'object') { + if (typeof options.mimeType === 'string') { + mimeType = options.mimeType + } + } const result: RunReadImagePipelineResult = await webworkerPromise.postMessage( { operation: 'readImage', @@ -40,7 +52,12 @@ async function readImageArrayBuffer (webWorker: Worker | null, arrayBuffer: Arra }, transferables ) - return { image: result.outputs[0].data as Image, webWorker: worker } + let image = result.outputs[0].data as Image + if (typeof options === 'object' && (typeof options.componentType !== 'undefined' || typeof options.pixelType !== 'undefined')) { + image = castImage(image, options) + } + + return { image, webWorker: worker } } export default readImageArrayBuffer diff --git a/test/browser/io/readImageTest.js b/test/browser/io/readImageTest.js index d4152483f..a25f2d786 100644 --- a/test/browser/io/readImageTest.js +++ b/test/browser/io/readImageTest.js @@ -13,10 +13,10 @@ for (let ii = 0; ii < byteString.length; ++ii) { const cthead1SmallBlob = new window.Blob([intArray], { type: mimeString }) const cthead1SmallFile = new window.File([cthead1SmallBlob], 'cthead1Small.png') -const verifyImage = (t, image) => { +function verifyImage(t, image, componentType, pixelType) { t.is(image.imageType.dimension, 2, 'dimension') - t.is(image.imageType.componentType, IntTypes.UInt8, 'componentType') - t.is(image.imageType.pixelType, PixelTypes.Scalar, 'pixelType') + t.is(image.imageType.componentType, componentType) + t.is(image.imageType.pixelType, pixelType) t.is(image.imageType.components, 1, 'components') t.is(image.origin[0], 0.0, 'origin[0]') t.is(image.origin[1], 0.0, 'origin[1]') @@ -34,42 +34,56 @@ const verifyImage = (t, image) => { } export default function () { - test('readImageArrayBuffer reads an ArrayBuffer', (t) => { - return PromiseFileReader.readAsArrayBuffer(cthead1SmallFile) - .then(arrayBuffer => { - return readImageArrayBuffer(null, arrayBuffer, 'cthead1Small.png') - .then(function ({ image, webWorker }) { - webWorker.terminate() - verifyImage(t, image) - }) - }) + test('readImageArrayBuffer reads an ArrayBuffer', async (t) => { + const arrayBuffer = await PromiseFileReader.readAsArrayBuffer(cthead1SmallFile) + const { image, webWorker } = await readImageArrayBuffer(null, arrayBuffer, 'cthead1Small.png') + webWorker.terminate() + const componentType = IntTypes.UInt8 + const pixelType = PixelTypes.Scalar + verifyImage(t, image, componentType, pixelType) }) - test('readImageBlob reads a Blob', (t) => { - return readImageBlob(null, cthead1SmallBlob, 'cthead1Small.png') - .then(function ({ image, webWorker }) { - webWorker.terminate() - verifyImage(t, image) - }) + test('readImageArrayBuffer casts to the specified componentType', async (t) => { + const arrayBuffer = await PromiseFileReader.readAsArrayBuffer(cthead1SmallFile) + const componentType = IntTypes.UInt16 + const { image, webWorker } = await readImageArrayBuffer(null, arrayBuffer, 'cthead1Small.png', { componentType }) + webWorker.terminate() + const pixelType = PixelTypes.Scalar + verifyImage(t, image, componentType, pixelType) }) - test('readImageFile reads a File', (t) => { - return readImageFile(null, cthead1SmallFile) - .then(function ({ image, webWorker }) { - webWorker.terminate() - verifyImage(t, image) - }) + test('readImageArrayBuffer casts to the specified pixelType', async (t) => { + const arrayBuffer = await PromiseFileReader.readAsArrayBuffer(cthead1SmallFile) + const componentType = IntTypes.UInt16 + const pixelType = PixelTypes.Scalar + const { image, webWorker } = await readImageArrayBuffer(null, arrayBuffer, 'cthead1Small.png', { componentType, pixelType }) + webWorker.terminate() + verifyImage(t, image, componentType, pixelType) }) - test('readImageFile re-uses a WebWorker', (t) => { - return readImageFile(null, cthead1SmallFile) - .then(function ({ image, webWorker }) { - return readImageFile(webWorker, cthead1SmallFile) - .then(function ({ image, webWorker }) { - webWorker.terminate() - verifyImage(t, image) - }) - }) + test('readImageBlob reads a Blob', async (t) => { + const { image, webWorker } = await readImageBlob(null, cthead1SmallBlob, 'cthead1Small.png') + webWorker.terminate() + const componentType = IntTypes.UInt8 + const pixelType = PixelTypes.Scalar + verifyImage(t, image, componentType, pixelType) + }) + + test('readImageFile reads a File', async (t) => { + const { image, webWorker } = await readImageFile(null, cthead1SmallFile) + webWorker.terminate() + const componentType = IntTypes.UInt8 + const pixelType = PixelTypes.Scalar + verifyImage(t, image, componentType, pixelType) + }) + + test('readImageFile re-uses a WebWorker', async (t) => { + const { webWorker } = await readImageFile(null, cthead1SmallFile) + const { image } = await readImageFile(webWorker, cthead1SmallFile) + webWorker.terminate() + const componentType = IntTypes.UInt8 + const pixelType = PixelTypes.Scalar + verifyImage(t, image, componentType, pixelType) }) test('readImageFile throws a catchable error for an invalid file', (t) => { diff --git a/test/node/io/image/PNGTest.js b/test/node/io/image/PNGTest.js index 0e89448b4..8a8ee1d35 100644 --- a/test/node/io/image/PNGTest.js +++ b/test/node/io/image/PNGTest.js @@ -24,10 +24,9 @@ const verifyImage = (t, image) => { t.is(image.data.length, 196608, 'data.length') } -test('Test reading a PNG file', t => { - return readImageLocalFile(testInputFilePath).then(function (image) { - verifyImage(t, image) - }) +test('Test reading a PNG file', async t => { + const image = await readImageLocalFile(testInputFilePath) + verifyImage(t, image) }) test('Test writing a PNG file', t => {