Skip to content

Commit

Permalink
feat(OverlayTool): Support for rendering DICOM Group 6xxx Overlay Pla…
Browse files Browse the repository at this point in the history
…ne layers on top of the image (#860) - Thanks @kofifus, @jdnarvaez

* feat(OverlayTool): Support for rendering overlay layers on top of the image data

See DICOM: http://dicom.nema.org/dicom/2013/output/chtml/part03/sect_C.9.html

re #780

* Add OverlayTool exports

* Add overlay tool to examples

* Make sure enabledElement is defined

* Capitalize data-tool; better tool toggling

* lowercase first letter 👍

* Use @cornerstonejs org scope

* dry run; finding tag and publishing feature/hotfix branches as tagged releases

* Change workflow priority

* filtering is regex

* Fix bash syntax error

* invoke script w/ bash

* Playing w/ bash syntax in circleCI's environment

* Public scoped packages

* Publish a tagged package

* Make sure we're not stealing a version number that can be used for master

* Better RegExp to set version

* Tidying up comments and formatting

* Try using an alternative package version

* Update OverlayTool.js

* Update OverlayTool.js

* Fix prettier build error

* Protect against `null` viewport pixelSpacing

* Remove unnecessary changes

* Fix unnecessary changes

* Fixes for rendering overlays

Co-authored-by: Kofifus <[email protected]>
Co-authored-by: Erik Ziegler <[email protected]>
  • Loading branch information
3 people committed Jan 28, 2020
1 parent 32af3d9 commit 4eef070
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 1 deletion.
13 changes: 12 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,14 @@
<input id="scaleOverlayCheckbox" class="hide" data-tool="ScaleOverlay" data-tool-type="none"
type="checkbox" />
</li>
<li>
<label id="overlay" class="checkbox-label" for="overlayCheckbox">
Overlay <label class="label-on"> ON</label>
<label class="label-off"> OFF</label>
</label>
<input id="overlayCheckbox" class="hide" data-tool="Overlay" data-tool-type="none"
type="checkbox" />
</li>
</ul>

<!-- Our beautiful element targets -->
Expand Down Expand Up @@ -361,7 +369,10 @@
} else {
cornerstoneTools.setToolDisabled(toolName);
}
const toolLabel = document.querySelector('#scaleOverlay');

const toolLabelId =
toolName.charAt(0).toLowerCase() + toolName.slice(1);
const toolLabel = document.querySelector(`#${toolLabelId}`); //scaleOverlay or overlay
toolLabel.classList.toggle('turned-on');
});
});
Expand Down
3 changes: 3 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ import {
EraserTool,
FreehandRoiSculptorTool,
MagnifyTool,
OverlayTool,
OrientationMarkersTool,
PanMultiTouchTool,
PanTool,
Expand Down Expand Up @@ -238,6 +239,7 @@ const cornerstoneTools = {
EraserTool,
FreehandRoiSculptorTool,
MagnifyTool,
OverlayTool,
OrientationMarkersTool,
PanMultiTouchTool,
PanTool,
Expand Down Expand Up @@ -346,6 +348,7 @@ export {
EraserTool,
FreehandRoiSculptorTool,
MagnifyTool,
OverlayTool,
OrientationMarkersTool,
PanMultiTouchTool,
PanTool,
Expand Down
110 changes: 110 additions & 0 deletions src/tools/OverlayTool.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import external from '../externalModules.js';
import BaseTool from './base/BaseTool.js';

/**
*
* http://dicom.nema.org/dicom/2013/output/chtml/part03/sect_C.9.html
*
* @public
* @class Overlay
* @memberof Tools
*
* @classdesc Tool for displaying a scale overlay on the image.
* @extends Tools.Base.BaseTool
*/
export default class OverlayTool extends BaseTool {
constructor(configuration = {}) {
const defaultConfig = {
name: 'Overlay',
configuration: {},
mixins: ['enabledOrDisabledBinaryTool'],
};
const initialConfiguration = Object.assign(defaultConfig, configuration);

super(initialConfiguration);

this.initialConfiguration = initialConfiguration;
}

enabledCallback(element) {
this.forceImageUpdate(element);
}

disabledCallback(element) {
this.forceImageUpdate(element);
}

forceImageUpdate(element) {
const enabledElement = external.cornerstone.getEnabledElement(element);

if (enabledElement.image) {
external.cornerstone.updateImage(element);
}
}

renderToolData(evt) {
const eventData = evt.detail;
const { enabledElement, image, viewport, canvasContext } = eventData;

if (!eventData || !enabledElement || !image) {
return;
}

const overlayPlaneMetadata = external.cornerstone.metaData.get(
'overlayPlaneModule',
image.imageId
);

if (
!overlayPlaneMetadata ||
!overlayPlaneMetadata.overlays ||
!overlayPlaneMetadata.overlays.length
) {
return;
}

const viewportPixelSpacing = {
column: viewport.displayedArea.columnPixelSpacing || 1,
row: viewport.displayedArea.rowPixelSpacing || 1,
};
const imageWidth =
Math.abs(viewport.displayedArea.brhc.x - viewport.displayedArea.tlhc.x) *
viewportPixelSpacing.column;
const imageHeight =
Math.abs(viewport.displayedArea.brhc.y - viewport.displayedArea.tlhc.y) *
viewportPixelSpacing.row;

overlayPlaneMetadata.overlays.forEach(overlay => {
if (overlay.visible === false) {
return;
}

const layerCanvas = document.createElement('canvas');

layerCanvas.width = imageWidth;
layerCanvas.height = imageHeight;

const layerContext = layerCanvas.getContext('2d');

layerContext.fillStyle = overlay.fillStyle || 'white';

if (overlay.type === 'R') {
layerContext.fillRect(0, 0, layerCanvas.width, layerCanvas.height);
layerContext.globalCompositeOperation = 'xor';
}

let i = 0;

for (let y = 0; y < overlay.rows; y++) {
for (let x = 0; x < overlay.columns; x++) {
if (overlay.pixelData[i++] > 0) {
layerContext.fillRect(x, y, 1, 1);
}
}
}

// Draw the overlay layer onto the canvas
canvasContext.drawImage(layerCanvas, 0, 0);
});
}
}
3 changes: 3 additions & 0 deletions src/tools/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import DragProbeTool from './DragProbeTool.js';
import EraserTool from './EraserTool.js';
import FreehandRoiSculptorTool from './FreehandRoiSculptorTool.js';
import MagnifyTool from './MagnifyTool.js';
import OverlayTool from './OverlayTool.js';
import OrientationMarkersTool from './OrientationMarkersTool.js';
import PanMultiTouchTool from './PanMultiTouchTool.js';
import PanTool from './PanTool.js';
Expand All @@ -28,6 +29,7 @@ export {
EraserTool,
FreehandRoiSculptorTool,
MagnifyTool,
OverlayTool,
OrientationMarkersTool,
PanMultiTouchTool,
PanTool,
Expand All @@ -53,6 +55,7 @@ export default {
EraserTool,
FreehandRoiSculptorTool,
MagnifyTool,
OverlayTool,
OrientationMarkersTool,
PanMultiTouchTool,
PanTool,
Expand Down

0 comments on commit 4eef070

Please sign in to comment.