UNPKG

cornerstone-wado-image-loader

Version:
354 lines (283 loc) 13.3 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>shared/decodeImageFrame.js - Documentation</title> <script src="scripts/prettify/prettify.js"></script> <script src="scripts/prettify/lang-css.js"></script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc.css"> <script src="scripts/nav.js" defer></script> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> <input type="checkbox" id="nav-trigger" class="nav-trigger" /> <label for="nav-trigger" class="navicon-button x"> <div class="navicon"></div> </label> <label for="nav-trigger" class="overlay"></label> <nav > <h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#addTask">addTask</a></li><li><a href="global.html#arrayBufferToString">arrayBufferToString</a></li><li><a href="global.html#cacheSizeInBytes">cacheSizeInBytes</a></li><li><a href="global.html#cancelTask">cancelTask</a></li><li><a href="global.html#decodeAsync">decodeAsync</a></li><li><a href="global.html#decodeImageFrame">decodeImageFrame</a></li><li><a href="global.html#extractOrientationFromDataset">extractOrientationFromDataset</a></li><li><a href="global.html#extractOrientationFromMetadata">extractOrientationFromMetadata</a></li><li><a href="global.html#extractOrientationFromNMMultiframeDataset">extractOrientationFromNMMultiframeDataset</a></li><li><a href="global.html#extractOrientationFromNMMultiframeMetadata">extractOrientationFromNMMultiframeMetadata</a></li><li><a href="global.html#extractPositionFromDataset">extractPositionFromDataset</a></li><li><a href="global.html#extractPositionFromMetadata">extractPositionFromMetadata</a></li><li><a href="global.html#extractPositionFromNMMultiframeDataset">extractPositionFromNMMultiframeDataset</a></li><li><a href="global.html#extractPositionFromNMMultiframeMetadata">extractPositionFromNMMultiframeMetadata</a></li><li><a href="global.html#extractSliceThicknessFromDataset">extractSliceThicknessFromDataset</a></li><li><a href="global.html#extractSpacingFromDataset">extractSpacingFromDataset</a></li><li><a href="global.html#framesAreFragmented">framesAreFragmented</a></li><li><a href="global.html#getImageTypeSubItemFromDataset">getImageTypeSubItemFromDataset</a></li><li><a href="global.html#getImageTypeSubItemFromMetadata">getImageTypeSubItemFromMetadata</a></li><li><a href="global.html#getMinMax">getMinMax</a></li><li><a href="global.html#getNumberString">getNumberString</a></li><li><a href="global.html#getNumberValues">getNumberValues</a></li><li><a href="global.html#getStatistics">getStatistics</a></li><li><a href="global.html#getTransferSyntaxForContentType">getTransferSyntaxForContentType</a></li><li><a href="global.html#getUncompressedImageFrame">getUncompressedImageFrame</a></li><li><a href="global.html#getValue">getValue</a></li><li><a href="global.html#handleMessageFromWorker">handleMessageFromWorker</a></li><li><a href="global.html#handler">handler</a></li><li><a href="global.html#initialize">initialize</a></li><li><a href="global.html#loadCodecs">loadCodecs</a></li><li><a href="global.html#loadWebWorkerTask">loadWebWorkerTask</a></li><li><a href="global.html#registerLoaders">registerLoaders</a></li><li><a href="global.html#registerTaskHandler">registerTaskHandler</a></li><li><a href="global.html#removeAFromRGBA">removeAFromRGBA</a></li><li><a href="global.html#setPixelDataType">setPixelDataType</a></li><li><a href="global.html#setTaskPriority">setTaskPriority</a></li><li><a href="global.html#spawnWebWorker">spawnWebWorker</a></li><li><a href="global.html#startTaskOnWebWorker">startTaskOnWebWorker</a></li><li><a href="global.html#terminate">terminate</a></li><li><a href="global.html#unpackBinaryFrame">unpackBinaryFrame</a></li></ul> </nav> <div id="main"> <h1 class="page-title">shared/decodeImageFrame.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>/* eslint-disable complexity */ import decodeLittleEndian from './decoders/decodeLittleEndian.js'; import decodeBigEndian from './decoders/decodeBigEndian.js'; import decodeRLE from './decoders/decodeRLE.js'; import decodeJPEGBaseline8Bit from './decoders/decodeJPEGBaseline8Bit.js'; // import decodeJPEGBaseline12Bit from './decoders/decodeJPEGBaseline12Bit.js'; import decodeJPEGBaseline12Bit from './decoders/decodeJPEGBaseline12Bit-js.js'; import decodeJPEGLossless from './decoders/decodeJPEGLossless.js'; import decodeJPEGLS from './decoders/decodeJPEGLS.js'; import decodeJPEG2000 from './decoders/decodeJPEG2000.js'; import decodeHTJ2K from './decoders/decodeHTJ2K.js'; import scaleArray from './scaling/scaleArray.js'; /** * Decodes the provided image frame. * This is an async function return the result, or you can provide an optional * callbackFn that is called with the results. */ async function decodeImageFrame( imageFrame, transferSyntax, pixelData, decodeConfig, options, callbackFn ) { const start = new Date().getTime(); let decodePromise = null; let opts; switch (transferSyntax) { case '1.2.840.10008.1.2': case '1.2.840.10008.1.2.1': // Implicit or Explicit VR Little Endian decodePromise = decodeLittleEndian(imageFrame, pixelData); break; case '1.2.840.10008.1.2.2': // Explicit VR Big Endian (retired) decodePromise = decodeBigEndian(imageFrame, pixelData); break; case '1.2.840.10008.1.2.1.99': // Deflate transfer syntax (deflated by dicomParser) decodePromise = decodeLittleEndian(imageFrame, pixelData); break; case '1.2.840.10008.1.2.5': // RLE Lossless decodePromise = decodeRLE(imageFrame, pixelData); break; case '1.2.840.10008.1.2.4.50': // JPEG Baseline lossy process 1 (8 bit) opts = { ...imageFrame, }; decodePromise = decodeJPEGBaseline8Bit(pixelData, opts); break; case '1.2.840.10008.1.2.4.51': // JPEG Baseline lossy process 2 &amp; 4 (12 bit) // opts = { // ...imageFrame, // }; // decodePromise = decodeJPEGBaseline12Bit(pixelData, opts); //throw new Error('Currently unsupported: 1.2.840.10008.1.2.4.51'); decodePromise = decodeJPEGBaseline12Bit(imageFrame, pixelData); break; case '1.2.840.10008.1.2.4.57': // JPEG Lossless, Nonhierarchical (Processes 14) decodePromise = decodeJPEGLossless(imageFrame, pixelData); break; case '1.2.840.10008.1.2.4.70': // JPEG Lossless, Nonhierarchical (Processes 14 [Selection 1]) decodePromise = decodeJPEGLossless(imageFrame, pixelData); break; case '1.2.840.10008.1.2.4.80': // JPEG-LS Lossless Image Compression opts = { signed: imageFrame.pixelRepresentation === 1, // imageFrame.signed, // shouldn't need... bytesPerPixel: imageFrame.bitsAllocated &lt;= 8 ? 1 : 2, ...imageFrame, }; decodePromise = decodeJPEGLS(pixelData, opts); break; case '1.2.840.10008.1.2.4.81': // JPEG-LS Lossy (Near-Lossless) Image Compression opts = { signed: false, // imageFrame.signed, // shouldn't need... bytesPerPixel: imageFrame.bitsAllocated &lt;= 8 ? 1 : 2, ...imageFrame, }; decodePromise = decodeJPEGLS(pixelData, opts); break; case '1.2.840.10008.1.2.4.90': opts = { ...imageFrame, }; // JPEG 2000 Lossless // imageFrame, pixelData, decodeConfig, options decodePromise = decodeJPEG2000(pixelData, opts); break; case '1.2.840.10008.1.2.4.91': // JPEG 2000 Lossy opts = { ...imageFrame, }; // JPEG 2000 Lossy // imageFrame, pixelData, decodeConfig, options decodePromise = decodeJPEG2000(pixelData, opts); break; case '3.2.840.10008.1.2.4.96': // HTJ2K opts = { ...imageFrame, }; decodePromise = decodeHTJ2K(pixelData, opts); break; default: throw new Error(`no decoder for transfer syntax ${transferSyntax}`); } /* Don't know if these work... // JPEG 2000 Part 2 Multicomponent Image Compression (Lossless Only) else if(transferSyntax === "1.2.840.10008.1.2.4.92") { return decodeJPEG2000(dataSet, frame); } // JPEG 2000 Part 2 Multicomponent Image Compression else if(transferSyntax === "1.2.840.10008.1.2.4.93") { return decodeJPEG2000(dataSet, frame); } */ if (!decodePromise) { throw new Error('decodePromise not defined'); } const decodedFrame = await decodePromise; const postProcessed = postProcessDecodedPixels( decodedFrame, options, start, decodeConfig ); // Call the callbackFn to agree with older arguments callbackFn?.(postProcessed); return postProcessed; } function postProcessDecodedPixels(imageFrame, options, start, decodeConfig) { const { use16BitDataType } = decodeConfig || {}; const shouldShift = imageFrame.pixelRepresentation !== undefined &amp;&amp; imageFrame.pixelRepresentation === 1; const shift = shouldShift &amp;&amp; imageFrame.bitsStored !== undefined ? 32 - imageFrame.bitsStored : undefined; if (shouldShift &amp;&amp; shift !== undefined) { for (let i = 0; i &lt; imageFrame.pixelData.length; i++) { // eslint-disable-next-line no-bitwise imageFrame.pixelData[i] = (imageFrame.pixelData[i] &lt;&lt; shift) >> shift; } } // Cache the pixelData reference quickly incase we want to set a targetBuffer _and_ scale. let pixelDataArray = imageFrame.pixelData; imageFrame.pixelDataLength = imageFrame.pixelData.length; if (options.targetBuffer) { let offset, length; // If we have a target buffer, write to that instead. This helps reduce memory duplication. ({ offset, length } = options.targetBuffer); const { arrayBuffer, type } = options.targetBuffer; let TypedArrayConstructor; if (offset === null || offset === undefined) { offset = 0; } if ((length === null || length === undefined) &amp;&amp; offset !== 0) { length = imageFrame.pixelDataLength - offset; } else if (length === null || length === undefined) { length = imageFrame.pixelDataLength; } switch (type) { case 'Uint8Array': TypedArrayConstructor = Uint8Array; break; case use16BitDataType &amp;&amp; 'Uint16Array': TypedArrayConstructor = Uint16Array; break; case use16BitDataType &amp;&amp; 'Int16Array': TypedArrayConstructor = Int16Array; break; case 'Float32Array': TypedArrayConstructor = Float32Array; break; default: throw new Error('target array for image does not have a valid type.'); } const imageFramePixelData = imageFrame.pixelData; if (length !== imageFramePixelData.length) { throw new Error( `target array for image does not have the same length (${length}) as the decoded image length (${imageFramePixelData.length}).` ); } // TypedArray.Set is api level and ~50x faster than copying elements even for // Arrays of different types, which aren't simply memcpy ops. let typedArray; if (arrayBuffer) { typedArray = new TypedArrayConstructor(arrayBuffer, offset, length); } else { typedArray = new TypedArrayConstructor(length); } typedArray.set(imageFramePixelData, 0); // If need to scale, need to scale correct array. pixelDataArray = typedArray; } if (options.preScale.enabled) { const scalingParameters = options.preScale.scalingParameters; if (!scalingParameters) { throw new Error( 'options.preScale.scalingParameters must be defined if preScale.enabled is true, and scalingParameters cannot be derived from the metadata providers.' ); } const { rescaleSlope, rescaleIntercept } = scalingParameters; if ( typeof rescaleSlope === 'number' &amp;&amp; typeof rescaleIntercept === 'number' ) { if (scaleArray(pixelDataArray, scalingParameters)) { imageFrame.preScale = { ...options.preScale, scaled: true, }; } } } // Handle cases where the targetBuffer is not backed by a SharedArrayBuffer if ( options.targetBuffer &amp;&amp; (!options.targetBuffer.arrayBuffer || options.targetBuffer.arrayBuffer instanceof ArrayBuffer) ) { imageFrame.pixelData = pixelDataArray; } const end = new Date().getTime(); imageFrame.decodeTimeInMS = end - start; return imageFrame; } export default decodeImageFrame; </code></pre> </article> </section> </div> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.6.7</a> using the <a href="https://github.com/clenemt/docdash">docdash</a> theme. </footer> <script>prettyPrint();</script> <script src="scripts/polyfill.js"></script> <script src="scripts/linenumber.js"></script> </body> </html>