Skip to content

Commit

Permalink
Complete merging PR #221 "Render to canvas" and add test use case.
Browse files Browse the repository at this point in the history
Fixes #67
  • Loading branch information
Zaid-Safadi committed Apr 16, 2018
1 parent 4340ff1 commit 717b928
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 73 deletions.
7 changes: 3 additions & 4 deletions src/enable.js
Expand Up @@ -34,12 +34,11 @@ function hasImageOrLayers (enabledElement) {
*
* @param {HTMLElement} element An HTML Element enabled for Cornerstone
* @param {Object} options Options for the enabledElement
* @param {Canvas} canvasInput An HTML canvas to draw the image to
*
* @return {void}
* @memberof Enable
*/
export default function (element, options, canvasInput = null) {
export default function (element, options) {
if (element === undefined) {
throw new Error('enable: parameter element cannot be undefined');
}
Expand All @@ -59,8 +58,8 @@ export default function (element, options, canvasInput = null) {
delete options.renderer;
}
}
const canvas = (canvasInput === null) ? getCanvas(element) : canvasInput;

const canvas = getCanvas(element);

const enabledElement = {
element,
Expand Down
1 change: 1 addition & 0 deletions src/index.js
Expand Up @@ -16,6 +16,7 @@ export { renderPseudoColorImage } from './rendering/renderPseudoColorImage.js';
export { renderColorImage } from './rendering/renderColorImage.js';
export { renderGrayscaleImage } from './rendering/renderGrayscaleImage.js';
export { renderWebImage } from './rendering/renderWebImage.js';
export { default as renderToCanvas } from './rendering/renderToCanvas.js';

/**
* @module PixelCoordinateSystem
Expand Down
4 changes: 3 additions & 1 deletion src/rendering/index.js
Expand Up @@ -3,6 +3,7 @@ import { renderGrayscaleImage } from './renderGrayscaleImage.js';
import { renderWebImage } from './renderWebImage.js';
import { renderPseudoColorImage } from './renderPseudoColorImage.js';
import { renderLabelMapImage } from './renderLabelMapImage.js';
import renderToCanvas from './renderToCanvas.js';

/**
* @module rendering
Expand All @@ -12,5 +13,6 @@ export default {
grayscaleImage: renderGrayscaleImage,
webImage: renderWebImage,
pseudoColorImage: renderPseudoColorImage,
labelMapImage: renderLabelMapImage
labelMapImage: renderLabelMapImage,
toCanvas: renderToCanvas
};
66 changes: 49 additions & 17 deletions src/rendering/renderToCanvas.js
@@ -1,27 +1,59 @@
import { getEnabledElements } from '../enabledElements.js';
import displayImage from '../displayImage.js';
import enableElement from '../enable.js';
import triggerEvent from '../triggerEvent.js';
import EVENTS from '../events.js';
import drawImageSync from '../internal/drawImageSync.js';
import getDefaultViewport from '../internal/getDefaultViewport.js';
import webGL from '../webgl/index.js';

export default function (canvas, imageID, viewport) {

export default function (canvas, image, viewport = null, options = null) {
if (canvas === undefined) {
throw new Error('renderToCanvas: parameter canvas cannot be undefined');
}

const enabledElements = getEnabledElements();
const elements = [];

enabledElements.forEach(function (enabledElement) {
if (enabledElement.canvas && enabledElement.canvas === canvas) {
elements.push(enabledElement.element);
// If this enabled element has the option set for WebGL, we should
// Check if this device actually supports it
if (options && options.renderer && options.renderer.toLowerCase() === 'webgl') {
if (webGL.renderer.isWebGLAvailable()) {
// If WebGL is available on the device, initialize the renderer
// And return the renderCanvas from the WebGL rendering path
webGL.renderer.initRenderer();
options.renderer = 'webgl';
} else {
// If WebGL is not available on this device, we will fall back
// To using the Canvas renderer
console.error('WebGL not available, falling back to Canvas renderer');
delete options.renderer;
}
});
}

const enabledElementStub = {
element: canvas,
canvas,
image,
invalid: true, // True if image needs to be drawn, false if not
needsRedraw: true,
options: null,
layers: [],
data: {},
renderingTools: {},
viewport: getDefaultViewport(canvas, image)
};

if (elements.length === 0) {
enableElement(canvas, null, canvas);
elements.push(canvas);
// Merge viewport
if (viewport) {
for (const attrname in viewport) {
if (viewport[attrname] !== null) {
enabledElementStub.viewport[attrname] = viewport[attrname];
}
}
}

elements.forEach(function (element) {
displayImage(element, imageID, viewport);
});
const eventDetails = {
enabledElement: enabledElementStub,
timestamp: Date.now()
};

triggerEvent(enabledElementStub.element, EVENTS.PRE_RENDER, eventDetails);

drawImageSync(enabledElementStub, enabledElementStub.invalid);
}
2 changes: 1 addition & 1 deletion src/version.js
@@ -1 +1 @@
export default '2.2.0';
export default '2.2.1-rc1';
50 changes: 0 additions & 50 deletions test/renderToCanvas_test.js

This file was deleted.

84 changes: 84 additions & 0 deletions test/rendering/renderToCanvas_test.js
@@ -0,0 +1,84 @@
import { assert, expect } from 'chai';

import renderToCanvas from '../../src/rendering/renderToCanvas.js';
import { getEnabledElement } from '../../src/enabledElements.js';

describe('renderToCanvas', function () {
beforeEach(function () {
// Arrange
this.canvas1 = document.createElement('canvas');

this.height = 256;
this.width = 256;

const canvasContext = this.canvas1.getContext('2d');
const imageData = canvasContext.createImageData(this.width, this.height);
const rnd = Math.round(Math.random() * 255);
const pixelData = imageData.data;
let index = 0;

for (let y = 0; y < this.height; y++) {
for (let x = 0; x < this.width; x++) {
pixelData[index++] = (x + rnd) % 256; // RED
pixelData[index++] = 0; // GREEN
pixelData[index++] = 0; // BLUE
pixelData[index++] = 255; // ALPHA
}
}
canvasContext.putImageData(imageData, 0, 0);

function getPixelData () {
return pixelData;
}

this.image = {
imageId: 'exampleImageId',
minPixelValue: 0,
maxPixelValue: 255,
slope: 1.0,
intercept: 0,
windowCenter: 127,
windowWidth: 256,
getPixelData,
rows: this.height,
columns: this.width,
height: this.height,
width: this.width,
color: true,
sizeInBytes: this.width * this.height * 2
};
});

it('should render an image on the existing canvas, then ', function (done) {
// Arrange
const renderCanvas1 = document.createElement('canvas');

renderCanvas1.width = this.width;
renderCanvas1.height = this.height;

renderCanvas1.addEventListener('cornerstoneimagerendered', (event) => {
// Assert
assert.equal(event.target, renderCanvas1);

expect(function () {
getEnabledElement(event.target);
}).to.throw('element not enabled');

done();
});

// Act
renderToCanvas(renderCanvas1, this.image);

const canvasContext1 = this.canvas1.getContext('2d');
const imageData1 = canvasContext1.createImageData(this.width, this.height);
const pixelData1 = imageData1.data;

const canvasContext2 = renderCanvas1.getContext('2d');
const imageData2 = canvasContext2.createImageData(this.width, this.height);
const pixelData2 = imageData2.data;

// Assert
assert.deepEqual(pixelData1, pixelData2);
});
});

0 comments on commit 717b928

Please sign in to comment.