js-dicom
Version:
this is js-dicom
161 lines (126 loc) • 4.78 kB
JavaScript
function decodeJpx (imageFrame, pixelData) {
const jpxImage = new JpxImage();
jpxImage.parse(pixelData);
const tileCount = jpxImage.tiles.length;
if (tileCount !== 1) {
throw `JPEG2000 decoder returned a tileCount of ${tileCount}, when 1 is expected`;
}
imageFrame.columns = jpxImage.width;
imageFrame.rows = jpxImage.height;
imageFrame.pixelData = jpxImage.tiles[0].items;
return imageFrame;
}
let openJPEG;
function decodeOpenJPEG (data, bytesPerPixel, signed) {
const dataPtr = openJPEG._malloc(data.length);
openJPEG.writeArrayToMemory(data, dataPtr);
// create param outpout
const imagePtrPtr = openJPEG._malloc(4);
const imageSizePtr = openJPEG._malloc(4);
const imageSizeXPtr = openJPEG._malloc(4);
const imageSizeYPtr = openJPEG._malloc(4);
const imageSizeCompPtr = openJPEG._malloc(4);
const t0 = Date.now();
const ret = openJPEG.ccall('jp2_decode', 'number', ['number', 'number', 'number', 'number', 'number', 'number', 'number'],
[dataPtr, data.length, imagePtrPtr, imageSizePtr, imageSizeXPtr, imageSizeYPtr, imageSizeCompPtr]);
// add num vomp..etc
if (ret !== 0) {
console.log('[opj_decode] decoding failed!');
openJPEG._free(dataPtr);
openJPEG._free(openJPEG.getValue(imagePtrPtr, '*'));
openJPEG._free(imageSizeXPtr);
openJPEG._free(imageSizeYPtr);
openJPEG._free(imageSizePtr);
openJPEG._free(imageSizeCompPtr);
return undefined;
}
const imagePtr = openJPEG.getValue(imagePtrPtr, '*');
const image = {
length: openJPEG.getValue(imageSizePtr, 'i32'),
sx: openJPEG.getValue(imageSizeXPtr, 'i32'),
sy: openJPEG.getValue(imageSizeYPtr, 'i32'),
nbChannels: openJPEG.getValue(imageSizeCompPtr, 'i32'), // hard coded for now
perf_timetodecode: undefined,
pixelData: undefined
};
// Copy the data from the EMSCRIPTEN heap into the correct type array
const length = image.sx * image.sy * image.nbChannels;
const src32 = new Int32Array(openJPEG.HEAP32.buffer, imagePtr, length);
if (bytesPerPixel === 1) {
if (Uint8Array.from) {
image.pixelData = Uint8Array.from(src32);
} else {
image.pixelData = new Uint8Array(length);
for (let i = 0; i < length; i++) {
image.pixelData[i] = src32[i];
}
}
} else if (signed) {
if (Int16Array.from) {
image.pixelData = Int16Array.from(src32);
} else {
image.pixelData = new Int16Array(length);
for (let i = 0; i < length; i++) {
image.pixelData[i] = src32[i];
}
}
} else if (Uint16Array.from) {
image.pixelData = Uint16Array.from(src32);
} else {
image.pixelData = new Uint16Array(length);
for (let i = 0; i < length; i++) {
image.pixelData[i] = src32[i];
}
}
const t1 = Date.now();
image.perf_timetodecode = t1 - t0;
// free
openJPEG._free(dataPtr);
openJPEG._free(imagePtrPtr);
openJPEG._free(imagePtr);
openJPEG._free(imageSizePtr);
openJPEG._free(imageSizeXPtr);
openJPEG._free(imageSizeYPtr);
openJPEG._free(imageSizeCompPtr);
return image;
}
function decodeOpenJpeg2000 (imageFrame, pixelData) {
const bytesPerPixel = imageFrame.bitsAllocated <= 8 ? 1 : 2;
const signed = imageFrame.pixelRepresentation === 1;
const image = decodeOpenJPEG(pixelData, bytesPerPixel, signed);
imageFrame.columns = image.sx;
imageFrame.rows = image.sy;
imageFrame.pixelData = image.pixelData;
if (image.nbChannels > 1) {
imageFrame.photometricInterpretation = 'RGB';
}
return imageFrame;
}
function initializeJPEG2000 (decodeConfig) {
// check to make sure codec is loaded
if (!decodeConfig.usePDFJS) {
if (typeof OpenJPEG === 'undefined') {
throw 'OpenJPEG decoder not loaded';
}
}
if (!openJPEG) {
openJPEG = OpenJPEG();
if (!openJPEG || !openJPEG._jp2_decode) {
throw 'OpenJPEG failed to initialize';
}
}
}
function decodeJPEG2000 (imageFrame, pixelData, decodeConfig, options) {
options = options || {};
initializeJPEG2000(decodeConfig);
if (options.usePDFJS || decodeConfig.usePDFJS) {
// OHIF image-JPEG2000 https://github.com/OHIF/image-JPEG2000
// console.log('PDFJS')
return decodeJpx(imageFrame, pixelData);
}
// OpenJPEG2000 https://github.com/jpambrun/openjpeg
// console.log('OpenJPEG')
return decodeOpenJpeg2000(imageFrame, pixelData);
}
export default decodeJPEG2000;
export { initializeJPEG2000 };