UNPKG

custom-cornerstone-tools

Version:

Medical imaging tools for the Cornerstone library - customized for DrNuvem

1,434 lines (1,102 loc) 242 kB
/*! cornerstone-core - 1.1.3 - 2017-11-17 | (c) 2016 Chris Hafey | https://github.com/chafey/cornerstone */ (function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define("cornerstone-core", [], factory); else if(typeof exports === 'object') exports["cornerstone-core"] = factory(); else root["cornerstone"] = factory(); })(this, function() { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { /******/ configurable: false, /******/ enumerable: true, /******/ get: getter /******/ }); /******/ } /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 41); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getEnabledElement = getEnabledElement; exports.addEnabledElement = addEnabledElement; exports.getEnabledElementsByImageId = getEnabledElementsByImageId; exports.getEnabledElements = getEnabledElements; var enabledElements = []; /** * A two-dimensional vector * * @typedef {Object} vec2 * @param {Number} x - The x distance * @param {Number} y - The y distance */ /** * VOI * * @typedef {Object} VOI * @param {Number} windowWidth - Window Width for display * @param {Number} windowCenter - Window Center for display */ /** * Lookup Table Array * * @typedef {Object} LUT * @property {Number} firstValueMapped * @property {Number} numBitsPerEntry * @property {Array} lut */ /** * Image Statistics Object * * @typedef {Object} ImageStats * * @property {Number} [lastGetPixelDataTime] The time in ms taken to retrieve stored pixels required to draw the image * @property {Number} [lastStoredPixelDataToCanvasImageDataTime] The time in ms taken to map from stored pixel array to canvas pixel array * @property {Number} [lastPutImageDataTime] The time in ms taken for putImageData to put the canvas pixel data into the canvas context * @property {Number} [lastRenderTime] The total time in ms taken for the entire rendering function to run * @property {Number} [lastLutGenerateTime] The time in ms taken to generate the lookup table for the image */ /** * An Image Object in Cornerstone * * @typedef {Object} Image * * @property {string} imageId - The imageId associated with this image object * @property {Number} minPixelValue - the minimum stored pixel value in the image * @property {Number} maxPixelValue - the maximum stored pixel value in the image * @property {Number} slope - the rescale slope to convert stored pixel values to modality pixel values or 1 if not specified * @property {Number} intercept - the rescale intercept used to convert stored pixel values to modality values or 0 if not specified * @property {Number} windowCenter - the default windowCenter to apply to the image * @property {Number} windowWidth - the default windowWidth to apply to the image * @property {function} getPixelData - a function that returns the underlying pixel data. An array of integers for grayscale and an array of RGBA for color * @property {function} getImageData - a function that returns a canvas imageData object for the image. This is only needed for color images * @property {function} getCanvas - a function that returns a canvas element with the image loaded into it. This is only needed for color images. * @property {function} getImage - a function that returns a JavaScript Image object with the image data. This is optional and typically used for images encoded in standard web JPEG and PNG formats * @property {Number} rows - number of rows in the image. This is the same as height but duplicated for convenience * @property {Number} columns - number of columns in the image. This is the same as width but duplicated for convenience * @property {Number} height - the height of the image. This is the same as rows but duplicated for convenience * @property {Number} width - the width of the image. This is the same as columns but duplicated for convenience * @property {Boolean} color - true if pixel data is RGB, false if grayscale * @property {Object} lut - The Lookup Table * @property {Boolean} rgba - Is the color pixel data stored in RGBA? * @property {Number} columnPixelSpacing - horizontal distance between the middle of each pixel (or width of each pixel) in mm or undefined if not known * @property {Number} rowPixelSpacing - vertical distance between the middle of each pixel (or heigh of each pixel) in mm or undefined if not known * @property {Boolean} invert - true if the the image should initially be displayed be inverted, false if not. This is here mainly to support DICOM images with a photometric interpretation of MONOCHROME1 * @property {Number} sizeInBytes - the number of bytes used to store the pixels for this image. * @property {Boolean} [falseColor=false] - Whether or not the image has undergone false color mapping * @property {Array} [origPixelData] - Original pixel data for an image after it has undergone false color mapping * @property {ImageStats} [stats] - Statistics for the last redraw of the image * @property {Object} cachedLut - Cached Lookup Table for this image. * @property {String|Colormap} [colormap] - an optional colormap ID or colormap object (from colors/colormap.js). This will be applied during rendering to convert the image to pseudocolor * @property {Boolean} [labelmap=false] - whether or not to render this image as a label map (i.e. skip modality and VOI LUT pipelines and use only a color lookup table) */ /** * A Viewport Settings Object Cornerstone * * @typedef {Object} Viewport * * @property {Number} [scale=1.0] - The scale applied to the image. A scale of 1.0 will display no zoom (one image pixel takes up one screen pixel). A scale of 2.0 will be double zoom and a scale of .5 will be zoomed out by 2x * @param {vec2} [translation] - An object with properties x and y which describe the translation to apply in the pixel coordinate system. Note that the image is initially displayed centered in the enabled element with a x and y translation of 0 and 0 respectively. * @param {VOI} [voi] - an object with properties windowWidth and windowCenter. * @property {boolean} [invert=false] - Whether or not the image is inverted. * @property {boolean} [pixelReplication=false] - true if the image smooth / interpolation should be used when zoomed in on the image or false if pixel replication should be used. * @property {boolean} [hflip=false] - true if the image is flipped horizontally. Default is false * @property {boolean} [vflip=false] - true if the image is flipped vertically. Default is false * @property {Number} [rotation=0] - the rotation of the image (90 degree increments). Default is 0 * @property {LUT} [modalityLUT] - the modality LUT to apply or undefined if none * @property {LUT} [voiLUT] - the modality LUT to apply or undefined if none * @property {String|Colormap} [colormap] - an optional colormap ID or colormap object (from colors/colormap.js). This will be applied during rendering to convert the image to pseudocolor * @property {Boolean} [labelmap=false] - whether or not to render this image as a label map (i.e. skip modality and VOI LUT pipelines and use only a color lookup table) */ /** * An Enabled Element in Cornerstone * * @typedef {Object} EnabledElement * * @property {HTMLElement} element - The DOM element which has been enabled for use by Cornerstone * @property {Image} [image] - The image currently displayed in the enabledElement * @property {Viewport} [viewport] - The current viewport settings of the enabledElement * @property {HTMLCanvasElement} [canvas] - The current canvas for this enabledElement * @property {Boolean} invalid - Whether or not the image pixel data underlying the enabledElement has been changed, necessitating a redraw * @property {Boolean} needsRedraw - A flag for triggering a redraw of the canvas without re-retrieving the pixel data, since it remains valid * @property {EnabledElementLayer[]} [layers] - The layers that have been added to the enabledElement * @property {Boolean} [syncViewports] - Whether or not to synchronize the viewport parameters * for each of the enabled element's layers * @property {Boolean} [lastSyncViewportsState] - The previous state for the sync viewport boolean */ /** * An Enabled Element Layer in Cornerstone * * @typedef {Object} EnabledElementLayer * * @property {HTMLElement} element - The DOM element which has been enabled for use by Cornerstone * @property {Image} [image] - The image currently displayed in the enabledElement * @property {Viewport} [viewport] - The current viewport settings of the enabledElement * @property {HTMLCanvasElement} [canvas] - The current canvas for this enabledElement * @property {Object} [options] - Layer drawing options * @property {Boolean} invalid - Whether or not the image pixel data underlying the enabledElement has been changed, necessitating a redraw * @property {Boolean} needsRedraw - A flag for triggering a redraw of the canvas without re-retrieving the pixel data, since it remains valid */ /** * Retrieves a Cornerstone Enabled Element object * * @param {HTMLElement} element An HTML Element enabled for Cornerstone * * @returns {EnabledElement} A Cornerstone Enabled Element */ function getEnabledElement(element) { if (element === undefined) { throw new Error('getEnabledElement: parameter element must not be undefined'); } for (var i = 0; i < enabledElements.length; i++) { if (enabledElements[i].element === element) { return enabledElements[i]; } } throw new Error('element not enabled'); } /** * Adds a Cornerstone Enabled Element object to the central store of enabledElements * * @param {EnabledElement} enabledElement A Cornerstone enabledElement Object * @returns {void} */ function addEnabledElement(enabledElement) { if (enabledElement === undefined) { throw new Error('getEnabledElement: enabledElement element must not be undefined'); } enabledElements.push(enabledElement); } /** * Adds a Cornerstone Enabled Element object to the central store of enabledElements * * @param {string} imageId A Cornerstone Image ID * @returns {EnabledElement[]} An Array of Cornerstone enabledElement Objects */ function getEnabledElementsByImageId(imageId) { var ees = []; enabledElements.forEach(function (enabledElement) { if (enabledElement.image && enabledElement.image.imageId === imageId) { ees.push(enabledElement); } }); return ees; } /** * Retrieve all of the currently enabled Cornerstone elements * * @return {EnabledElement[]} An Array of Cornerstone enabledElement Objects */ function getEnabledElements() { return enabledElements; } /***/ }), /* 1 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = function () { if (window.performance) { return performance.now(); } return Date.now(); }; /***/ }), /* 2 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = triggerEvent; var _externalModules = __webpack_require__(33); /** * Trigger a CustomEvent * * @param {EventTarget} el The element or EventTarget to trigger the event upon * @param {String} type The event type name * @param {Object|null} detail=null The event data to be sent * @returns {void} */ function triggerEvent(el, type) { var detail = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; var event = void 0; // This check is needed to polyfill CustomEvent on IE11- if (typeof window.CustomEvent === 'function') { event = new CustomEvent(type.toLocaleLowerCase(), { detail: detail }); } else { event = document.createEvent('CustomEvent'); event.initCustomEvent(type.toLocaleLowerCase(), true, true, detail); } // TODO: remove jQuery event triggers _externalModules.external.$(el).trigger(type, detail); el.dispatchEvent(event); } /***/ }), /* 3 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = function (enabledElement, context, scale) { if (enabledElement === undefined) { throw new Error('setToPixelCoordinateSystem: parameter enabledElement must not be undefined'); } if (context === undefined) { throw new Error('setToPixelCoordinateSystem: parameter context must not be undefined'); } var transform = (0, _calculateTransform2.default)(enabledElement, scale); context.setTransform(transform.m[0], transform.m[1], transform.m[2], transform.m[3], transform.m[4], transform.m[5]); }; var _calculateTransform = __webpack_require__(22); var _calculateTransform2 = _interopRequireDefault(_calculateTransform); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /***/ }), /* 4 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = function (element) { var invalidated = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; var enabledElement = (0, _enabledElements.getEnabledElement)(element); if (enabledElement.image === undefined && !enabledElement.layers.length) { throw new Error('updateImage: image has not been loaded yet'); } (0, _drawImage2.default)(enabledElement, invalidated); }; var _enabledElements = __webpack_require__(0); var _drawImage = __webpack_require__(5); var _drawImage2 = _interopRequireDefault(_drawImage); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /***/ }), /* 5 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = function (enabledElement) { var invalidated = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; enabledElement.needsRedraw = true; if (invalidated) { enabledElement.invalid = true; } }; /***/ }), /* 6 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = function (canvas, image) { if (canvas === undefined) { throw new Error('getDefaultViewport: parameter canvas must not be undefined'); } if (image === undefined) { return { scale: 1, translation: { x: 0, y: 0 }, voi: { windowWidth: undefined, windowCenter: undefined }, invert: false, pixelReplication: false, rotation: 0, hflip: false, vflip: false, modalityLUT: undefined, voiLUT: undefined, colormap: undefined, labelmap: false }; } // Fit image to window var verticalScale = canvas.height / image.rows; var horizontalScale = canvas.width / image.columns; var scale = Math.min(horizontalScale, verticalScale); return { scale: scale, translation: { x: 0, y: 0 }, voi: { windowWidth: image.windowWidth, windowCenter: image.windowCenter }, invert: image.invert, pixelReplication: false, rotation: 0, hflip: false, vflip: false, modalityLUT: image.modalityLUT, voiLUT: image.voiLUT, colormap: image.colormap, labelmap: Boolean(image.labelmap) }; }; /***/ }), /* 7 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _colormap = __webpack_require__(27); var _lookupTable = __webpack_require__(28); var _lookupTable2 = _interopRequireDefault(_lookupTable); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } exports.default = { getColormap: _colormap.getColormap, getColormapsList: _colormap.getColormapsList, LookupTable: _lookupTable2.default }; /***/ }), /* 8 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.renderColorImage = renderColorImage; exports.addColorLayer = addColorLayer; var _now = __webpack_require__(1); var _now2 = _interopRequireDefault(_now); var _generateLut = __webpack_require__(9); var _generateLut2 = _interopRequireDefault(_generateLut); var _storedColorPixelDataToCanvasImageData = __webpack_require__(19); var _storedColorPixelDataToCanvasImageData2 = _interopRequireDefault(_storedColorPixelDataToCanvasImageData); var _storedRGBAPixelDataToCanvasImageData = __webpack_require__(45); var _storedRGBAPixelDataToCanvasImageData2 = _interopRequireDefault(_storedRGBAPixelDataToCanvasImageData); var _setToPixelCoordinateSystem = __webpack_require__(3); var _setToPixelCoordinateSystem2 = _interopRequireDefault(_setToPixelCoordinateSystem); var _index = __webpack_require__(14); var _index2 = _interopRequireDefault(_index); var _doesImageNeedToBeRendered = __webpack_require__(13); var _doesImageNeedToBeRendered2 = _interopRequireDefault(_doesImageNeedToBeRendered); var _initializeRenderCanvas = __webpack_require__(11); var _initializeRenderCanvas2 = _interopRequireDefault(_initializeRenderCanvas); var _saveLastRendered = __webpack_require__(12); var _saveLastRendered2 = _interopRequireDefault(_saveLastRendered); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function getLut(image, viewport) { // If we have a cached lut and it has the right values, return it immediately if (image.cachedLut !== undefined && image.cachedLut.windowCenter === viewport.voi.windowCenter && image.cachedLut.windowWidth === viewport.voi.windowWidth && image.cachedLut.invert === viewport.invert) { return image.cachedLut.lutArray; } // Lut is invalid or not present, regenerate it and cache it (0, _generateLut2.default)(image, viewport.voi.windowWidth, viewport.voi.windowCenter, viewport.invert); image.cachedLut.windowWidth = viewport.voi.windowWidth; image.cachedLut.windowCenter = viewport.voi.windowCenter; image.cachedLut.invert = viewport.invert; return image.cachedLut.lutArray; } /** * This module is responsible for drawing an image to an enabled elements canvas element */ function getRenderCanvas(enabledElement, image, invalidated) { if (!enabledElement.renderingTools.renderCanvas) { enabledElement.renderingTools.renderCanvas = document.createElement('canvas'); } var renderCanvas = enabledElement.renderingTools.renderCanvas; // The ww/wc is identity and not inverted - get a canvas with the image rendered into it for // Fast drawing if (enabledElement.viewport.voi.windowWidth === 255 && enabledElement.viewport.voi.windowCenter === 128 && enabledElement.viewport.invert === false && image.getCanvas && image.getCanvas()) { return image.getCanvas(); } // Apply the lut to the stored pixel data onto the render canvas if ((0, _doesImageNeedToBeRendered2.default)(enabledElement, image) === false && invalidated !== true) { return renderCanvas; } // If our render canvas does not match the size of this image reset it // NOTE: This might be inefficient if we are updating multiple images of different // Sizes frequently. if (renderCanvas.width !== image.width || renderCanvas.height !== image.height) { (0, _initializeRenderCanvas2.default)(enabledElement, image); } // Get the lut to use var start = (0, _now2.default)(); var colorLut = getLut(image, enabledElement.viewport); image.stats = image.stats || {}; image.stats.lastLutGenerateTime = (0, _now2.default)() - start; var renderCanvasData = enabledElement.renderingTools.renderCanvasData; var renderCanvasContext = enabledElement.renderingTools.renderCanvasContext; // The color image voi/invert has been modified - apply the lut to the underlying // Pixel data and put it into the renderCanvas if (image.rgba) { (0, _storedRGBAPixelDataToCanvasImageData2.default)(image, colorLut, renderCanvasData.data); } else { (0, _storedColorPixelDataToCanvasImageData2.default)(image, colorLut, renderCanvasData.data); } start = (0, _now2.default)(); renderCanvasContext.putImageData(renderCanvasData, 0, 0); image.stats.lastPutImageDataTime = (0, _now2.default)() - start; return renderCanvas; } /** * API function to render a color image to an enabled element * * @param {EnabledElement} enabledElement The Cornerstone Enabled Element to redraw * @param {Boolean} invalidated - true if pixel data has been invalidated and cached rendering should not be used * @returns {void} */ function renderColorImage(enabledElement, invalidated) { if (enabledElement === undefined) { throw new Error('renderColorImage: enabledElement parameter must not be undefined'); } var image = enabledElement.image; if (image === undefined) { throw new Error('renderColorImage: image must be loaded before it can be drawn'); } // Get the canvas context and reset the transform var context = enabledElement.canvas.getContext('2d'); context.setTransform(1, 0, 0, 1, 0, 0); // Clear the canvas context.fillStyle = 'black'; context.fillRect(0, 0, enabledElement.canvas.width, enabledElement.canvas.height); // Turn off image smooth/interpolation if pixelReplication is set in the viewport context.imageSmoothingEnabled = !enabledElement.viewport.pixelReplication; context.mozImageSmoothingEnabled = context.imageSmoothingEnabled; // Save the canvas context state and apply the viewport properties (0, _setToPixelCoordinateSystem2.default)(enabledElement, context); var renderCanvas = void 0; if (enabledElement.options && enabledElement.options.renderer && enabledElement.options.renderer.toLowerCase() === 'webgl') { // If this enabled element has the option set for WebGL, we should // User it as our renderer. renderCanvas = _index2.default.renderer.render(enabledElement); } else { // If no options are set we will retrieve the renderCanvas through the // Normal Canvas rendering path renderCanvas = getRenderCanvas(enabledElement, image, invalidated); } context.drawImage(renderCanvas, 0, 0, image.width, image.height, 0, 0, image.width, image.height); enabledElement.renderingTools = (0, _saveLastRendered2.default)(enabledElement); } function addColorLayer(layer, invalidated) { if (layer === undefined) { throw new Error('addColorLayer: layer parameter must not be undefined'); } var image = layer.image; if (image === undefined) { throw new Error('addColorLayer: image must be loaded before it can be drawn'); } // All multi-layer images should include the alpha value image.rgba = true; layer.canvas = getRenderCanvas(layer, image, invalidated); var context = layer.canvas.getContext('2d'); // Turn off image smooth/interpolation if pixelReplication is set in the viewport context.imageSmoothingEnabled = !layer.viewport.pixelReplication; context.mozImageSmoothingEnabled = context.imageSmoothingEnabled; layer.renderingTools = (0, _saveLastRendered2.default)(layer); } /***/ }), /* 9 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = function (image, windowWidth, windowCenter, invert, modalityLUT, voiLUT) { var maxPixelValue = image.maxPixelValue; var minPixelValue = image.minPixelValue; var offset = Math.min(minPixelValue, 0); if (image.cachedLut === undefined) { var length = maxPixelValue - offset + 1; image.cachedLut = {}; image.cachedLut.lutArray = new Uint8ClampedArray(length); } var lut = image.cachedLut.lutArray; var mlutfn = (0, _getModalityLUT2.default)(image.slope, image.intercept, modalityLUT); var vlutfn = (0, _getVOILut2.default)(windowWidth, windowCenter, voiLUT); if (invert === true) { for (var storedValue = minPixelValue; storedValue <= maxPixelValue; storedValue++) { lut[storedValue + -offset] = 255 - vlutfn(mlutfn(storedValue)); } } else { for (var _storedValue = minPixelValue; _storedValue <= maxPixelValue; _storedValue++) { lut[_storedValue + -offset] = vlutfn(mlutfn(_storedValue)); } } return lut; }; var _getModalityLUT = __webpack_require__(26); var _getModalityLUT2 = _interopRequireDefault(_getModalityLUT); var _getVOILut = __webpack_require__(42); var _getVOILut2 = _interopRequireDefault(_getVOILut); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /***/ }), /* 10 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = function (enabledElement) { // For now we will calculate it every time it is requested. // In the future, we may want to cache it in the enabled element to speed things up. return (0, _calculateTransform2.default)(enabledElement); }; var _calculateTransform = __webpack_require__(22); var _calculateTransform2 = _interopRequireDefault(_calculateTransform); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /***/ }), /* 11 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = function (enabledElement, image) { var renderCanvas = enabledElement.renderingTools.renderCanvas; // Resize the canvas renderCanvas.width = image.width; renderCanvas.height = image.height; var canvasContext = renderCanvas.getContext('2d'); // NOTE - we need to fill the render canvas with white pixels since we // control the luminance using the alpha channel to improve rendering performance. canvasContext.fillStyle = 'white'; canvasContext.fillRect(0, 0, renderCanvas.width, renderCanvas.height); var renderCanvasData = canvasContext.getImageData(0, 0, image.width, image.height); enabledElement.renderingTools.renderCanvasContext = canvasContext; enabledElement.renderingTools.renderCanvasData = renderCanvasData; }; /***/ }), /* 12 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = function (enabledElement) { var imageId = enabledElement.image.imageId; var viewport = enabledElement.viewport; enabledElement.renderingTools.lastRenderedImageId = imageId; enabledElement.renderingTools.lastRenderedViewport = { windowCenter: viewport.voi.windowCenter, windowWidth: viewport.voi.windowWidth, invert: viewport.invert, rotation: viewport.rotation, hflip: viewport.hflip, vflip: viewport.vflip, modalityLUT: viewport.modalityLUT, voiLUT: viewport.voiLUT, colormap: viewport.colormap }; return enabledElement.renderingTools; }; /***/ }), /* 13 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = function (enabledElement, image) { var lastRenderedImageId = enabledElement.renderingTools.lastRenderedImageId; var lastRenderedViewport = enabledElement.renderingTools.lastRenderedViewport; return image.imageId !== lastRenderedImageId || !lastRenderedViewport || lastRenderedViewport.windowCenter !== enabledElement.viewport.voi.windowCenter || lastRenderedViewport.windowWidth !== enabledElement.viewport.voi.windowWidth || lastRenderedViewport.invert !== enabledElement.viewport.invert || lastRenderedViewport.rotation !== enabledElement.viewport.rotation || lastRenderedViewport.hflip !== enabledElement.viewport.hflip || lastRenderedViewport.vflip !== enabledElement.viewport.vflip || lastRenderedViewport.modalityLUT !== enabledElement.viewport.modalityLUT || lastRenderedViewport.voiLUT !== enabledElement.viewport.voiLUT || lastRenderedViewport.colormap !== enabledElement.viewport.colormap; }; /***/ }), /* 14 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _renderer = __webpack_require__(46); var _createProgramFromString = __webpack_require__(34); var _createProgramFromString2 = _interopRequireDefault(_createProgramFromString); var _textureCache = __webpack_require__(32); var _textureCache2 = _interopRequireDefault(_textureCache); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var mod = { createProgramFromString: _createProgramFromString2.default, renderer: { render: _renderer.render, initRenderer: _renderer.initRenderer, getRenderCanvas: _renderer.getRenderCanvas, isWebGLAvailable: _renderer.isWebGLAvailable }, textureCache: _textureCache2.default }; Object.defineProperty(mod, 'isWebGLInitialized', { enumerable: true, configurable: false, get: function get() { return _renderer.isWebGLInitialized; } }); exports.default = mod; /***/ }), /* 15 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var EventTarget = function () { function EventTarget() { _classCallCheck(this, EventTarget); this.listeners = {}; } _createClass(EventTarget, [{ key: "addEventListener", value: function addEventListener(type, callback) { if (!(type in this.listeners)) { this.listeners[type] = []; } this.listeners[type].push(callback); } }, { key: "removeEventListener", value: function removeEventListener(type, callback) { if (!(type in this.listeners)) { return; } var stack = this.listeners[type]; for (var i = 0, l = stack.length; i < l; i++) { if (stack[i] === callback) { stack.splice(i, 1); return; } } } }, { key: "dispatchEvent", value: function dispatchEvent(event) { if (!(event.type in this.listeners)) { return true; } var stack = this.listeners[event.type]; for (var i = 0, l = stack.length; i < l; i++) { stack[i].call(this, event); } return !event.defaultPrevented; } }]); return EventTarget; }(); var events = new EventTarget(); exports.default = events; /***/ }), /* 16 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.renderGrayscaleImage = renderGrayscaleImage; exports.addGrayscaleLayer = addGrayscaleLayer; var _storedPixelDataToCanvasImageData = __webpack_require__(18); var _storedPixelDataToCanvasImageData2 = _interopRequireDefault(_storedPixelDataToCanvasImageData); var _storedPixelDataToCanvasImageDataRGBA = __webpack_require__(29); var _storedPixelDataToCanvasImageDataRGBA2 = _interopRequireDefault(_storedPixelDataToCanvasImageDataRGBA); var _setToPixelCoordinateSystem = __webpack_require__(3); var _setToPixelCoordinateSystem2 = _interopRequireDefault(_setToPixelCoordinateSystem); var _now = __webpack_require__(1); var _now2 = _interopRequireDefault(_now); var _index = __webpack_require__(14); var _index2 = _interopRequireDefault(_index); var _getLut = __webpack_require__(31); var _getLut2 = _interopRequireDefault(_getLut); var _doesImageNeedToBeRendered = __webpack_require__(13); var _doesImageNeedToBeRendered2 = _interopRequireDefault(_doesImageNeedToBeRendered); var _initializeRenderCanvas = __webpack_require__(11); var _initializeRenderCanvas2 = _interopRequireDefault(_initializeRenderCanvas); var _saveLastRendered = __webpack_require__(12); var _saveLastRendered2 = _interopRequireDefault(_saveLastRendered); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function getRenderCanvas(enabledElement, image, invalidated) { var useAlphaChannel = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; if (!enabledElement.renderingTools.renderCanvas) { enabledElement.renderingTools.renderCanvas = document.createElement('canvas'); } var renderCanvas = enabledElement.renderingTools.renderCanvas; if ((0, _doesImageNeedToBeRendered2.default)(enabledElement, image) === false && invalidated !== true) { return renderCanvas; } // If our render canvas does not match the size of this image reset it // NOTE: This might be inefficient if we are updating multiple images of different // Sizes frequently. if (renderCanvas.width !== image.width || renderCanvas.height !== image.height) { (0, _initializeRenderCanvas2.default)(enabledElement, image); } // Get the lut to use var start = (0, _now2.default)(); var lut = (0, _getLut2.default)(image, enabledElement.viewport, invalidated); image.stats = image.stats || {}; image.stats.lastLutGenerateTime = (0, _now2.default)() - start; var renderCanvasData = enabledElement.renderingTools.renderCanvasData; var renderCanvasContext = enabledElement.renderingTools.renderCanvasContext; // Gray scale image - apply the lut and put the resulting image onto the render canvas if (useAlphaChannel) { (0, _storedPixelDataToCanvasImageData2.default)(image, lut, renderCanvasData.data); } else { (0, _storedPixelDataToCanvasImageDataRGBA2.default)(image, lut, renderCanvasData.data); } start = (0, _now2.default)(); renderCanvasContext.putImageData(renderCanvasData, 0, 0); image.stats.lastPutImageDataTime = (0, _now2.default)() - start; return renderCanvas; } /** * API function to draw a grayscale image to a given enabledElement * * @param {EnabledElement} enabledElement The Cornerstone Enabled Element to redraw * @param {Boolean} invalidated - true if pixel data has been invalidated and cached rendering should not be used * @returns {void} */ function renderGrayscaleImage(enabledElement, invalidated) { if (enabledElement === undefined) { throw new Error('drawImage: enabledElement parameter must not be undefined'); } var image = enabledElement.image; if (image === undefined) { throw new Error('drawImage: image must be loaded before it can be drawn'); } // Get the canvas context and reset the transform var context = enabledElement.canvas.getContext('2d'); context.setTransform(1, 0, 0, 1, 0, 0); // Clear the canvas context.fillStyle = 'black'; context.fillRect(0, 0, enabledElement.canvas.width, enabledElement.canvas.height); // Turn off image smooth/interpolation if pixelReplication is set in the viewport context.imageSmoothingEnabled = !enabledElement.viewport.pixelReplication; context.mozImageSmoothingEnabled = context.imageSmoothingEnabled; // Save the canvas context state and apply the viewport properties (0, _setToPixelCoordinateSystem2.default)(enabledElement, context); var renderCanvas = void 0; if (enabledElement.options && enabledElement.options.renderer && enabledElement.options.renderer.toLowerCase() === 'webgl') { // If this enabled element has the option set for WebGL, we should // User it as our renderer. renderCanvas = _index2.default.renderer.render(enabledElement); } else { // If no options are set we will retrieve the renderCanvas through the // Normal Canvas rendering path renderCanvas = getRenderCanvas(enabledElement, image, invalidated); } context.drawImage(renderCanvas, 0, 0, image.width, image.height, 0, 0, image.width, image.height); enabledElement.renderingTools = (0, _saveLastRendered2.default)(enabledElement); } /** * API function to draw a grayscale image to a given layer * * @param {EnabledElementLayer} layer The layer that the image will be added to * @param {Boolean} invalidated - true if pixel data has been invalidated and cached rendering should not be used * @param {Boolean} [useAlphaChannel] - Whether or not to render the grayscale image using only the alpha channel. This does not work if this layer is not the first layer in the enabledElement. * @returns {void} */ function addGrayscaleLayer(layer, invalidated) { var useAlphaChannel = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; if (layer === undefined) { throw new Error('addGrayscaleLayer: layer parameter must not be undefined'); } var image = layer.image; if (image === undefined) { throw new Error('addGrayscaleLayer: image must be loaded before it can be drawn'); } layer.canvas = getRenderCanvas(layer, image, invalidated, useAlphaChannel); var context = layer.canvas.getContext('2d'); // Turn off image smooth/interpolation if pixelReplication is set in the viewport context.imageSmoothingEnabled = !layer.viewport.pixelReplication; context.mozImageSmoothingEnabled = context.imageSmoothingEnabled; layer.renderingTools = (0, _saveLastRendered2.default)(layer); } /***/ }), /* 17 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = function (callback) { return window.requestAnimationFrame(callback) || window.webkitRequestAnimationFrame(callback) || window.mozRequestAnimationFrame(callback) || window.oRequestAnimationFrame(callback) || window.msRequestAnimationFrame(callback) || requestFrame(callback); }; function requestFrame(callback) { window.setTimeout(callback, 1000 / 60); } /** * Polyfills requestAnimationFrame for older browsers. * * @param {Function} callback A parameter specifying a function to call when it's time to update your animation for the next repaint. The callback has one single argument, a DOMHighResTimeStamp, which indicates the current time (the time returned from performance.now() ) for when requestAnimationFrame starts to fire callbacks. * * @return {Number} A long integer value, the request id, that uniquely identifies the entry in the callback list. This is a non-zero value, but you may not make any other assumptions about its value. You can pass this value to window.cancelAnimationFrame() to cancel the refresh callback request. */ /***/ }), /* 18 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = function (image, lut, canvasImageDataData) { var start = (0, _now2.default)(); var pixelData = image.getPixelData(); image.stats.lastGetPixelDataTime = (0, _now2.default)() - start; var numPixels = pixelData.length; var minPixelValue = image.minPixelValue; var canvasImageDataIndex = 3; var storedPixelDataIndex = 0; // NOTE: As of Nov 2014, most javascript engines have lower performance when indexing negative indexes. // We have a special code path for this case that improves performance. Thanks to @jpambrun for this enhancement // Added two paths (Int16Array, Uint16Array) to avoid polymorphic deoptimization in chrome. start = (0, _now2.default)(); if (pixelData instanceof Int16Array) { if (minPixelValue < 0) { while (storedPixelDataIndex < numPixels) { canvasImageDataData[canvasImageDataIndex] = lut[pixelData[storedPixelDataIndex++] + -minPixelValue]; // Alpha canvasImageDataIndex += 4; } } else { while (storedPixelDataIndex < numPixels) { canvasImageDataData[canvasImageDataIndex] = lut[pixelData[storedPixelDataIndex++]]; // Alpha canvasImageDataIndex += 4; } } } else if (pixelData instanceof Uint16Array) { while (storedPixelDataIndex < numPixels) { canvasImageDataData[canvasImageDataIndex] = lut[pixelData[storedPixelDataIndex++]]; // Alpha canvasImageDataIndex += 4; } } else if (minPixelValue < 0) { while (storedPixelDataIndex < numPixels) { canvasImageDataData[canvasImageDataIndex] = lut[pixelData[storedPixelDataIndex++] + -minPixelValue]; // Alpha canvasImageDataIndex += 4; } } else { while (storedPixelDataIndex < numPixels) { canvasImageDataData[canvasImageDataIndex] = lut[pixelData[storedPixelDataIndex++]]; // Alpha canvasImageDataIndex += 4; } } image.stats.lastStoredPixelDataToCanvasImageDataTime = (0, _now2.default)() - start; }; var _now = __webpack_require__(1); var _now2 = _interopRequireDefault(_now); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /***/ }), /* 19 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = function (image, lut, canvasImageDataData) { var start = (0, _now2.default)(); var pixelData = image.getPixelData(); image.stats.lastGetPixelDataTime = (0, _now2.default)() - start; var minPixelValue = image.minPixelValue; var canvasImageDataIndex = 0; var storedPixelDataIndex = 0; var numPixels = pixelData.length; // NOTE: As of Nov 2014, most javascript engines have lower performance when indexing negative indexes. // We have a special code path for this case that improves performance. Thanks to @jpambrun for this enhancement start = (0, _now2.default)(); if (minPixelValue < 0) { while (storedPixelDataIndex < numPixels) { canvasImageDataData[canvasImageDataIndex++] = lut[pixelData[storedPixelDataIndex++] + -minPixelValue]; // Red canvasImageDataData[canvasImageDataIndex++] = lut[pixelData[storedPixelDataIndex++] + -minPixelValue]; // Green canvasImageDataData[canvasImageDataIndex] = lut[pixelData[storedPixelDataIndex] + -minPixelValue]; // Blue storedPixelDataIndex += 2; canvasImageDataIndex += 2; } } else { while (storedPixelDataIndex < numPixels) { canvasImageDataData[canvasImageDataIndex++] = lut[pixelData[storedPixelDataIndex++]]; // Red canvasImageDataData[canvasImageDataIndex++] = lut[pixelData[storedPixelDataIndex++]]; // Green canvasImageDataData[canvasImageDataIndex] = lut[pixelData[storedPixelDataIndex]]; // Blue storedPixelDataIndex += 2; canvasImageDataIndex += 2; } } image.stats.lastStoredPixelDataToCanvasImageDataTime = (0, _now2.default)() - start; }; var _now = __webpack_require__(1); var _now2 = _interopRequireDefault(_now); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /***/ }), /* 20 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _index = __webpack_require__(7); var _index2 = _interopRequireDefault(_index); var _now = __webpack_require__(1); var _now2 = _interopRequireDefault(_now); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * * @param {Image} image A Cornerstone Image Object * @param {LookupTable|Array} colorLut Lookup table array * @param {Uint8ClampedArray} canvasImageDataData canvasImageData.data buffer filled with white pixels * * @returns {void} */ function storedPixelDataToCanvasImageDataColorLUT(image, colorLut, canvasImageDataData) { var start = (0, _now2.default)(); var pixelData = image.getPixelData(); image.stats.lastGetPixelDataTime = (0, _now2.default)() - start; var numPixels = pixelData.length; var minPixelValue = image.minPixelValue; var canvasImageDataIndex = 0; var storedPixelDataIndex = 0; var rgba = void 0; var clut = void 0; start = (0, _now2.default)(); if (colorLut instanceof _index2.default.LookupTable) { clut = colorLut.Table; } else { clut = colorLut; } if (minPixelValue < 0) { while (storedPixelDataIndex < numPixels) { rgba = clut[pixelData[storedPixelDataIndex++] + -minPixelValue]; canvasImageDataData[canvasImageDataIndex++] = rgba[0]; canvasImageDataData[canvasImageDataIndex++] = rgba[1]; canvasImageDataData[canvasImageDataIndex++] = rgba[2]; canvasImageDataData[canvasImageDataIndex++] = rgba[3]; } } else { while (storedPixelDataIndex < numPixels) { rgba = clut[pixelData[storedPixelDataIndex++]]; canvasImageDataData[canvasImageDataIndex++] = rgba[0]; canvasImageDataData[canvasImageDataIndex++] = rgba[1]; canvasImageDataData[canvasImageDataIndex++] = rgba[2]; canvasImageDataData[canvasImageDataIndex++] = rgba[3]; } } image.stats.lastStoredPixelDataToCanvasImageDataTime = (0, _now2.default)() - start; } exports.default = storedPixelDataToCanvasImageDataColorLUT; /***/ }), /* 21 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _index = __webpack_require__(7); var _index2 = _interopRequireDefault(_index); var _now = __webpack_require__(1); var _now2 = _interopRequireDefault(_now); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * * @param {Image} image A Cornerstone Image Object * @param {Array} grayscaleLut Lookup table array * @param {LookupTable|Array} colorLut Lookup table array * @param {Uint8ClampedArray} canvasImageDataData canvasImageData.data buffer filled with white pixels * * @returns {void} */ function storedPixelDataToCanvasImageDataPseudocolorLUT(image, grayscaleLut, colorLut, canvasImageDataData) { var start = (0, _now2.default)(); var pixelData = image.getPixelData(); image.stats.lastGetPixelDataTime = (0, _now2.default)() - start; var numPixels = pixelData.length; var minPixelValue = image.minPixelValue; var canvasImageDataIndex = 0; var storedPixelDataIndex = 0; var grayscale = void 0; var rgba = void 0; var clut = void 0; start = (0, _now2.default)(); if (colorLut instanceof _index2.default.LookupTable) { clut = colorLut.Table; } else { clut = colorLut; } if (minPixelValue < 0) { while (storedPixelDataIndex < numPixels) { grayscale = grayscaleLut[pixelData[storedPixelDataIndex++] + -minPixelValue]; rgba = clut[grayscale]; canvasImageDataData[canvasImageDataIndex++] = rgba[0]; canvasImageDataData[canvasImageDataIndex++] = rgba[1]; canvasImageDataData[canvasImageDataIndex++] = rgba[2]; canvasImageDataData[canvasImageDataIndex++] = rgba[3]; } } else { while (storedPixelDataIndex < numPixels) { grayscale = grayscaleLut[pixelData[storedPixelDataIndex++]]; rgba = clut[grayscale]; canvasImageDataData[canvasImageDataIndex++] = rgba[0]; canvasImageDataData[canvasImageDataIndex++] = rgba[1]; canvasImageDataData[canvasImageDataIndex++] = rgba[2]; canvasImageDataData[canv