Update Cornerstone WADO Image Loader

This commit is contained in:
Erik Ziegler committed 2017-04-04 10:50:00 +02:00
1 parent b1e5cab20c
commit 62fccc5928
3 files changed
+105 -3661

No files matched your search

@@ -1,4 +1,4 @@
/*! cornerstone-wado-image-loader - v0.14.2 - 2017-02-22 | (c) 2016 Chris Hafey | https://github.com/chafey/cornerstoneWADOImageLoader */
/*! cornerstone-wado-image-loader - v0.14.3 - 2017-04-04 | (c) 2016 Chris Hafey | https://github.com/chafey/cornerstoneWADOImageLoader */
//
// This is a cornerstone image loader for WADO-URI requests.
//
@@ -323,7 +323,7 @@ if(typeof cornerstoneWADOImageLoader === 'undefined'){
}
else if(imageFrame.photometricInterpretation === "YBR_FULL" )
{
convertRGB(imageFrame, rgbaBuffer);
convertYBRFull(imageFrame, rgbaBuffer);
}
else
{
@@ -447,12 +447,10 @@ if(typeof cornerstoneWADOImageLoader === 'undefined'){
image.render = cornerstone.renderGrayscaleImage;
}
// calculate min/max if not supplied
if(image.minPixelValue === undefined || image.maxPixelValue === undefined) {
var minMax = cornerstoneWADOImageLoader.getMinMax(imageFrame.pixelData);
image.minPixelValue = minMax.min;
image.maxPixelValue = minMax.max;
}
// Calculate min/max pixel values (do not trust DICOM Headers)
var minMax = cornerstoneWADOImageLoader.getMinMax(imageFrame.pixelData);
image.minPixelValue = minMax.min;
image.maxPixelValue = minMax.max;
// Modality LUT
if(modalityLutModule.modalityLUTSequence &&
@@ -929,7 +927,7 @@ if(typeof cornerstoneWADOImageLoader === 'undefined'){
// TODO: load bulk data items that we might need
var mediaType = 'multipart/related; type=application/octet-stream'; // 'image/dicom+jp2';
var mediaType = 'multipart/related; type="application/octet-stream"'; // 'image/dicom+jp2';
// get the pixel data from the server
cornerstoneWADOImageLoader.wadors.getPixelData(uri, imageId, mediaType).then(function(result) {
@@ -1268,7 +1266,15 @@ if(typeof cornerstoneWADOImageLoader === 'undefined'){
var loadDeferred = $.Deferred();
promise.then(function(dicomPart10AsArrayBuffer/*, xhr*/) {
var byteArray = new Uint8Array(dicomPart10AsArrayBuffer);
var dataSet = dicomParser.parseDicom(byteArray);
// Reject the promise if parsing the dicom file fails
var dataSet;
try {
dataSet = dicomParser.parseDicom(byteArray);
} catch(error) {
loadDeferred.reject(error);
return;
}
loadedDataSets[uri] = {
dataSet: dataSet,
@@ -1415,6 +1421,12 @@ if(typeof cornerstoneWADOImageLoader === 'undefined'){
throw 'frame exceeds size of pixelData';
}
return new Uint8Array(dataSet.byteArray.buffer, frameOffset,pixelsPerFrame * 2);
} else if (bitsAllocated === 1) {
frameOffset = pixelDataOffset + frameIndex * pixelsPerFrame * 0.125;
if(frameOffset >= dataSet.byteArray.length) {
throw 'frame exceeds size of pixelData';
}
return cornerstoneWADOImageLoader.wadouri.unpackBinaryFrame(dataSet.byteArray, frameOffset, pixelsPerFrame);
}
throw 'unsupported pixel format';
@@ -1788,6 +1800,40 @@ if(typeof cornerstoneWADOImageLoader === 'undefined'){
cornerstoneWADOImageLoader.wadouri.parseImageId = parseImageId;
}(cornerstoneWADOImageLoader));
/**
* Function to deal with unpacking a binary frame
*/
(function ($, cornerstone, cornerstoneWADOImageLoader) {
"use strict";
function isBitSet(byte, bitPos) {
return byte & (1 << bitPos);
}
function unpackBinaryFrame(byteArray, frameOffset, pixelsPerFrame) {
// Create a new pixel array given the image size
var pixelData = new Uint8Array(pixelsPerFrame);
for (var i = 0; i < pixelsPerFrame; i++) {
// Compute byte position
var bytePos = Math.floor(i / 8);
// Get the current byte
var byte = byteArray[bytePos + frameOffset];
// Bit position (0-7) within byte
var bitPos = (i % 8);
// Check whether bit at bitpos is set
pixelData[i] = isBitSet(byte, bitPos) ? 1 : 0;
}
return pixelData;
}
cornerstoneWADOImageLoader.wadouri.unpackBinaryFrame = unpackBinaryFrame;
}($, cornerstone, cornerstoneWADOImageLoader));
(function ($, cornerstoneWADOImageLoader) {
"use strict";
File diff suppressed because it is too large. Load diff
@@ -1,861 +1,2 @@
/*! cornerstone-wado-image-loader - v0.14.2 - 2017-02-22 | (c) 2016 Chris Hafey | https://github.com/chafey/cornerstoneWADOImageLoader */
cornerstoneWADOImageLoaderWebWorker = {
registerTaskHandler : undefined
};
(function () {
// an object of task handlers
var taskHandlers = {};
// Flag to ensure web worker is only initialized once
var initialized = false;
// the configuration object passed in when the web worker manager is initialized
var config;
/**
* Initialization function that loads additional web workers and initializes them
* @param data
*/
function initialize(data) {
//console.log('web worker initialize ', data.workerIndex);
// prevent initialization from happening more than once
if(initialized) {
return;
}
// save the config data
config = data.config;
// load any additional web worker tasks
if(data.config.webWorkerTaskPaths) {
for(var i=0; i < data.config.webWorkerTaskPaths.length; i++) {
self.importScripts(data.config.webWorkerTaskPaths[i]);
}
}
// initialize each task handler
Object.keys(taskHandlers).forEach(function(key) {
taskHandlers[key].initialize(config.taskConfiguration);
});
// tell main ui thread that we have completed initialization
self.postMessage({
taskType: 'initialize',
status: 'success',
result: {
},
workerIndex: data.workerIndex
});
initialized = true;
}
/**
* Function exposed to web worker tasks to register themselves
* @param taskHandler
*/
cornerstoneWADOImageLoaderWebWorker.registerTaskHandler = function(taskHandler) {
if(taskHandlers[taskHandler.taskType]) {
console.log('attempt to register duplicate task handler "', taskHandler.taskType, '"');
return false;
}
taskHandlers[taskHandler.taskType] = taskHandler;
if(initialized) {
taskHandler.initialize(config.taskConfiguration);
}
};
/**
* Function to load a new web worker task with updated configuration
* @param data
*/
function loadWebWorkerTask(data) {
config = data.config;
self.importScripts(data.sourcePath);
}
/**
* Web worker message handler - dispatches messages to the registered task handlers
* @param msg
*/
self.onmessage = function(msg) {
//console.log('web worker onmessage', msg.data);
// handle initialize message
if(msg.data.taskType === 'initialize') {
initialize(msg.data);
return;
}
// handle loadWebWorkerTask message
if(msg.data.taskType === 'loadWebWorkerTask') {
loadWebWorkerTask(msg.data);
return;
}
// dispatch the message if there is a handler registered for it
if(taskHandlers[msg.data.taskType]) {
taskHandlers[msg.data.taskType].handler(msg.data, function(result, transferList) {
self.postMessage({
taskType: msg.data.taskType,
status: 'success',
result: result,
workerIndex: msg.data.workerIndex
}, transferList);
});
return;
}
// not task handler registered - send a failure message back to ui thread
console.log('no task handler for ', msg.data.taskType);
console.log(taskHandlers);
self.postMessage({
taskType: msg.data.taskType,
status: 'failed - no task handler registered',
workerIndex: msg.data.workerIndex
});
};
}());
cornerstoneWADOImageLoader = {};
(function () {
// flag to ensure codecs are loaded only once
var codecsLoaded = false;
// the configuration object for the decodeTask
var decodeConfig;
/**
* Function to control loading and initializing the codecs
* @param config
*/
function loadCodecs(config) {
// prevent loading codecs more than once
if (codecsLoaded) {
return;
}
// Load the codecs
//console.time('loadCodecs');
self.importScripts(config.decodeTask.codecsPath);
codecsLoaded = true;
//console.timeEnd('loadCodecs');
// Initialize the codecs
if (config.decodeTask.initializeCodecsOnStartup) {
//console.time('initializeCodecs');
cornerstoneWADOImageLoader.initializeJPEG2000(config.decodeTask);
cornerstoneWADOImageLoader.initializeJPEGLS(config.decodeTask);
//console.timeEnd('initializeCodecs');
}
}
/**
* Task initialization function
*/
function decodeTaskInitialize(config) {
decodeConfig = config;
if (config.decodeTask.loadCodecsOnStartup) {
loadCodecs(config);
}
}
function calculateMinMax(imageFrame) {
if (imageFrame.smallestPixelValue !== undefined && imageFrame.largestPixelValue !== undefined) {
return;
}
var minMax = cornerstoneWADOImageLoader.getMinMax(imageFrame.pixelData);
imageFrame.smallestPixelValue = minMax.min;
imageFrame.largestPixelValue = minMax.max;
}
/**
* Task handler function
*/
function decodeTaskHandler(data, doneCallback) {
// Load the codecs if they aren't already loaded
loadCodecs(decodeConfig);
var imageFrame = data.data.imageFrame;
// convert pixel data from ArrayBuffer to Uint8Array since web workers support passing ArrayBuffers but
// not typed arrays
var pixelData = new Uint8Array(data.data.pixelData);
cornerstoneWADOImageLoader.decodeImageFrame(
imageFrame,
data.data.transferSyntax,
pixelData,
decodeConfig.decodeTask,
data.data.options);
calculateMinMax(imageFrame);
// convert from TypedArray to ArrayBuffer since web workers support passing ArrayBuffers but not
// typed arrays
imageFrame.pixelData = imageFrame.pixelData.buffer;
// invoke the callback with our result and pass the pixelData in the transferList to move it to
// UI thread without making a copy
doneCallback(imageFrame, [imageFrame.pixelData]);
}
// register our task
cornerstoneWADOImageLoaderWebWorker.registerTaskHandler({
taskType: 'decodeTask',
handler: decodeTaskHandler,
initialize: decodeTaskInitialize
});
}());
/**
*/
(function (cornerstoneWADOImageLoader) {
"use strict";
function decodeImageFrame(imageFrame, transferSyntax, pixelData, decodeConfig, options) {
var start = new Date().getTime();
// Implicit VR Little Endian
if(transferSyntax === "1.2.840.10008.1.2") {
imageFrame = cornerstoneWADOImageLoader.decodeLittleEndian(imageFrame, pixelData);
}
// Explicit VR Little Endian
else if(transferSyntax === "1.2.840.10008.1.2.1") {
imageFrame = cornerstoneWADOImageLoader.decodeLittleEndian(imageFrame, pixelData);
}
// Explicit VR Big Endian (retired)
else if (transferSyntax === "1.2.840.10008.1.2.2" ) {
imageFrame = cornerstoneWADOImageLoader.decodeBigEndian(imageFrame, pixelData);
}
// Deflate transfer syntax (deflated by dicomParser)
else if(transferSyntax === '1.2.840.10008.1.2.1.99') {
imageFrame = cornerstoneWADOImageLoader.decodeLittleEndian(imageFrame, pixelData);
}
// RLE Lossless
else if (transferSyntax === "1.2.840.10008.1.2.5" )
{
imageFrame = cornerstoneWADOImageLoader.decodeRLE(imageFrame, pixelData);
}
// JPEG Baseline lossy process 1 (8 bit)
else if (transferSyntax === "1.2.840.10008.1.2.4.50")
{
imageFrame = cornerstoneWADOImageLoader.decodeJPEGBaseline(imageFrame, pixelData);
}
// JPEG Baseline lossy process 2 & 4 (12 bit)
else if (transferSyntax === "1.2.840.10008.1.2.4.51")
{
imageFrame = cornerstoneWADOImageLoader.decodeJPEGBaseline(imageFrame, pixelData);
}
// JPEG Lossless, Nonhierarchical (Processes 14)
else if (transferSyntax === "1.2.840.10008.1.2.4.57")
{
imageFrame = cornerstoneWADOImageLoader.decodeJPEGLossless(imageFrame, pixelData);
}
// JPEG Lossless, Nonhierarchical (Processes 14 [Selection 1])
else if (transferSyntax === "1.2.840.10008.1.2.4.70" )
{
imageFrame = cornerstoneWADOImageLoader.decodeJPEGLossless(imageFrame, pixelData);
}
// JPEG-LS Lossless Image Compression
else if (transferSyntax === "1.2.840.10008.1.2.4.80" )
{
imageFrame = cornerstoneWADOImageLoader.decodeJPEGLS(imageFrame, pixelData);
}
// JPEG-LS Lossy (Near-Lossless) Image Compression
else if (transferSyntax === "1.2.840.10008.1.2.4.81" )
{
imageFrame = cornerstoneWADOImageLoader.decodeJPEGLS(imageFrame, pixelData);
}
// JPEG 2000 Lossless
else if (transferSyntax === "1.2.840.10008.1.2.4.90")
{
imageFrame = cornerstoneWADOImageLoader.decodeJPEG2000(imageFrame, pixelData, decodeConfig, options);
}
// JPEG 2000 Lossy
else if (transferSyntax === "1.2.840.10008.1.2.4.91")
{
imageFrame = cornerstoneWADOImageLoader.decodeJPEG2000(imageFrame, pixelData, decodeConfig, options);
}
/* 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 cornerstoneWADOImageLoader.decodeJPEG2000(dataSet, frame);
}
// JPEG 2000 Part 2 Multicomponent Image Compression
else if(transferSyntax === "1.2.840.10008.1.2.4.93")
{
return cornerstoneWADOImageLoader.decodeJPEG2000(dataSet, frame);
}
*/
else
{
if(console && console.log) {
console.log("Image cannot be decoded due to Unsupported transfer syntax " + transferSyntax);
}
throw "no decoder for transfer syntax " + transferSyntax;
}
var end = new Date().getTime();
imageFrame.decodeTimeInMS = end - start;
return imageFrame;
}
cornerstoneWADOImageLoader.decodeImageFrame = decodeImageFrame;
}(cornerstoneWADOImageLoader));
/**
*/
(function (cornerstoneWADOImageLoader) {
function swap16(val) {
return ((val & 0xFF) << 8)
| ((val >> 8) & 0xFF);
}
function decodeBigEndian(imageFrame, pixelData) {
if(imageFrame.bitsAllocated === 16) {
var arrayBuffer = pixelData.buffer;
var offset = pixelData.byteOffset;
var length = pixelData.length;
// if pixel data is not aligned on even boundary, shift it so we can create the 16 bit array
// buffers on it
if(offset % 2) {
arrayBuffer = arrayBuffer.slice(offset);
offset = 0;
}
if(imageFrame.pixelRepresentation === 0) {
imageFrame.pixelData = new Uint16Array(arrayBuffer, offset, length / 2);
} else {
imageFrame.pixelData = new Int16Array(arrayBuffer, offset, length / 2);
}
// Do the byte swap
for(var i=0; i < imageFrame.pixelData.length; i++) {
imageFrame[i] = swap16(imageFrame.pixelData[i]);
}
} else if(imageFrame.bitsAllocated === 8) {
imageFrame.pixelData = pixelData;
}
return imageFrame;
}
// module exports
cornerstoneWADOImageLoader.decodeBigEndian = decodeBigEndian;
}(cornerstoneWADOImageLoader));
(function (cornerstoneWADOImageLoader) {
"use strict";
function decodeJpx(imageFrame, pixelData) {
var jpxImage = new JpxImage();
jpxImage.parse(pixelData);
var 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;
}
var openJPEG;
function decodeOpenJPEG(data, bytesPerPixel, signed) {
var dataPtr = openJPEG._malloc(data.length);
openJPEG.writeArrayToMemory(data, dataPtr);
// create param outpout
var imagePtrPtr=openJPEG._malloc(4);
var imageSizePtr=openJPEG._malloc(4);
var imageSizeXPtr=openJPEG._malloc(4);
var imageSizeYPtr=openJPEG._malloc(4);
var imageSizeCompPtr=openJPEG._malloc(4);
var t0 = Date.now();
var 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;
}
var imagePtr = openJPEG.getValue(imagePtrPtr, '*')
var 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
var length = image.sx*image.sy*image.nbChannels;
var 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(var 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(var 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(var i=0; i < length; i++) {
image.pixelData[i] = src32[i];
}
}
}
}
var 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) {
var bytesPerPixel = imageFrame.bitsAllocated <= 8 ? 1 : 2;
var signed = imageFrame.pixelRepresentation === 1;
var 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);
} else {
// OpenJPEG2000 https://github.com/jpambrun/openjpeg
//console.log('OpenJPEG')
return decodeOpenJpeg2000(imageFrame, pixelData);
}
}
cornerstoneWADOImageLoader.decodeJPEG2000 = decodeJPEG2000;
cornerstoneWADOImageLoader.initializeJPEG2000 = initializeJPEG2000;
}(cornerstoneWADOImageLoader));
(function (cornerstoneWADOImageLoader) {
"use strict";
function decodeJPEGBaseline(imageFrame, pixelData)
{
// check to make sure codec is loaded
if(typeof JpegImage === 'undefined') {
throw 'No JPEG Baseline decoder loaded';
}
var jpeg = new JpegImage();
jpeg.parse(pixelData);
if(imageFrame.bitsAllocated === 8) {
imageFrame.pixelData = jpeg.getData(imageFrame.columns, imageFrame.rows);
return imageFrame;
}
else if(imageFrame.bitsAllocated === 16) {
imageFrame.pixelData = jpeg.getData16(imageFrame.columns, imageFrame.rows);
return imageFrame;
}
}
cornerstoneWADOImageLoader.decodeJPEGBaseline = decodeJPEGBaseline;
}(cornerstoneWADOImageLoader));
"use strict";
(function (cornerstoneWADOImageLoader) {
function decodeJPEGLossless(imageFrame, pixelData) {
// check to make sure codec is loaded
if(typeof jpeg === 'undefined' ||
typeof jpeg.lossless === 'undefined' ||
typeof jpeg.lossless.Decoder === 'undefined') {
throw 'No JPEG Lossless decoder loaded';
}
var byteOutput = imageFrame.bitsAllocated <= 8 ? 1 : 2;
//console.time('jpeglossless');
var buffer = pixelData.buffer;
var decoder = new jpeg.lossless.Decoder();
var decompressedData = decoder.decode(buffer, buffer.byteOffset, buffer.length, byteOutput);
//console.timeEnd('jpeglossless');
if (imageFrame.pixelRepresentation === 0) {
if (imageFrame.bitsAllocated === 16) {
imageFrame.pixelData = new Uint16Array(decompressedData.buffer);
return imageFrame;
} else {
// untested!
imageFrame.pixelData = new Uint8Array(decompressedData.buffer);
return imageFrame;
}
} else {
imageFrame.pixelData = new Int16Array(decompressedData.buffer);
return imageFrame;
}
}
// module exports
cornerstoneWADOImageLoader.decodeJPEGLossless = decodeJPEGLossless;
}(cornerstoneWADOImageLoader));
"use strict";
(function (cornerstoneWADOImageLoader) {
var charLS;
function jpegLSDecode(data, isSigned) {
// prepare input parameters
var dataPtr = charLS._malloc(data.length);
charLS.writeArrayToMemory(data, dataPtr);
// prepare output parameters
var imagePtrPtr=charLS._malloc(4);
var imageSizePtr=charLS._malloc(4);
var widthPtr=charLS._malloc(4);
var heightPtr=charLS._malloc(4);
var bitsPerSamplePtr=charLS._malloc(4);
var stridePtr=charLS._malloc(4);
var allowedLossyErrorPtr =charLS._malloc(4);
var componentsPtr=charLS._malloc(4);
var interleaveModePtr=charLS._malloc(4);
// Decode the image
var result = charLS.ccall(
'jpegls_decode',
'number',
['number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number', 'number'],
[dataPtr, data.length, imagePtrPtr, imageSizePtr, widthPtr, heightPtr, bitsPerSamplePtr, stridePtr, componentsPtr, allowedLossyErrorPtr, interleaveModePtr]
);
// Extract result values into object
var image = {
result : result,
width : charLS.getValue(widthPtr,'i32'),
height : charLS.getValue(heightPtr,'i32'),
bitsPerSample : charLS.getValue(bitsPerSamplePtr,'i32'),
stride : charLS.getValue(stridePtr,'i32'),
components : charLS.getValue(componentsPtr, 'i32'),
allowedLossyError : charLS.getValue(allowedLossyErrorPtr, 'i32'),
interleaveMode: charLS.getValue(interleaveModePtr, 'i32'),
pixelData: undefined
};
// Copy image from emscripten heap into appropriate array buffer type
var imagePtr = charLS.getValue(imagePtrPtr, '*');
if(image.bitsPerSample <= 8) {
image.pixelData = new Uint8Array(image.width * image.height * image.components);
image.pixelData.set(new Uint8Array(charLS.HEAP8.buffer, imagePtr, image.pixelData.length));
} else {
// I have seen 16 bit signed images, but I don't know if 16 bit unsigned is valid, hoping to get
// answer here:
// https://github.com/team-charls/charls/issues/14
if(isSigned) {
image.pixelData = new Int16Array(image.width * image.height * image.components);
image.pixelData.set(new Int16Array(charLS.HEAP16.buffer, imagePtr, image.pixelData.length));
} else {
image.pixelData = new Uint16Array(image.width * image.height * image.components);
image.pixelData.set(new Uint16Array(charLS.HEAP16.buffer, imagePtr, image.pixelData.length));
}
}
// free memory and return image object
charLS._free(dataPtr);
charLS._free(imagePtr);
charLS._free(imagePtrPtr);
charLS._free(imageSizePtr);
charLS._free(widthPtr);
charLS._free(heightPtr);
charLS._free(bitsPerSamplePtr);
charLS._free(stridePtr);
charLS._free(componentsPtr);
charLS._free(interleaveModePtr);
return image;
}
function initializeJPEGLS() {
// check to make sure codec is loaded
if(typeof CharLS === 'undefined') {
throw 'No JPEG-LS decoder loaded';
}
// Try to initialize CharLS
// CharLS https://github.com/chafey/charls
if(!charLS) {
charLS = CharLS();
if(!charLS || !charLS._jpegls_decode) {
throw 'JPEG-LS failed to initialize';
}
}
}
function decodeJPEGLS(imageFrame, pixelData)
{
initializeJPEGLS();
var image = jpegLSDecode(pixelData, imageFrame.pixelRepresentation === 1);
//console.log(image);
// throw error if not success or too much data
if(image.result !== 0 && image.result !== 6) {
throw 'JPEG-LS decoder failed to decode frame (error code ' + image.result + ')';
}
imageFrame.columns = image.width;
imageFrame.rows = image.height;
imageFrame.pixelData = image.pixelData;
return imageFrame;
}
// module exports
cornerstoneWADOImageLoader.decodeJPEGLS = decodeJPEGLS;
cornerstoneWADOImageLoader.initializeJPEGLS = initializeJPEGLS;
}(cornerstoneWADOImageLoader));
/**
*/
(function (cornerstoneWADOImageLoader) {
function decodeLittleEndian(imageFrame, pixelData) {
if(imageFrame.bitsAllocated === 16) {
var arrayBuffer = pixelData.buffer;
var offset = pixelData.byteOffset;
var length = pixelData.length;
// if pixel data is not aligned on even boundary, shift it so we can create the 16 bit array
// buffers on it
if(offset % 2) {
arrayBuffer = arrayBuffer.slice(offset);
offset = 0;
}
if(imageFrame.pixelRepresentation === 0) {
imageFrame.pixelData = new Uint16Array(arrayBuffer, offset, length / 2);
} else {
imageFrame.pixelData = new Int16Array(arrayBuffer, offset, length / 2);
}
} else if(imageFrame.bitsAllocated === 8) {
imageFrame.pixelData = pixelData;
}
return imageFrame;
}
// module exports
cornerstoneWADOImageLoader.decodeLittleEndian = decodeLittleEndian;
}(cornerstoneWADOImageLoader));
/**
*/
(function (cornerstoneWADOImageLoader) {
function decodeRLE(imageFrame, pixelData) {
if(imageFrame.bitsAllocated === 8) {
return decode8(imageFrame, pixelData);
} else if( imageFrame.bitsAllocated === 16) {
return decode16(imageFrame, pixelData);
} else {
throw 'unsupported pixel format for RLE'
}
}
function decode8(imageFrame, pixelData ) {
var frameData = pixelData;
var frameSize = imageFrame.rows * imageFrame.columns;
var outFrame = new ArrayBuffer(frameSize*imageFrame.samplesPerPixel);
var header=new DataView(frameData.buffer, frameData.byteOffset);
var data=new DataView( frameData.buffer, frameData.byteOffset );
var out=new DataView( outFrame );
var outIndex=0;
var numSegments = header.getInt32(0,true);
for( var s=0 ; s < numSegments ; ++s ) {
outIndex = s;
var inIndex=header.getInt32( (s+1)*4,true);
var maxIndex=header.getInt32( (s+2)*4,true);
if( maxIndex===0 )
maxIndex = frameData.length;
var endOfSegment = frameSize * numSegments;
while( inIndex < maxIndex ) {
var n=data.getInt8(inIndex++);
if( n >=0 && n <=127 ) {
// copy n bytes
for( var i=0 ; i < n+1 && outIndex < endOfSegment; ++i ) {
out.setInt8(outIndex, data.getInt8(inIndex++));
outIndex+=imageFrame.samplesPerPixel;
}
} else if( n<= -1 && n>=-127 ) {
var value=data.getInt8(inIndex++);
// run of n bytes
for( var j=0 ; j < -n+1 && outIndex < endOfSegment; ++j ) {
out.setInt8(outIndex, value );
outIndex+=imageFrame.samplesPerPixel;
}
} else if (n===-128)
; // do nothing
}
}
imageFrame.pixelData = new Uint8Array(outFrame);
return imageFrame;
}
function decode16( imageFrame, pixelData ) {
var frameData = pixelData;
var frameSize = imageFrame.rows * imageFrame.columns;
var outFrame = new ArrayBuffer(frameSize*imageFrame.samplesPerPixel*2);
var header=new DataView(frameData.buffer, frameData.byteOffset);
var data=new DataView( frameData.buffer, frameData.byteOffset );
var out=new DataView( outFrame );
var numSegments = header.getInt32(0,true);
for( var s=0 ; s < numSegments ; ++s ) {
var outIndex=0;
var highByte=( s===0 ? 1 : 0);
var inIndex=header.getInt32( (s+1)*4,true);
var maxIndex=header.getInt32( (s+2)*4,true);
if( maxIndex===0 )
maxIndex = frameData.length;
while( inIndex < maxIndex ) {
var n=data.getInt8(inIndex++);
if( n >=0 && n <=127 ) {
for( var i=0 ; i < n+1 && outIndex < frameSize ; ++i ) {
out.setInt8( (outIndex*2)+highByte, data.getInt8(inIndex++) );
outIndex++;
}
} else if( n<= -1 && n>=-127 ) {
var value=data.getInt8(inIndex++);
for( var j=0 ; j < -n+1 && outIndex < frameSize ; ++j ) {
out.setInt8( (outIndex*2)+highByte, value );
outIndex++;
}
} else if (n===-128)
; // do nothing
}
}
if(imageFrame.pixelRepresentation === 0) {
imageFrame.pixelData = new Uint16Array(outFrame);
} else {
imageFrame.pixelData = new Int16Array(outFrame);
}
return imageFrame;
}
// module exports
cornerstoneWADOImageLoader.decodeRLE = decodeRLE;
}(cornerstoneWADOImageLoader));
(function (cornerstoneWADOImageLoader) {
"use strict";
function getMinMax(storedPixelData)
{
// we always calculate the min max values since they are not always
// present in DICOM and we don't want to trust them anyway as cornerstone
// depends on us providing reliable values for these
var min = storedPixelData[0];
var max = storedPixelData[0];
var storedPixel;
var numPixels = storedPixelData.length;
for(var index = 1; index < numPixels; index++) {
storedPixel = storedPixelData[index];
min = Math.min(min, storedPixel);
max = Math.max(max, storedPixel);
}
return {
min: min,
max: max
};
}
// module exports
cornerstoneWADOImageLoader.getMinMax = getMinMax;
}(cornerstoneWADOImageLoader));
/*! cornerstone-wado-image-loader - v0.14.3 - 2017-04-04 | (c) 2014 Chris Hafey | https://github.com/chafey/cornerstoneWADOImageLoader */
cornerstoneWADOImageLoaderWebWorker={registerTaskHandler:void 0},function(){function a(a){if(!e){if(c=a.config,a.config.webWorkerTaskPaths)for(var b=0;b<a.config.webWorkerTaskPaths.length;b++)self.importScripts(a.config.webWorkerTaskPaths[b]);Object.keys(d).forEach(function(a){d[a].initialize(c.taskConfiguration)}),self.postMessage({taskType:"initialize",status:"success",result:{},workerIndex:a.workerIndex}),e=!0}}function b(a){c=a.config,self.importScripts(a.sourcePath)}var c,d={},e=!1;cornerstoneWADOImageLoaderWebWorker.registerTaskHandler=function(a){return d[a.taskType]?(console.log('attempt to register duplicate task handler "',a.taskType,'"'),!1):(d[a.taskType]=a,void(e&&a.initialize(c.taskConfiguration)))},self.onmessage=function(c){return"initialize"===c.data.taskType?void a(c.data):"loadWebWorkerTask"===c.data.taskType?void b(c.data):d[c.data.taskType]?void d[c.data.taskType].handler(c.data,function(a,b){self.postMessage({taskType:c.data.taskType,status:"success",result:a,workerIndex:c.data.workerIndex},b)}):(console.log("no task handler for ",c.data.taskType),console.log(d),void self.postMessage({taskType:c.data.taskType,status:"failed - no task handler registered",workerIndex:c.data.workerIndex}))}}(),cornerstoneWADOImageLoader={},function(){function a(a){f||(self.importScripts(a.decodeTask.codecsPath),f=!0,a.decodeTask.initializeCodecsOnStartup&&(cornerstoneWADOImageLoader.initializeJPEG2000(a.decodeTask),cornerstoneWADOImageLoader.initializeJPEGLS(a.decodeTask)))}function b(b){e=b,b.decodeTask.loadCodecsOnStartup&&a(b)}function c(a){var b=cornerstoneWADOImageLoader.getMinMax(a.pixelData);a.smallestPixelValue=b.min,a.largestPixelValue=b.max}function d(b,d){a(e);var f=b.data.imageFrame,g=new Uint8Array(b.data.pixelData);cornerstoneWADOImageLoader.decodeImageFrame(f,b.data.transferSyntax,g,e.decodeTask,b.data.options),c(f),f.pixelData=f.pixelData.buffer,d(f,[f.pixelData])}var e,f=!1;cornerstoneWADOImageLoaderWebWorker.registerTaskHandler({taskType:"decodeTask",handler:d,initialize:b})}(),function(a){"use strict";function b(b,c,d,e,f){var g=(new Date).getTime();if("1.2.840.10008.1.2"===c)b=a.decodeLittleEndian(b,d);else if("1.2.840.10008.1.2.1"===c)b=a.decodeLittleEndian(b,d);else if("1.2.840.10008.1.2.2"===c)b=a.decodeBigEndian(b,d);else if("1.2.840.10008.1.2.1.99"===c)b=a.decodeLittleEndian(b,d);else if("1.2.840.10008.1.2.5"===c)b=a.decodeRLE(b,d);else if("1.2.840.10008.1.2.4.50"===c)b=a.decodeJPEGBaseline(b,d);else if("1.2.840.10008.1.2.4.51"===c)b=a.decodeJPEGBaseline(b,d);else if("1.2.840.10008.1.2.4.57"===c)b=a.decodeJPEGLossless(b,d);else if("1.2.840.10008.1.2.4.70"===c)b=a.decodeJPEGLossless(b,d);else if("1.2.840.10008.1.2.4.80"===c)b=a.decodeJPEGLS(b,d);else if("1.2.840.10008.1.2.4.81"===c)b=a.decodeJPEGLS(b,d);else if("1.2.840.10008.1.2.4.90"===c)b=a.decodeJPEG2000(b,d,e,f);else{if("1.2.840.10008.1.2.4.91"!==c)throw console&&console.log&&console.log("Image cannot be decoded due to Unsupported transfer syntax "+c),"no decoder for transfer syntax "+c;b=a.decodeJPEG2000(b,d,e,f)}var h=(new Date).getTime();return b.decodeTimeInMS=h-g,b}a.decodeImageFrame=b}(cornerstoneWADOImageLoader),function(a){function b(a){return(255&a)<<8|a>>8&255}function c(a,c){if(16===a.bitsAllocated){var d=c.buffer,e=c.byteOffset,f=c.length;e%2&&(d=d.slice(e),e=0),0===a.pixelRepresentation?a.pixelData=new Uint16Array(d,e,f/2):a.pixelData=new Int16Array(d,e,f/2);for(var g=0;g<a.pixelData.length;g++)a[g]=b(a.pixelData[g])}else 8===a.bitsAllocated&&(a.pixelData=c);return a}a.decodeBigEndian=c}(cornerstoneWADOImageLoader),function(a){"use strict";function b(a,b){var c=new JpxImage;c.parse(b);var d=c.tiles.length;if(1!==d)throw"JPEG2000 decoder returned a tileCount of "+d+", when 1 is expected";return a.columns=c.width,a.rows=c.height,a.pixelData=c.tiles[0].items,a}function c(a,b,c){var d=g._malloc(a.length);g.writeArrayToMemory(a,d);var e=g._malloc(4),f=g._malloc(4),h=g._malloc(4),i=g._malloc(4),j=g._malloc(4),k=Date.now(),l=g.ccall("jp2_decode","number",["number","number","number","number","number","number","number"],[d,a.length,e,f,h,i,j]);if(0!==l)return console.log("[opj_decode] decoding failed!"),g._free(d),g._free(g.getValue(e,"*")),g._free(h),g._free(i),g._free(f),void g._free(j);var m=g.getValue(e,"*"),n={length:g.getValue(f,"i32"),sx:g.getValue(h,"i32"),sy:g.getValue(i,"i32"),nbChannels:g.getValue(j,"i32"),perf_timetodecode:void 0,pixelData:void 0},o=n.sx*n.sy*n.nbChannels,p=new Int32Array(g.HEAP32.buffer,m,o);if(1===b)if(Uint8Array.from)n.pixelData=Uint8Array.from(p);else{n.pixelData=new Uint8Array(o);for(var q=0;o>q;q++)n.pixelData[q]=p[q]}else if(c)if(Int16Array.from)n.pixelData=Int16Array.from(p);else{n.pixelData=new Int16Array(o);for(var q=0;o>q;q++)n.pixelData[q]=p[q]}else if(Uint16Array.from)n.pixelData=Uint16Array.from(p);else{n.pixelData=new Uint16Array(o);for(var q=0;o>q;q++)n.pixelData[q]=p[q]}var r=Date.now();return n.perf_timetodecode=r-k,g._free(d),g._free(e),g._free(m),g._free(f),g._free(h),g._frLine truncated