UNPKG

@cornerstonejs/dicom-image-loader

Version:

Cornerstone Image Loader for DICOM WADO-URI and WADO-RS and Local file

94 lines (93 loc) 3.68 kB
import openJpegFactory from '@cornerstonejs/codec-openjpeg/decodewasmjs'; const openjpegWasm = new URL('@cornerstonejs/codec-openjpeg/decodewasm', import.meta.url); const local = { codec: undefined, decoder: undefined, decodeConfig: {}, }; export function initialize(decodeConfig) { local.decodeConfig = decodeConfig; if (local.codec) { return Promise.resolve(); } const openJpegModule = openJpegFactory({ locateFile: (f) => { if (f.endsWith('.wasm')) { return openjpegWasm.toString(); } return f; }, }); return new Promise((resolve, reject) => { openJpegModule.then((instance) => { local.codec = instance; local.decoder = new instance.J2KDecoder(); resolve(); }, reject); }); } async function decodeAsync(compressedImageFrame, imageInfo) { await initialize(); const decoder = local.decoder; const encodedBufferInWASM = decoder.getEncodedBuffer(compressedImageFrame.length); encodedBufferInWASM.set(compressedImageFrame); decoder.decode(); const frameInfo = decoder.getFrameInfo(); const decodedBufferInWASM = decoder.getDecodedBuffer(); const imageFrame = new Uint8Array(decodedBufferInWASM.length); imageFrame.set(decodedBufferInWASM); const imageOffset = `x: ${decoder.getImageOffset().x}, y: ${decoder.getImageOffset().y}`; const numDecompositions = decoder.getNumDecompositions(); const numLayers = decoder.getNumLayers(); const progessionOrder = ['unknown', 'LRCP', 'RLCP', 'RPCL', 'PCRL', 'CPRL'][decoder.getProgressionOrder() + 1]; const reversible = decoder.getIsReversible(); const blockDimensions = `${decoder.getBlockDimensions().width} x ${decoder.getBlockDimensions().height}`; const tileSize = `${decoder.getTileSize().width} x ${decoder.getTileSize().height}`; const tileOffset = `${decoder.getTileOffset().x}, ${decoder.getTileOffset().y}`; const colorTransform = decoder.getColorSpace(); const decodedSize = `${decodedBufferInWASM.length.toLocaleString()} bytes`; const compressionRatio = `${(decodedBufferInWASM.length / encodedBufferInWASM.length).toFixed(2)}:1`; const encodedImageInfo = { columns: frameInfo.width, rows: frameInfo.height, bitsPerPixel: frameInfo.bitsPerSample, signed: frameInfo.isSigned, bytesPerPixel: imageInfo.bytesPerPixel, componentsPerPixel: frameInfo.componentCount, }; const pixelData = getPixelData(frameInfo, decodedBufferInWASM); const encodeOptions = { imageOffset, numDecompositions, numLayers, progessionOrder, reversible, blockDimensions, tileSize, tileOffset, colorTransform, decodedSize, compressionRatio, }; return { ...imageInfo, pixelData, imageInfo: encodedImageInfo, encodeOptions, ...encodeOptions, ...encodedImageInfo, }; } function getPixelData(frameInfo, decodedBuffer) { if (frameInfo.bitsPerSample > 8) { if (frameInfo.isSigned) { return new Int16Array(decodedBuffer.buffer, decodedBuffer.byteOffset, decodedBuffer.byteLength / 2); } return new Uint16Array(decodedBuffer.buffer, decodedBuffer.byteOffset, decodedBuffer.byteLength / 2); } if (frameInfo.isSigned) { return new Int8Array(decodedBuffer.buffer, decodedBuffer.byteOffset, decodedBuffer.byteLength); } return new Uint8Array(decodedBuffer.buffer, decodedBuffer.byteOffset, decodedBuffer.byteLength); } export default decodeAsync;