Added latest from Cornerstone WebGL branch

This commit is contained in:
Erik Ziegler 2016-02-12 12:03:15 +01:00 committed by Erik Ziegler
parent afeb0d82fb
commit 624d2aeaf5
2 changed files with 62 additions and 69 deletions

View File

@ -1,4 +1,4 @@
/*! cornerstone - v0.9.0 - 2016-02-04 | (c) 2014 Chris Hafey | https://github.com/chafey/cornerstone */ /*! cornerstone - v0.9.0 - 2016-02-12 | (c) 2014 Chris Hafey | https://github.com/chafey/cornerstone */
if(typeof cornerstone === 'undefined'){ if(typeof cornerstone === 'undefined'){
cornerstone = { cornerstone = {
internal : {}, internal : {},
@ -163,33 +163,38 @@ if(typeof cornerstone === 'undefined'){
"use strict"; "use strict";
function enable(element, renderer) { function enable(element, options) {
if(element === undefined) { if(element === undefined) {
throw "enable: parameter element cannot be undefined"; throw "enable: parameter element cannot be undefined";
} }
// 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 (cornerstone.webGL.renderer.isWebGLAvailable()) {
// If WebGL is available on the device, initialize the renderer
// and return the renderCanvas from the WebGL rendering path
console.log('Using WebGL rendering path');
cornerstone.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;
}
}
var canvas = document.createElement('canvas'); var canvas = document.createElement('canvas');
element.appendChild(canvas); element.appendChild(canvas);
if (typeof renderer === 'string' && renderer.toLowerCase() === 'webgl') {
renderer = cornerstone.webGL.renderer.render;
}
if (renderer === cornerstone.webGL.renderer.render) {
if (!cornerstone.webGL.renderer.isWebGLAvailable()) {
console.error('WebGL not available, falling back to Canvas renderer');
renderer = undefined;
} else {
cornerstone.webGL.renderer.initRenderer();
}
}
var el = { var el = {
element: element, element: element,
canvas: canvas, canvas: canvas,
image : undefined, // will be set once image is loaded image : undefined, // will be set once image is loaded
invalid: false, // true if image needs to be drawn, false if not invalid: false, // true if image needs to be drawn, false if not
render: renderer, options: options,
data : {} data : {}
}; };
cornerstone.addEnabledElement(el); cornerstone.addEnabledElement(el);
@ -868,11 +873,7 @@ if(typeof cornerstone === 'undefined'){
var start = new Date(); var start = new Date();
if (enabledElement.render) {
enabledElement.render(enabledElement, invalidated);
} else {
enabledElement.image.render(enabledElement, invalidated); enabledElement.image.render(enabledElement, invalidated);
}
var context = enabledElement.canvas.getContext('2d'); var context = enabledElement.canvas.getContext('2d');
@ -1650,7 +1651,17 @@ if(typeof cornerstone === 'undefined'){
context.save(); context.save();
cornerstone.setToPixelCoordinateSystem(enabledElement, context); cornerstone.setToPixelCoordinateSystem(enabledElement, context);
var renderCanvas = getRenderCanvas(enabledElement, image, invalidated); var renderCanvas;
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 = cornerstone.webGL.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); context.drawImage(renderCanvas, 0,0, image.width, image.height, 0, 0, image.width, image.height);
@ -1709,7 +1720,7 @@ if(typeof cornerstone === 'undefined'){
return false; return false;
} }
// check the unique ids // check the unique ids
return (a.id !== b.id) return (a.id !== b.id);
} }
function getLut(image, viewport, invalidated) function getLut(image, viewport, invalidated)
@ -1783,12 +1794,12 @@ if(typeof cornerstone === 'undefined'){
* @param invalidated - true if pixel data has been invaldiated and cached rendering should not be used * @param invalidated - true if pixel data has been invaldiated and cached rendering should not be used
*/ */
function renderGrayscaleImage(enabledElement, invalidated) { function renderGrayscaleImage(enabledElement, invalidated) {
if (enabledElement === undefined) {
if(enabledElement === undefined) {
throw "drawImage: enabledElement parameter must not be undefined"; throw "drawImage: enabledElement parameter must not be undefined";
} }
var image = enabledElement.image; var image = enabledElement.image;
if(image === undefined) { if (image === undefined) {
throw "drawImage: image must be loaded before it can be drawn"; throw "drawImage: image must be loaded before it can be drawn";
} }
@ -1810,10 +1821,20 @@ if(typeof cornerstone === 'undefined'){
context.mozImageSmoothingEnabled = true; context.mozImageSmoothingEnabled = true;
} }
// save the canvas context state and apply the viewport properties // Save the canvas context state and apply the viewport properties
cornerstone.setToPixelCoordinateSystem(enabledElement, context); cornerstone.setToPixelCoordinateSystem(enabledElement, context);
var renderCanvas = getRenderCanvas(enabledElement, image, invalidated); var renderCanvas;
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 = cornerstone.webGL.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);
}
// Draw the render canvas half the image size (because we set origin to the middle of the canvas above) // 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); context.drawImage(renderCanvas, 0,0, image.width, image.height, 0, 0, image.width, image.height);
@ -2228,7 +2249,8 @@ if(typeof cornerstone === 'undefined'){
console.log("WEBGL Renderer already initialized"); console.log("WEBGL Renderer already initialized");
return; return;
} }
if ( initWebGL( renderCanvas ) ) {
if (initWebGL(renderCanvas)) {
initBuffers(); initBuffers();
initShaders(); initShaders();
console.log("WEBGL Renderer initialized!"); console.log("WEBGL Renderer initialized!");
@ -2318,7 +2340,7 @@ if(typeof cornerstone === 'undefined'){
// choosing the shader based on the image datatype // choosing the shader based on the image datatype
// console.log("Datatype: " + datatype); // console.log("Datatype: " + datatype);
if (cornerstone.webGL.shaders.hasOwnProperty(datatype)) { if (cornerstone.webGL.shaders.hasOwnProperty(datatype)) {
return cornerstone.webGL.shaders[ datatype ]; return cornerstone.webGL.shaders[datatype];
} }
var shader = cornerstone.webGL.shaders.rgb; var shader = cornerstone.webGL.shaders.rgb;
@ -2380,7 +2402,6 @@ if(typeof cornerstone === 'undefined'){
} }
function initBuffers() { function initBuffers() {
positionBuffer = gl.createBuffer(); positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
@ -2401,8 +2422,7 @@ if(typeof cornerstone === 'undefined'){
]), gl.STATIC_DRAW); ]), gl.STATIC_DRAW);
} }
function renderQuad(shader, parameters, texture, width, height ) function renderQuad(shader, parameters, texture, width, height) {
{
gl.clearColor(1.0,0.0,0.0,1.0); gl.clearColor(1.0,0.0,0.0,1.0);
gl.viewport( 0, 0, width, height ); gl.viewport( 0, 0, width, height );
@ -2444,37 +2464,11 @@ if(typeof cornerstone === 'undefined'){
} }
function render(enabledElement) { function render(enabledElement) {
if (!enabledElement) {
throw "drawImage: enabledElement parameter must not be undefined";
}
var image = enabledElement.image;
if (!image) {
throw "drawImage: image must be loaded before it can be drawn";
}
// Resize the canvas // Resize the canvas
var image = enabledElement.image;
renderCanvas.width = image.width; renderCanvas.width = image.width;
renderCanvas.height = image.height; renderCanvas.height = image.height;
// 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;
}
var viewport = enabledElement.viewport; var viewport = enabledElement.viewport;
// Render the current image // Render the current image
@ -2482,21 +2476,16 @@ if(typeof cornerstone === 'undefined'){
var texture = getImageTexture(image); var texture = getImageTexture(image);
var parameters = { var parameters = {
"u_resolution": { type: "2f", value: [image.width, image.height] }, "u_resolution": { type: "2f", value: [image.width, image.height] },
"wc": { type: "f", value: enabledElement.viewport.voi.windowCenter }, "wc": { type: "f", value: viewport.voi.windowCenter },
"ww": { type: "f", value: enabledElement.viewport.voi.windowWidth }, "ww": { type: "f", value: viewport.voi.windowWidth },
"slope": { type: "f", value: image.slope }, "slope": { type: "f", value: image.slope },
"intercept": { type: "f", value: image.intercept }, "intercept": { type: "f", value: image.intercept },
//"minPixelValue": { type: "f", value: image.minPixelValue }, //"minPixelValue": { type: "f", value: image.minPixelValue },
"invert": { type: "i", value: enabledElement.viewport.invert ? 1 : 0 }, "invert": { type: "i", value: viewport.invert ? 1 : 0 },
}; };
renderQuad(shader, parameters, texture, image.width, image.height ); renderQuad(shader, parameters, texture, image.width, image.height );
// Save the canvas context state and apply the viewport properties return renderCanvas;
cornerstone.setToPixelCoordinateSystem(enabledElement, context);
// Copy pixels from the offscreen canvas to the onscreen canvas
context.drawImage(renderCanvas, 0,0, image.width, image.height, 0, 0, image.width, image.height);
} }
function isWebGLAvailable() { function isWebGLAvailable() {

View File

@ -130,10 +130,14 @@ function loadSeriesIntoViewport(data, templateData) {
// Enable Cornerstone for the viewport element // Enable Cornerstone for the viewport element
// //
var options = {
renderer: 'webgl'
};
// NOTE: This uses the experimental WebGL renderer for Cornerstone! // NOTE: This uses the experimental WebGL renderer for Cornerstone!
// If you have problems, replace it with this line instead: // If you have problems, replace it with this line instead:
// cornerstone.enable(element); // cornerstone.enable(element);
cornerstone.enable(element, cornerstone.webGL.renderer.render); cornerstone.enable(element, options);
// Get the handler functions that will run when loading has finished or thrown // Get the handler functions that will run when loading has finished or thrown
// an error. These are used to show/hide loading / error text boxes on each viewport. // an error. These are used to show/hide loading / error text boxes on each viewport.