Skip to content

Commit

Permalink
Fix for rotation bug on non square pixel images
Browse files Browse the repository at this point in the history
added getImage api to return image currently displayed in an element
  • Loading branch information
chafey committed May 30, 2015
1 parent d83dc6f commit 52425b9
Show file tree
Hide file tree
Showing 11 changed files with 187 additions and 95 deletions.
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cornerstone",
"version": "0.7.3",
"version": "0.7.4",
"description": "HTML5 Medical Image Viewer Component",
"main" : "dist/cornerstone.js",
"ignore": [
Expand Down
2 changes: 1 addition & 1 deletion dist/cornerstone.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*! cornerstone - v0.7.3 - 2015-05-20 | (c) 2014 Chris Hafey | https://github.com/chafey/cornerstone */
/*! cornerstone - v0.7.4 - 2015-05-30 | (c) 2014 Chris Hafey | https://github.com/chafey/cornerstone */
.cornerstone-enabled-image {

/* prevent text selection from occurring when dragging the mouse on the div */
Expand Down
104 changes: 63 additions & 41 deletions dist/cornerstone.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*! cornerstone - v0.7.3 - 2015-05-20 | (c) 2014 Chris Hafey | https://github.com/chafey/cornerstone */
/*! cornerstone - v0.7.4 - 2015-05-30 | (c) 2014 Chris Hafey | https://github.com/chafey/cornerstone */
var cornerstone = (function (cornerstone) {

"use strict";
Expand Down Expand Up @@ -507,6 +507,34 @@ var cornerstone = (function (cornerstone) {
return cornerstone;
}(cornerstone));

/**
* This module is responsible for returning the currently displayed image for an element
*/

var cornerstone = (function ($, cornerstone) {

"use strict";

if(cornerstone === undefined) {
cornerstone = {};
}

/**
* returns the currently displayed image for an element or undefined if no image has
* been displayed yet
*
* @param element
*/
function getImage(element) {
var enabledElement = cornerstone.getEnabledElement(element);
return enabledElement.image;
}

// Module exports
cornerstone.getImage = getImage;

return cornerstone;
}($, cornerstone));
/**
* This module returns a subset of the stored pixels of an image
*/
Expand Down Expand Up @@ -1491,71 +1519,65 @@ var cornerstone = (function (cornerstone) {
// reset the transformation matrix
context.setTransform(1, 0, 0, 1, 0, 0);
// move origin to center of canvas
context.translate(enabledElement.canvas.width / 2, enabledElement.canvas.height / 2);
context.translate(enabledElement.canvas.width/2, enabledElement.canvas.height / 2);

var image = enabledElement.image;
var viewport = enabledElement.viewport;
//Apply the rotation before scaling for non square pixels
var angle = enabledElement.viewport.rotation;
if(angle!==0) {
context.rotate(angle*Math.PI/180);
}

// apply the scale
var widthScale = viewport.scale;
var heightScale = viewport.scale;

if(viewport.rotation === 90 || viewport.rotation === 270 || viewport.rotation === -90 || viewport.rotation === -270) {
if(image.rowPixelSpacing < image.columnPixelSpacing) {
widthScale = heightScale * (image.rowPixelSpacing / image.columnPixelSpacing);
}
else if(image.columnPixelSpacing < image.rowPixelSpacing) {
heightScale = widthScale * (image.columnPixelSpacing / image.rowPixelSpacing);
}
} else {
if(image.rowPixelSpacing < image.columnPixelSpacing) {
widthScale = widthScale * (image.columnPixelSpacing / image.rowPixelSpacing);
}
else if(image.columnPixelSpacing < image.rowPixelSpacing) {
heightScale = heightScale * (image.rowPixelSpacing / image.columnPixelSpacing);
}
var widthScale = enabledElement.viewport.scale;
var heightScale = enabledElement.viewport.scale;
if(enabledElement.image.rowPixelSpacing < enabledElement.image.columnPixelSpacing) {
widthScale = widthScale * (enabledElement.image.columnPixelSpacing / enabledElement.image.rowPixelSpacing);
}
else if(enabledElement.image.columnPixelSpacing < enabledElement.image.rowPixelSpacing) {
heightScale = heightScale * (enabledElement.image.rowPixelSpacing / enabledElement.image.columnPixelSpacing);
}

context.scale(widthScale, heightScale);

// unrotate to so we can translate unrotated
if(angle!==0) {
context.rotate(-angle*Math.PI/180);
}

// apply the pan offset
context.translate(viewport.translation.x, viewport.translation.y);
context.translate(enabledElement.viewport.translation.x, enabledElement.viewport.translation.y);

// rotate again so we can apply general scale
if(angle!==0) {
context.rotate(angle*Math.PI/180);
}

if(scale === undefined) {
scale = 1.0;
} else {
// apply the font scale
context.scale(scale, scale);
}

//Apply if rotation required
var angle = viewport.rotation;

if (angle !== 0) {
context.rotate(angle * Math.PI / 180);
}
//Apply Flip if required
if(enabledElement.viewport.hflip) {
context.translate(enabledElement.offsetWidth,0);
context.scale(-1,1);
}

//Apply Flip if required
if (viewport.hflip) {
context.translate(enabledElement.offsetWidth,0);
context.scale(-1, 1);
}
if(enabledElement.viewport.vflip) {
context.translate(0, enabledElement.offsetHeight);
context.scale(1,-1);
}

if (viewport.vflip) {
context.translate(0, enabledElement.offsetHeight);
context.scale(1, -1);
}

// translate the origin back to the corner of the image so the event handlers can draw in image coordinate system
context.translate(-image.width / 2 / scale, -image.height / 2 / scale);
context.translate(-enabledElement.image.width / 2 / scale, -enabledElement.image.height/ 2 / scale);
}

// Module exports
cornerstone.setToPixelCoordinateSystem = setToPixelCoordinateSystem;

return cornerstone;
}(cornerstone));

/**
* This module contains a function to convert stored pixel values to display pixel values using a LUT
*/
Expand Down
2 changes: 1 addition & 1 deletion dist/cornerstone.min.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions dist/cornerstone.min.js

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions example/jquery.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion example/jquery.min.map

Large diffs are not rendered by default.

47 changes: 47 additions & 0 deletions example/nonSquarePixels/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ <h1>
<br>
<br>

<button id="hFlip" type="button" class="btn btn-default">HFlip</button>
<button id="vFlip" type="button" class="btn btn-default">VFlip</button>
<button id="lRotate" type="button" class="btn btn-default">Rotate Left</button>
<button id="rRotate" type="button" class="btn btn-default">Rotate Right</button>
<button id="reset" type="button" class="btn btn-default">Reset</button>
<div><span id="coords"></span></div>

<div id="dicomImage" style="width:512px;height:512px;"
class="cornerstone-enabled-image"
oncontextmenu="return false"
Expand Down Expand Up @@ -124,6 +131,46 @@ <h1>
cornerstone.displayImage(element, image);
});

// Add event handlers to flip or rotate the image
$('#hFlip').click(function (e) {
var viewport = cornerstone.getViewport(element);
viewport.hflip = !viewport.hflip;
cornerstone.setViewport(element, viewport);
});

$('#vFlip').click(function (e) {
var viewport = cornerstone.getViewport(element);
viewport.vflip = !viewport.vflip;
cornerstone.setViewport(element, viewport);
});

$('#lRotate').click(function (e) {
var viewport = cornerstone.getViewport(element);
viewport.rotation-=90;
cornerstone.setViewport(element, viewport);
});

$('#rRotate').click(function (e) {
var viewport = cornerstone.getViewport(element);
viewport.rotation+=90;
cornerstone.setViewport(element, viewport);
});

$('#reset').click(function (e) {
var viewport = cornerstone.getViewport(element);
viewport.hflip = false;
viewport.vflip = false;
viewport.rotation = 0;
cornerstone.setViewport(element, viewport);
});
$(element).mousemove(function(event)
{
var pixelCoords = cornerstone.pageToPixel(element, event.pageX, event.pageY);
var x = event.pageX;
var y = event.pageY;
$('#coords').text("pageX=" + event.pageX + ", pageY=" + event.pageY + ", pixelX=" + pixelCoords.x + ", pixelY=" + pixelCoords.y);
});

});

</script>
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cornerstone",
"version": "0.7.3",
"version": "0.7.4",
"description": "HTML5 Medical Image Viewer Component",
"keywords": [
"DICOM",
Expand Down
28 changes: 28 additions & 0 deletions src/getImage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* This module is responsible for returning the currently displayed image for an element
*/

var cornerstone = (function ($, cornerstone) {

"use strict";

if(cornerstone === undefined) {
cornerstone = {};
}

/**
* returns the currently displayed image for an element or undefined if no image has
* been displayed yet
*
* @param element
*/
function getImage(element) {
var enabledElement = cornerstone.getEnabledElement(element);
return enabledElement.image;
}

// Module exports
cornerstone.getImage = getImage;

return cornerstone;
}($, cornerstone));
81 changes: 38 additions & 43 deletions src/setToPixelCoordinateSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,67 +30,62 @@ var cornerstone = (function (cornerstone) {
// reset the transformation matrix
context.setTransform(1, 0, 0, 1, 0, 0);
// move origin to center of canvas
context.translate(enabledElement.canvas.width / 2, enabledElement.canvas.height / 2);
context.translate(enabledElement.canvas.width/2, enabledElement.canvas.height / 2);

var image = enabledElement.image;
var viewport = enabledElement.viewport;
//Apply the rotation before scaling for non square pixels
var angle = enabledElement.viewport.rotation;
if(angle!==0) {
context.rotate(angle*Math.PI/180);
}

// apply the scale
var widthScale = viewport.scale;
var heightScale = viewport.scale;

if(viewport.rotation === 90 || viewport.rotation === 270 || viewport.rotation === -90 || viewport.rotation === -270) {
if(image.rowPixelSpacing < image.columnPixelSpacing) {
widthScale = heightScale * (image.rowPixelSpacing / image.columnPixelSpacing);
}
else if(image.columnPixelSpacing < image.rowPixelSpacing) {
heightScale = widthScale * (image.columnPixelSpacing / image.rowPixelSpacing);
}
} else {
if(image.rowPixelSpacing < image.columnPixelSpacing) {
widthScale = widthScale * (image.columnPixelSpacing / image.rowPixelSpacing);
}
else if(image.columnPixelSpacing < image.rowPixelSpacing) {
heightScale = heightScale * (image.rowPixelSpacing / image.columnPixelSpacing);
}
var widthScale = enabledElement.viewport.scale;
var heightScale = enabledElement.viewport.scale;
if(enabledElement.image.rowPixelSpacing < enabledElement.image.columnPixelSpacing) {
widthScale = widthScale * (enabledElement.image.columnPixelSpacing / enabledElement.image.rowPixelSpacing);
}
else if(enabledElement.image.columnPixelSpacing < enabledElement.image.rowPixelSpacing) {
heightScale = heightScale * (enabledElement.image.rowPixelSpacing / enabledElement.image.columnPixelSpacing);
}

context.scale(widthScale, heightScale);

// unrotate to so we can translate unrotated
if(angle!==0) {
context.rotate(-angle*Math.PI/180);
}

// apply the pan offset
context.translate(viewport.translation.x, viewport.translation.y);
context.translate(enabledElement.viewport.translation.x, enabledElement.viewport.translation.y);

// rotate again so we can apply general scale
if(angle!==0) {
context.rotate(angle*Math.PI/180);
}

if(scale === undefined) {
scale = 1.0;
} else {
// apply the font scale
context.scale(scale, scale);
}

//Apply if rotation required
var angle = viewport.rotation;

if (angle !== 0) {
context.rotate(angle * Math.PI / 180);
}

//Apply Flip if required
if (viewport.hflip) {
context.translate(enabledElement.offsetWidth,0);
context.scale(-1, 1);
}

if (viewport.vflip) {
context.translate(0, enabledElement.offsetHeight);
context.scale(1, -1);
}


//Apply Flip if required
if(enabledElement.viewport.hflip) {
context.translate(enabledElement.offsetWidth,0);
context.scale(-1,1);
}

if(enabledElement.viewport.vflip) {
context.translate(0, enabledElement.offsetHeight);
context.scale(1,-1);
}

// translate the origin back to the corner of the image so the event handlers can draw in image coordinate system
context.translate(-image.width / 2 / scale, -image.height / 2 / scale);
context.translate(-enabledElement.image.width / 2 / scale, -enabledElement.image.height/ 2 / scale);
}

// Module exports
cornerstone.setToPixelCoordinateSystem = setToPixelCoordinateSystem;

return cornerstone;
}(cornerstone));
}(cornerstone));

0 comments on commit 52425b9

Please sign in to comment.