From 230c1898c5db5c80e5457f09efb9ac59dc6c2890 Mon Sep 17 00:00:00 2001 From: James Manners Date: Fri, 24 Feb 2023 09:01:19 +1100 Subject: [PATCH 1/3] Improve WARORS types as per PR comments --- .../wadors/metaData/getNumberString.ts | 8 ++-- .../wadors/metaData/getNumberValue.ts | 4 +- .../wadors/metaData/getNumberValues.ts | 11 +++-- .../wadors/metaData/getOverlayPlaneModule.ts | 7 ++- .../imageLoader/wadors/metaData/getValue.ts | 6 +-- .../wadors/metaData/metaDataProvider.ts | 47 ++++++++++++------- .../wadors/retrieveMultiframeMetadata.ts | 2 +- .../wadouri/metaData/metaDataProvider.ts | 18 ++++--- .../src/types/WADORSMetaData.ts | 6 ++- 9 files changed, 69 insertions(+), 40 deletions(-) diff --git a/packages/dicomImageLoader/src/imageLoader/wadors/metaData/getNumberString.ts b/packages/dicomImageLoader/src/imageLoader/wadors/metaData/getNumberString.ts index 7f71fa5731..637dfe836a 100644 --- a/packages/dicomImageLoader/src/imageLoader/wadors/metaData/getNumberString.ts +++ b/packages/dicomImageLoader/src/imageLoader/wadors/metaData/getNumberString.ts @@ -12,15 +12,15 @@ import getValue from './getValue'; function getNumberString( element: WADORSMetaDataElement, index: number, - defaultValue -) { - const value = getValue(element, index, defaultValue); + defaultValue: number +): number { + const value = getValue(element, index, defaultValue); if (value === undefined) { return; } - return parseFloat(value as string); + return parseFloat(value); } export default getNumberString; diff --git a/packages/dicomImageLoader/src/imageLoader/wadors/metaData/getNumberValue.ts b/packages/dicomImageLoader/src/imageLoader/wadors/metaData/getNumberValue.ts index 8e68cb0125..dd10381118 100644 --- a/packages/dicomImageLoader/src/imageLoader/wadors/metaData/getNumberValue.ts +++ b/packages/dicomImageLoader/src/imageLoader/wadors/metaData/getNumberValue.ts @@ -5,13 +5,13 @@ function getNumberValue( element: WADORSMetaDataElement, index?: number ): number { - const value = getValue(element, index); + const value = getValue(element, index); if (value === undefined) { return; } - return parseFloat(value as string); + return parseFloat(value); } export default getNumberValue; diff --git a/packages/dicomImageLoader/src/imageLoader/wadors/metaData/getNumberValues.ts b/packages/dicomImageLoader/src/imageLoader/wadors/metaData/getNumberValues.ts index 0659924e63..148bc5b43d 100644 --- a/packages/dicomImageLoader/src/imageLoader/wadors/metaData/getNumberValues.ts +++ b/packages/dicomImageLoader/src/imageLoader/wadors/metaData/getNumberValues.ts @@ -18,15 +18,20 @@ function getNumberValues( if (!element.Value) { return; } + // Make sure the Value is an array + if (!Array.isArray(element.Value)) { + return; + } // make sure we have the expected length - if (minimumLength && (element.Value as any).length < minimumLength) { + if (minimumLength && element.Value.length < minimumLength) { return; } const values: number[] = []; - for (let i = 0; i < (element.Value as any).length; i++) { - values.push(parseFloat(element.Value[i] as string)); + for (let i = 0; i < element.Value.length; i++) { + // @ts-expect-error + values.push(parseFloat(element.Value[i])); } return values; diff --git a/packages/dicomImageLoader/src/imageLoader/wadors/metaData/getOverlayPlaneModule.ts b/packages/dicomImageLoader/src/imageLoader/wadors/metaData/getOverlayPlaneModule.ts index 289d81ae19..e94c47c6fe 100644 --- a/packages/dicomImageLoader/src/imageLoader/wadors/metaData/getOverlayPlaneModule.ts +++ b/packages/dicomImageLoader/src/imageLoader/wadors/metaData/getOverlayPlaneModule.ts @@ -12,7 +12,12 @@ export default function getOverlayPlaneModule(metaData: WADORSMetaData) { groupStr = `x600${overlayGroup.toString(16)}`; } - const data = getValue(metaData[`${groupStr}3000`]) as any; + /** + * @todo there is a type issue with WADORSMetaData. Currently WADORSMetaData + * on includes string[] | number[] | boolean. from the look of this, data + * is a more complex type + */ + const data = getValue(metaData[`${groupStr}3000`]); if (!data) { continue; diff --git a/packages/dicomImageLoader/src/imageLoader/wadors/metaData/getValue.ts b/packages/dicomImageLoader/src/imageLoader/wadors/metaData/getValue.ts index ce984aafd8..b22362bbed 100644 --- a/packages/dicomImageLoader/src/imageLoader/wadors/metaData/getValue.ts +++ b/packages/dicomImageLoader/src/imageLoader/wadors/metaData/getValue.ts @@ -8,11 +8,11 @@ import { WADORSMetaDataElement } from '../../../types'; * @param [defaultValue] - The default value to return if the element does not exist * @returns {*} */ -function getValue( +function getValue( element: WADORSMetaDataElement, index?: number, - defaultValue?: number | string -): number[] | string[] | string | number { + defaultValue?: ReturnType +): ReturnType { index = index || 0; if (!element) { return defaultValue; diff --git a/packages/dicomImageLoader/src/imageLoader/wadors/metaData/metaDataProvider.ts b/packages/dicomImageLoader/src/imageLoader/wadors/metaData/metaDataProvider.ts index 7e52b67349..93979bbdeb 100644 --- a/packages/dicomImageLoader/src/imageLoader/wadors/metaData/metaDataProvider.ts +++ b/packages/dicomImageLoader/src/imageLoader/wadors/metaData/metaDataProvider.ts @@ -56,15 +56,20 @@ function metaDataProvider(type, imageId) { if (type === 'generalSeriesModule') { return { - modality: getValue(metaData['00080060']), - seriesInstanceUID: getValue(metaData['0020000E']), + modality: getValue(metaData['00080060']), + seriesInstanceUID: getValue(metaData['0020000E']), seriesNumber: getNumberValue(metaData['00200011']), - studyInstanceUID: getValue(metaData['0020000D']), - seriesDate: dicomParser.parseDA(getValue(metaData['00080021'])), - seriesTime: dicomParser.parseTM(getValue(metaData['00080031'], 0, '')), - acquisitionDate: dicomParser.parseDA(getValue(metaData['00080022']), ''), + studyInstanceUID: getValue(metaData['0020000D']), + seriesDate: dicomParser.parseDA(getValue(metaData['00080021'])), + seriesTime: dicomParser.parseTM( + getValue(metaData['00080031'], 0, '') + ), + acquisitionDate: dicomParser.parseDA( + getValue(metaData['00080022']), + '' + ), acquisitionTime: dicomParser.parseTM( - getValue(metaData['00080032'], 0, '') + getValue(metaData['00080032'], 0, '') ), }; } @@ -73,7 +78,7 @@ function metaDataProvider(type, imageId) { return { patientAge: getNumberValue(metaData['00101010']), patientSize: getNumberValue(metaData['00101020']), - patientSex: getValue(metaData['00100040']), + patientSex: getValue<'M' | 'F'>(metaData['00100040']), patientWeight: getNumberValue(metaData['00101030']), }; } @@ -99,19 +104,25 @@ function metaDataProvider(type, imageId) { if (imageOrientationPatient) { rowCosines = [ - parseFloat(imageOrientationPatient[0] as any), - parseFloat(imageOrientationPatient[1] as any), - parseFloat(imageOrientationPatient[2] as any), + // @ts-expect-error + parseFloat(imageOrientationPatient[0]), + // @ts-expect-error + parseFloat(imageOrientationPatient[1]), + // @ts-expect-error + parseFloat(imageOrientationPatient[2]), ]; columnCosines = [ - parseFloat(imageOrientationPatient[3] as any), - parseFloat(imageOrientationPatient[4] as any), - parseFloat(imageOrientationPatient[5] as any), + // @ts-expect-error + parseFloat(imageOrientationPatient[3]), + // @ts-expect-error + parseFloat(imageOrientationPatient[4]), + // @ts-expect-error + parseFloat(imageOrientationPatient[5]), ]; } return { - frameOfReferenceUID: getValue(metaData['00200052']), + frameOfReferenceUID: getValue(metaData['00200052']), rows: getNumberValue(metaData['00280010']), columns: getNumberValue(metaData['00280011']), imageOrientationPatient, @@ -174,8 +185,8 @@ function metaDataProvider(type, imageId) { if (type === 'sopCommonModule') { return { - sopClassUID: getValue(metaData['00080016']), - sopInstanceUID: getValue(metaData['00080018']), + sopClassUID: getValue(metaData['00080016']), + sopInstanceUID: getValue(metaData['00080018']), }; } @@ -209,7 +220,7 @@ function metaDataProvider(type, imageId) { // retrieved from the image if (type === 'transferSyntax') { return { - transferSyntaxUID: getValue(metaData['00020010']), + transferSyntaxUID: getValue(metaData['00020010']), }; } diff --git a/packages/dicomImageLoader/src/imageLoader/wadors/retrieveMultiframeMetadata.ts b/packages/dicomImageLoader/src/imageLoader/wadors/retrieveMultiframeMetadata.ts index aa34131ecc..2f55f8814a 100644 --- a/packages/dicomImageLoader/src/imageLoader/wadors/retrieveMultiframeMetadata.ts +++ b/packages/dicomImageLoader/src/imageLoader/wadors/retrieveMultiframeMetadata.ts @@ -27,7 +27,7 @@ function retrieveMultiframeMetadata(imageId) { function isMultiframe(metadata) { // Checks if dicomTag NumberOf Frames exists and it is greater than one - const numberOfFrames = getValue(metadata['00280008']); + const numberOfFrames = getValue(metadata['00280008']); return numberOfFrames && numberOfFrames > 1; } diff --git a/packages/dicomImageLoader/src/imageLoader/wadouri/metaData/metaDataProvider.ts b/packages/dicomImageLoader/src/imageLoader/wadouri/metaData/metaDataProvider.ts index 1843694b9a..c38ff57831 100644 --- a/packages/dicomImageLoader/src/imageLoader/wadouri/metaData/metaDataProvider.ts +++ b/packages/dicomImageLoader/src/imageLoader/wadouri/metaData/metaDataProvider.ts @@ -77,14 +77,20 @@ function metaDataProvider(type, imageId) { if (imageOrientationPatient) { rowCosines = [ - parseFloat(imageOrientationPatient[0] as any), - parseFloat(imageOrientationPatient[1] as any), - parseFloat(imageOrientationPatient[2] as any), + // @ts-expect-error + parseFloat(imageOrientationPatient[0]), + // @ts-expect-error + parseFloat(imageOrientationPatient[1]), + // @ts-expect-error + parseFloat(imageOrientationPatient[2]), ]; columnCosines = [ - parseFloat(imageOrientationPatient[3] as any), - parseFloat(imageOrientationPatient[4] as any), - parseFloat(imageOrientationPatient[5] as any), + // @ts-expect-error + parseFloat(imageOrientationPatient[3]), + // @ts-expect-error + parseFloat(imageOrientationPatient[4]), + // @ts-expect-error + parseFloat(imageOrientationPatient[5]), ]; } diff --git a/packages/dicomImageLoader/src/types/WADORSMetaData.ts b/packages/dicomImageLoader/src/types/WADORSMetaData.ts index 95b129264c..bf3db80140 100644 --- a/packages/dicomImageLoader/src/types/WADORSMetaData.ts +++ b/packages/dicomImageLoader/src/types/WADORSMetaData.ts @@ -1,5 +1,7 @@ -export interface WADORSMetaDataElement { - Value: string[] | number[] | boolean; +export interface WADORSMetaDataElement< + ValueType = string[] | number[] | boolean +> { + Value: ValueType; } export type WADORSMetaData = Record; From f4a23d25e261a74954b8d4df5826e7153145e649 Mon Sep 17 00:00:00 2001 From: James Manners Date: Fri, 24 Feb 2023 10:07:05 +1100 Subject: [PATCH 2/3] [dicom-image-loader] add types for wasm codec modules --- packages/dicomImageLoader/package.json | 1 + .../src/shared/decoders/codec-charls.d.ts | 18 ++++++++++++++ .../decoders/codec-libjpeg-turbo-8bit.d.ts | 15 ++++++++++++ .../src/shared/decoders/codec-openjpeg.d.ts | 24 +++++++++++++++++++ .../src/shared/decoders/decodeJPEG2000.ts | 12 ++++++++-- .../shared/decoders/decodeJPEGBaseline8Bit.ts | 14 +++++++---- .../src/shared/decoders/decodeJPEGLS.ts | 12 ++++++++-- yarn.lock | 5 ++++ 8 files changed, 93 insertions(+), 8 deletions(-) create mode 100644 packages/dicomImageLoader/src/shared/decoders/codec-charls.d.ts create mode 100644 packages/dicomImageLoader/src/shared/decoders/codec-libjpeg-turbo-8bit.d.ts create mode 100644 packages/dicomImageLoader/src/shared/decoders/codec-openjpeg.d.ts diff --git a/packages/dicomImageLoader/package.json b/packages/dicomImageLoader/package.json index bc0e6ce8d4..3bd6d3b162 100644 --- a/packages/dicomImageLoader/package.json +++ b/packages/dicomImageLoader/package.json @@ -58,6 +58,7 @@ "devDependencies": { "@babel/plugin-proposal-object-rest-spread": "^7.14.7", "@babel/runtime-corejs3": "^7.15.4", + "@types/emscripten": "^1.39.6", "@types/jasmine": "^4.3.1", "@types/karma": "^6.3.3", "chai": "^4.3.4", diff --git a/packages/dicomImageLoader/src/shared/decoders/codec-charls.d.ts b/packages/dicomImageLoader/src/shared/decoders/codec-charls.d.ts new file mode 100644 index 0000000000..a565e418d7 --- /dev/null +++ b/packages/dicomImageLoader/src/shared/decoders/codec-charls.d.ts @@ -0,0 +1,18 @@ +/// + +declare module '@cornerstonejs/codec-charls/dist/charlswasm_decode' { + export class JpegLSDecoder { + decode: () => any; + getDecodedBuffer: () => any; + getEncodedBuffer: (length: number) => any; + getFrameInfo: () => any; + getInterleaveMode: () => any; + getNearLossless: () => any; + } + export interface CharlsModule extends EmscriptenModule { + JpegLSDecoder: typeof JpegLSDecoder; + getExceptionMessage: (exception: number) => any; + } + declare const Module: EmscriptenModuleFactory; + export default Module; +} diff --git a/packages/dicomImageLoader/src/shared/decoders/codec-libjpeg-turbo-8bit.d.ts b/packages/dicomImageLoader/src/shared/decoders/codec-libjpeg-turbo-8bit.d.ts new file mode 100644 index 0000000000..2ceebc888e --- /dev/null +++ b/packages/dicomImageLoader/src/shared/decoders/codec-libjpeg-turbo-8bit.d.ts @@ -0,0 +1,15 @@ +/// + +declare module '@cornerstonejs/codec-libjpeg-turbo-8bit/dist/libjpegturbowasm_decode' { + export class LibJpegTurbo8Bit { + decode: () => any; + getDecodedBuffer: () => any; + getEncodedBuffer: (length: number) => any; + getFrameInfo: () => any; + } + export interface OpenJpegModule extends EmscriptenModule { + JPEGDecoder: typeof LibJpegTurbo8Bit; + } + declare const Module: EmscriptenModuleFactory; + export default Module; +} diff --git a/packages/dicomImageLoader/src/shared/decoders/codec-openjpeg.d.ts b/packages/dicomImageLoader/src/shared/decoders/codec-openjpeg.d.ts new file mode 100644 index 0000000000..10467e472f --- /dev/null +++ b/packages/dicomImageLoader/src/shared/decoders/codec-openjpeg.d.ts @@ -0,0 +1,24 @@ +/// + +declare module '@cornerstonejs/codec-openjpeg/dist/openjpegwasm_decode' { + export class J2KDecoder { + decode: () => any; + getBlockDimensions: () => any; + getColorSpace: () => any; + getDecodedBuffer: () => any; + getEncodedBuffer: (length: number) => any; + getFrameInfo: () => any; + getImageOffset: () => any; + getIsReversible: () => any; + getNumDecompositions: () => any; + getNumLayers: () => any; + getProgressionOrder: () => number; + getTileOffset: () => any; + getTileSize: () => any; + } + export interface OpenJpegModule extends EmscriptenModule { + J2KDecoder: typeof J2KDecoder; + } + declare const Module: EmscriptenModuleFactory; + export default Module; +} diff --git a/packages/dicomImageLoader/src/shared/decoders/decodeJPEG2000.ts b/packages/dicomImageLoader/src/shared/decoders/decodeJPEG2000.ts index 64fb8bbd2c..7423071cd1 100644 --- a/packages/dicomImageLoader/src/shared/decoders/decodeJPEG2000.ts +++ b/packages/dicomImageLoader/src/shared/decoders/decodeJPEG2000.ts @@ -1,4 +1,8 @@ // https://emscripten.org/docs/api_reference/module.html +import type { + J2KDecoder, + OpenJpegModule, +} from '@cornerstonejs/codec-openjpeg/dist/openjpegwasm_decode'; import openJpegFactory from '@cornerstonejs/codec-openjpeg/dist/openjpegwasm_decode'; const openjpegWasm = new URL( @@ -8,7 +12,11 @@ const openjpegWasm = new URL( import { ImageFrame, WebWorkerDecodeConfig } from '../../types'; -const local = { +const local: { + codec: OpenJpegModule; + decoder: J2KDecoder; + decodeConfig: WebWorkerDecodeConfig; +} = { codec: undefined, decoder: undefined, decodeConfig: {} as WebWorkerDecodeConfig, @@ -26,7 +34,7 @@ export function initialize( const openJpegModule = openJpegFactory({ locateFile: (f) => { if (f.endsWith('.wasm')) { - return openjpegWasm; + return openjpegWasm.toString(); } return f; diff --git a/packages/dicomImageLoader/src/shared/decoders/decodeJPEGBaseline8Bit.ts b/packages/dicomImageLoader/src/shared/decoders/decodeJPEGBaseline8Bit.ts index 76715e7720..aff5618cba 100644 --- a/packages/dicomImageLoader/src/shared/decoders/decodeJPEGBaseline8Bit.ts +++ b/packages/dicomImageLoader/src/shared/decoders/decodeJPEGBaseline8Bit.ts @@ -1,6 +1,9 @@ -import { ByteArray } from 'dicom-parser'; - +import type { + LibJpegTurbo8Bit, + OpenJpegModule, +} from '@cornerstonejs/codec-libjpeg-turbo-8bit/dist/libjpegturbowasm_decode'; import libjpegTurboFactory from '@cornerstonejs/codec-libjpeg-turbo-8bit/dist/libjpegturbowasm_decode'; +import { ByteArray } from 'dicom-parser'; const libjpegTurboWasm = new URL( '@cornerstonejs/codec-libjpeg-turbo-8bit/dist/libjpegturbowasm_decode.wasm', @@ -9,7 +12,10 @@ const libjpegTurboWasm = new URL( import { ImageFrame } from '../../types'; -const local = { +const local: { + codec: OpenJpegModule; + decoder: LibJpegTurbo8Bit; +} = { codec: undefined, decoder: undefined, }; @@ -22,7 +28,7 @@ function initLibjpegTurbo(): Promise { const libjpegTurboModule = libjpegTurboFactory({ locateFile: (f) => { if (f.endsWith('.wasm')) { - return libjpegTurboWasm; + return libjpegTurboWasm.toString(); } return f; diff --git a/packages/dicomImageLoader/src/shared/decoders/decodeJPEGLS.ts b/packages/dicomImageLoader/src/shared/decoders/decodeJPEGLS.ts index 9db9712453..514b66ce0a 100644 --- a/packages/dicomImageLoader/src/shared/decoders/decodeJPEGLS.ts +++ b/packages/dicomImageLoader/src/shared/decoders/decodeJPEGLS.ts @@ -1,3 +1,7 @@ +import type { + CharlsModule, + JpegLSDecoder, +} from '@cornerstonejs/codec-charls/dist/charlswasm_decode'; import charlsFactory from '@cornerstonejs/codec-charls/dist/charlswasm_decode'; const charlsWasm = new URL( @@ -8,7 +12,11 @@ const charlsWasm = new URL( import { ByteArray } from 'dicom-parser'; import { ImageFrame, WebWorkerDecodeConfig } from '../../types'; -const local = { +const local: { + codec: CharlsModule; + decoder: JpegLSDecoder; + decodeConfig: WebWorkerDecodeConfig; +} = { codec: undefined, decoder: undefined, decodeConfig: {} as WebWorkerDecodeConfig, @@ -32,7 +40,7 @@ export function initialize( const charlsModule = charlsFactory({ locateFile: (f) => { if (f.endsWith('.wasm')) { - return charlsWasm; + return charlsWasm.toString(); } return f; diff --git a/yarn.lock b/yarn.lock index 66b09117f5..392311a790 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5520,6 +5520,11 @@ "@types/got" "^8" "@types/node" "*" +"@types/emscripten@^1.39.6": + version "1.39.6" + resolved "https://registry.yarnpkg.com/@types/emscripten/-/emscripten-1.39.6.tgz#698b90fe60d44acf93c31064218fbea93fbfd85a" + integrity sha512-H90aoynNhhkQP6DRweEjJp5vfUVdIj7tdPLsu7pq89vODD/lcugKfZOsfgwpvM6XUewEp2N5dCg1Uf3Qe55Dcg== + "@types/eslint-scope@^3.7.0", "@types/eslint-scope@^3.7.3": version "3.7.3" resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.3.tgz#125b88504b61e3c8bc6f870882003253005c3224" From d8a48f5c1ecdba1c4b1390e6b6f780bef376dabd Mon Sep 17 00:00:00 2001 From: James Manners Date: Fri, 24 Feb 2023 10:34:44 +1100 Subject: [PATCH 3/3] [dicom-image-loader] relocate WASM types --- .../src/{shared/decoders => types}/codec-charls.d.ts | 0 .../src/{shared/decoders => types}/codec-libjpeg-turbo-8bit.d.ts | 0 .../src/{shared/decoders => types}/codec-openjpeg.d.ts | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename packages/dicomImageLoader/src/{shared/decoders => types}/codec-charls.d.ts (100%) rename packages/dicomImageLoader/src/{shared/decoders => types}/codec-libjpeg-turbo-8bit.d.ts (100%) rename packages/dicomImageLoader/src/{shared/decoders => types}/codec-openjpeg.d.ts (100%) diff --git a/packages/dicomImageLoader/src/shared/decoders/codec-charls.d.ts b/packages/dicomImageLoader/src/types/codec-charls.d.ts similarity index 100% rename from packages/dicomImageLoader/src/shared/decoders/codec-charls.d.ts rename to packages/dicomImageLoader/src/types/codec-charls.d.ts diff --git a/packages/dicomImageLoader/src/shared/decoders/codec-libjpeg-turbo-8bit.d.ts b/packages/dicomImageLoader/src/types/codec-libjpeg-turbo-8bit.d.ts similarity index 100% rename from packages/dicomImageLoader/src/shared/decoders/codec-libjpeg-turbo-8bit.d.ts rename to packages/dicomImageLoader/src/types/codec-libjpeg-turbo-8bit.d.ts diff --git a/packages/dicomImageLoader/src/shared/decoders/codec-openjpeg.d.ts b/packages/dicomImageLoader/src/types/codec-openjpeg.d.ts similarity index 100% rename from packages/dicomImageLoader/src/shared/decoders/codec-openjpeg.d.ts rename to packages/dicomImageLoader/src/types/codec-openjpeg.d.ts