Update SampleClientOnlyBuild for StandaloneViewer
This commit is contained in:
parent
f0fe96fb19
commit
dd7c47bdb7
@ -9,7 +9,7 @@ meteor npm install
|
||||
Run the application:
|
||||
|
||||
```bash
|
||||
METEOR_PACKAGE_DIRS="../../Packages" meteor
|
||||
METEOR_PACKAGE_DIRS="../../Packages" ROOT_URL=http://localhost:3000 meteor
|
||||
```
|
||||
|
||||
Open your web browser and navigate to one of the following URLs to test the standalone viewer application:
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,10 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" class="__meteor-css__" href="/c8f421f9f0b9011ff3b423d6be202b9f51bad8ed.css?meteor_css_resource=true">
|
||||
<link rel="stylesheet" type="text/css" class="__meteor-css__" href="/6ed8e97b72964fae0a2a3d6dc97b73f7d7bb3b8a.css?meteor_css_resource=true">
|
||||
<link rel="stylesheet" type="text/css" class="__meteor-css__" href="/5658a51260342ba7d4b75a34560a11478ec52615.css?meteor_css_resource=true">
|
||||
<link rel="stylesheet" type="text/css" class="__meteor-css__" href="/d158e88df10469493a1a9e42bf318b1633773633.css?meteor_css_resource=true">
|
||||
<script type="text/javascript">__meteor_runtime_config__ = JSON.parse(decodeURIComponent("%7B%22meteorRelease%22%3A%22METEOR%401.4.2.3%22%2C%22ROOT_URL_PATH_PREFIX%22%3A%22%22%2C%22meteorEnv%22%3A%7B%22NODE_ENV%22%3A%22production%22%7D%2C%22ROOT_URL%22%3A%22localhost%3A3000%22%7D"));</script>
|
||||
<script type="text/javascript" src="/1b141e5df4cc5763349d5ad09402ac283977d7af.js"></script>
|
||||
<script type="text/javascript" src="/07ea9f48ca86e7470deb3a8cbe877b1e551e67b6.js"></script>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<title>OHIF DICOM Viewer</title>
|
||||
@ -15,9 +15,6 @@
|
||||
<meta name="MobileOptimized" content="320">
|
||||
<meta name="HandheldFriendly" content="True">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
|
||||
<link href='http://fonts.googleapis.com/css?family=Roboto:400,100,100italic,300,300italic,400italic,500,500italic,700,700italic,900,900italic&subset=latin,latin-ext' rel='stylesheet' type='text/css'>
|
||||
<link href='http://fonts.googleapis.com/css?family=Sanchez:400,700&subset=latin,latin-ext' rel='stylesheet' type='text/css'>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -0,0 +1,861 @@
|
||||
/*! 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));
|
||||
|
||||
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -91,6 +91,33 @@
|
||||
<path id="icon-tools-measure-target-plus" d="m6,0 a6 6 0 0 1 0 12 a6 6 0 0 1 0 -12 m0.5,3 a0.5 0.5 0 0 0 -1 0 l0,2.5 -2.5,0 a0.5 0.5 0 0 0 0 1 l2.5,0 0,2.5 a0.5 0.5 0 0 0 1 0 l0,-2.5 2.5,0 a0.5 0.5 0 0 0 0 -1 l-2.5,0 z" />
|
||||
</g>
|
||||
</symbol>
|
||||
<symbol id="icon-tools-measure-target-cr" viewBox="0 0 24 24">
|
||||
<title>
|
||||
Target CR Measurement
|
||||
</title>
|
||||
<g id="icon-tools-measure-target-cr-group" fill="none" stroke-width="1" stroke-linecap="round" stroke-linejoin="round">
|
||||
<text id="icon-tools-measure-target-cr-text" fill="#000000" x="0" y="8" style="font-size:10px; font-family:sans-serif">CR</text>
|
||||
<path id="icon-tools-measure-target-cr-arrow" d="M23,7 l-15,15 M7,17 l0,6 6,0" stroke-width="2" />
|
||||
</g>
|
||||
</symbol>
|
||||
<symbol id="icon-tools-measure-target-ex" viewBox="0 0 24 24">
|
||||
<title>
|
||||
Target EX Measurement
|
||||
</title>
|
||||
<g id="icon-tools-measure-target-ex-group" fill="none" stroke-width="1" stroke-linecap="round" stroke-linejoin="round">
|
||||
<text id="icon-tools-measure-target-ex-text" fill="#000000" x="0" y="8" style="font-size:10px; font-family:sans-serif">EX</text>
|
||||
<path id="icon-tools-measure-target-ex-arrow" d="M23,7 l-15,15 M7,17 l0,6 6,0" stroke-width="2" />
|
||||
</g>
|
||||
</symbol>
|
||||
<symbol id="icon-tools-measure-target-un" viewBox="0 0 24 24">
|
||||
<title>
|
||||
Target UN Measurement
|
||||
</title>
|
||||
<g id="icon-tools-measure-target-un-group" fill="none" stroke-width="1" stroke-linecap="round" stroke-linejoin="round">
|
||||
<text id="icon-tools-measure-target-un-text" fill="#000000" x="0" y="8" style="font-size:10px; font-family:sans-serif">UN</text>
|
||||
<path id="icon-tools-measure-target-un-arrow" d="M23,7 l-15,15 M7,17 l0,6 6,0" stroke-width="2" />
|
||||
</g>
|
||||
</symbol>
|
||||
<symbol id="icon-tools-measure-temp" viewBox="0 0 24 24">
|
||||
<title>
|
||||
Temporary Measurement
|
||||
@ -235,4 +262,13 @@
|
||||
<rect x="26" y="26" width="18.8" height="18.8" rx="1" ry="1"/>
|
||||
</g>
|
||||
</symbol>
|
||||
<symbol id="icon-viewport-link" viewBox="0 0 32 32">
|
||||
<title>
|
||||
Viewport Link
|
||||
</title>
|
||||
<g id="icon-viewport-link-group" stroke="none">
|
||||
<path d="m5.364 28.917c1.047 1.046 2.422 1.57 3.797 1.57 1.376 0 2.751-0.523 3.798-1.572l7.552-7.554c1.016-1.014 1.574-2.361 1.574-3.797 -0.001-1.432-0.558-2.781-1.574-3.796l-2.297-2.298 -2.009 2.009 2.297 2.298c0.478 0.478 0.741 1.113 0.741 1.788 0 0.674-0.264 1.309-0.741 1.786l-7.553 7.555c-0.987 0.985-2.59 0.985-3.576 0l-2.297-2.298c-0.987-0.985-0.987-2.589 0-3.576l3.775-3.776 -2.009-2.009 -3.776 3.776c-2.094 2.096-2.092 5.502 0 7.595l2.299 2.3zM26.695 2.992"/>
|
||||
<path d="m26.695 2.992c-1.014-1.016-2.362-1.575-3.797-1.575 -0.001 0-0.001 0-0.002 0 -1.435 0-2.784 0.56-3.798 1.573l-7.551 7.553c-1.017 1.016-1.576 2.363-1.576 3.799 0 1.434 0.558 2.784 1.574 3.797l2.297 2.297 2.01-2.009 -2.298-2.297c-0.477-0.477-0.741-1.113-0.741-1.788 0-0.676 0.265-1.311 0.742-1.788l7.553-7.555c0.477-0.477 1.111-0.74 1.789-0.74 0 0 0 0 0.001 0 0.674 0 1.309 0.264 1.786 0.74l2.297 2.299c0.477 0.477 0.74 1.111 0.74 1.788 0 0.674-0.264 1.311-0.74 1.788l-3.776 3.777 2.009 2.009 3.776-3.777c1.014-1.013 1.573-2.363 1.574-3.797 0-1.435-0.56-2.784-1.574-3.797l-2.295-2.296z"/>
|
||||
</g>
|
||||
</symbol>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 18 KiB |
Loading…
Reference in New Issue
Block a user