From f9ac56ecafaa0168c0f6226cbe9857c562539212 Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Sat, 2 Jul 2022 13:42:32 -0400 Subject: [PATCH] feat(Image): use Map for metadata member Better interface with `has` that is more appropriate for key/value pairs of the itk::MetaDataDictionary. BREAKING_CHANGE: Image.metadata is now a Map instead of an Object --- doc/content/api/Image.md | 1 + src/core/Image.ts | 5 +++-- src/core/Metadata.ts | 3 +++ src/core/castImage.ts | 3 ++- src/core/index.ts | 1 + src/io/readImageDICOMArrayBufferSeries.ts | 8 ++++---- src/pipeline/internal/runPipelineEmscripten.ts | 4 +++- 7 files changed, 17 insertions(+), 8 deletions(-) create mode 100644 src/core/Metadata.ts diff --git a/doc/content/api/Image.md b/doc/content/api/Image.md index ccf7ebb4c..440b71569 100644 --- a/doc/content/api/Image.md +++ b/doc/content/api/Image.md @@ -10,6 +10,7 @@ An `Image` is the N-dimensional image data structure for *itk-wasm*. `Image` is **direction**: A *dimension* by *dimension* Float64Array in column-major order, that describes the orientation of the image at its *origin*. The orientation of each axis are the orthonormal columns. **size**: An Array with length *dimension* that contains the number of pixels along dimension. **data**: A [TypedArray](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray) containing the pixel buffer data. +**metadata**: A [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) of string keys to values that could be strings, string arrays, numbers, number arrays, or arrays of number arrays providing additional metadata for the image. For more information, see [the description](https://itk.org/ITKSoftwareGuide/html/Book1/ITKSoftwareGuide-Book1ch4.html#x38-490004.1) of an `itk::Image` in the ITK Software Guide. diff --git a/src/core/Image.ts b/src/core/Image.ts index 7ebf7143a..6291031e0 100644 --- a/src/core/Image.ts +++ b/src/core/Image.ts @@ -1,6 +1,7 @@ import ImageType from './ImageType.js' import type TypedArray from './TypedArray.js' import setMatrixElement from './setMatrixElement.js' +import Metadata from './Metadata.js' class Image { name: string = 'image' @@ -13,7 +14,7 @@ class Image { size: number[] - metadata: Record + metadata: Metadata data: null | TypedArray @@ -34,7 +35,7 @@ class Image { this.size = new Array(dimension) this.size.fill(0) - this.metadata = {} + this.metadata = new Map() this.data = null } diff --git a/src/core/Metadata.ts b/src/core/Metadata.ts new file mode 100644 index 000000000..6685698ca --- /dev/null +++ b/src/core/Metadata.ts @@ -0,0 +1,3 @@ +type Metadata = Map + +export default Metadata diff --git a/src/core/castImage.ts b/src/core/castImage.ts index 55ba01bde..bf83b04da 100644 --- a/src/core/castImage.ts +++ b/src/core/castImage.ts @@ -30,7 +30,8 @@ function castImage (inputImage: Image, options?: CastImageOptions): Image { outputImage.spacing = Array.from(inputImage.spacing) outputImage.direction = inputImage.direction.slice() outputImage.size = Array.from(inputImage.size) - outputImage.metadata = { ...inputImage.metadata } + // Deep copy the map + outputImage.metadata = new Map(JSON.parse(JSON.stringify(Array.from(inputImage.metadata)))) if (inputImage.data !== null) { if (typeof options !== 'undefined' && typeof options.componentType !== 'undefined' && options.componentType !== inputImage.imageType.componentType) { diff --git a/src/core/index.ts b/src/core/index.ts index 7ff136cb5..8e8037a4c 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -14,6 +14,7 @@ export { default as JsonObject } from './JsonObject.js' export { default as TypedArray } from './TypedArray.js' export { default as IntTypes } from './IntTypes.js' export { default as FloatTypes } from './FloatTypes.js' +export { default as Metadata } from './Metadata.js' export { default as IOTypes } from './IOTypes.js' diff --git a/src/io/readImageDICOMArrayBufferSeries.ts b/src/io/readImageDICOMArrayBufferSeries.ts index ae7b475d5..0a9c2a2a2 100644 --- a/src/io/readImageDICOMArrayBufferSeries.ts +++ b/src/io/readImageDICOMArrayBufferSeries.ts @@ -1,5 +1,6 @@ import createWebWorkerPromise from '../core/internal/createWebWorkerPromise.js' import WorkerPool from '../core/WorkerPool.js' +import Metadata from '../core/Metadata.js' import stackImages from '../core/stackImages.js' import BinaryFile from '../core/BinaryFile.js' import InterfaceTypes from '../core/InterfaceTypes.js' @@ -63,12 +64,11 @@ const workerFunction = async ( filenames?.pop() if (image.metadata === undefined) { - const metadata: - Record = {} - metadata.orderedFileNames = filenames + const metadata: Metadata = new Map() + metadata.set('OrderedFileNames', filenames) image.metadata = metadata } else { - image.metadata.orderedFileNames = filenames + image.metadata.set('OrderedFileNames', filenames) } return { image: result.outputs[0].data as Image, webWorker: worker } diff --git a/src/pipeline/internal/runPipelineEmscripten.ts b/src/pipeline/internal/runPipelineEmscripten.ts index 0f3cfc7ec..9bf6cd6ab 100644 --- a/src/pipeline/internal/runPipelineEmscripten.ts +++ b/src/pipeline/internal/runPipelineEmscripten.ts @@ -123,7 +123,8 @@ function runPipelineEmscripten (pipelineModule: PipelineEmscriptenModule, args: spacing: image.spacing, direction: `data:application/vnd.itk.address,0:${directionPtr}`, size: image.size, - data: `data:application/vnd.itk.address,0:${dataPtr}` + data: `data:application/vnd.itk.address,0:${dataPtr}`, + metadata: JSON.stringify(Array.from(image.metadata.entries())) } setPipelineModuleInputJSON(pipelineModule, imageJSON, index) break @@ -353,6 +354,7 @@ function runPipelineEmscripten (pipelineModule: PipelineEmscriptenModule, args: const image = getPipelineModuleOutputJSON(pipelineModule, index) as Image image.data = getPipelineModuleOutputArray(pipelineModule, index, 0, image.imageType.componentType) image.direction = getPipelineModuleOutputArray(pipelineModule, index, 1, FloatTypes.Float64) as Float64Array + image.metadata = new Map(image.metadata) outputData = image break }