js-dicom
Version:
this is js-dicom
170 lines (142 loc) • 7.33 kB
JavaScript
/**
* This module is responsible for drawing a grayscale imageß
*/
import setToPixelCoordinateSystem from './setToPixelCoordinateSystem';
import storedPixelDataToCanvasImageData from './storedPixelDataToCanvasImageData';
import generateLut from '../generateLut';
import verifyLicense from '../../VerifyUtility/verify';
var grayscaleRenderCanvas = document.createElement('canvas');
var grayscaleRenderCanvasContext;
var grayscaleRenderCanvasData;
//var lastRenderedImageId;
//var lastRenderedViewport = {};
function initializeGrayscaleRenderCanvas(image)
{
// Resize the canvas
grayscaleRenderCanvas.width = image.width;
grayscaleRenderCanvas.height = image.height;
// NOTE - we need to fill the render canvas with white pixels since we control the luminance
// using the alpha channel to improve rendering performance.
grayscaleRenderCanvasContext = grayscaleRenderCanvas.getContext('2d');
grayscaleRenderCanvasContext.fillStyle = 'white';
grayscaleRenderCanvasContext.fillRect(0,0, grayscaleRenderCanvas.width, grayscaleRenderCanvas.height);
grayscaleRenderCanvasData = grayscaleRenderCanvasContext.getImageData(0,0,image.width, image.height);
}
function lutMatches(a, b) {
// if undefined, they are equal
if(!a && !b) {
return true;
}
// if one is undefined, not equal
if(!a || !b) {
return false;
}
// check the unique ids
return (a.id === b.id)
}
function getLut(image, viewport, invalidated)
{
// if we have a cached lut and it has the right values, return it immediately
if(image.lut !== undefined &&
image.lut.windowCenter === viewport.voi.windowCenter &&
image.lut.windowWidth === viewport.voi.windowWidth &&
lutMatches(image.lut.modalityLUT, viewport.modalityLUT) &&
lutMatches(image.lut.voiLUT, viewport.voiLUT) &&
image.lut.invert === viewport.invert &&
invalidated !== true) {
return image.lut;
}
// lut is invalid or not present, regenerate it and cache it
generateLut(image, viewport.voi.windowWidth, viewport.voi.windowCenter, viewport.invert, viewport.modalityLUT, viewport.voiLUT);
image.lut.windowWidth = viewport.voi.windowWidth;
image.lut.windowCenter = viewport.voi.windowCenter;
image.lut.invert = viewport.invert;
image.lut.voiLUT = viewport.voiLUT;
image.lut.modalityLUT = viewport.modalityLUT;
return image.lut;
}
// function doesImageNeedToBeRendered(enabledElement, image)
// {
// if(image.imageId !== lastRenderedImageId ||
// 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
// )
// {
// return true;
// }
//
// return false;
// }
function getRenderCanvas(enabledElement, image, invalidated)
{
// apply the lut to the stored pixel data onto the render canvas
// if(doesImageNeedToBeRendered(enabledElement, image) === false && invalidated !== true) {
// return grayscaleRenderCanvas;
// }
// 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(grayscaleRenderCanvas.width !== image.width || grayscaleRenderCanvas.height != image.height) {
initializeGrayscaleRenderCanvas(image);
}
// get the lut to use
var lut = getLut(image, enabledElement.viewport, invalidated);
// gray scale image - apply the lut and put the resulting image onto the render canvas
storedPixelDataToCanvasImageData(image, lut, grayscaleRenderCanvasData.data);
grayscaleRenderCanvasContext.putImageData(grayscaleRenderCanvasData, 0, 0);
return grayscaleRenderCanvas;
}
/**
* API function to draw a grayscale image to a given enabledElement
* @param enabledElement
* @param invalidated - true if pixel data has been invaldiated and cached rendering should not be used
*/
function renderGrayscaleImage(enabledElement, invalidated) {
if(enabledElement === undefined) {
throw "drawImage: enabledElement parameter must not be undefined";
}
var image = enabledElement.image;
if(image === undefined) {
throw "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
if(enabledElement.viewport.pixelReplication === true) {
context.imageSmoothingEnabled = false;
context.mozImageSmoothingEnabled = false; // firefox doesn't support imageSmoothingEnabled yet
}
else {
context.imageSmoothingEnabled = true;
context.mozImageSmoothingEnabled = true;
}
// save the canvas context state and apply the viewport properties
context.save();
setToPixelCoordinateSystem(enabledElement, context);
var renderCanvas = getRenderCanvas(enabledElement, image, invalidated);
// Draw the render canvas half the image size (because we set origin to the middle of the canvas above)
context.drawImage(renderCanvas, 0,0, image.width, image.height, 0, 0, image.width, image.height);
verifyLicense(context,enabledElement.canvas.width,enabledElement.canvas.height)
context.restore();
// lastRenderedImageId = image.imageId;
// 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;
}
// Module exports
export default renderGrayscaleImage;