Skip to content

Instantly share code, notes, and snippets.

@rayhu
Created October 18, 2021 22:25
Show Gist options
  • Save rayhu/134cfff0263c7b1543d7fde9a0a0a56d to your computer and use it in GitHub Desktop.
Save rayhu/134cfff0263c7b1543d7fde9a0a0a56d to your computer and use it in GitHub Desktop.
Reference Line
<div>
<div class="buttons">
<button class="button set-tool-mode is-primary" data-action="Active">
Active
</button>
<button class="button set-tool-mode" data-action="Passive">
Passive
</button>
<button class="button set-tool-mode" data-action="Enabled">Enable</button>
<button class="button set-tool-mode" data-action="Disabled">
Disable
</button>
</div>
</div>
<div class="cornerstone-element-wrapper">
<div class="cornerstone-element" id="topgram_element" data-index="0" oncontextmenu="return false" style="touch-action: none; user-select: none; -webkit-user-drag: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);">
<canvas class="cornerstone-canvas" width="668" style="display: block; width: 668px; height: 316px;" height="316">
</canvas>
</div>
<div class="cornerstone-element" id="chest_element" data-index="0" oncontextmenu="return false" style="touch-action: none; user-select: none; -webkit-user-drag: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);">
<canvas class="cornerstone-canvas" width="668" style="display: block; width: 668px; height: 316px;" height="316">
</canvas>
</div>
</div>
<script src="https://unpkg.com/[email protected]/hammer.js"></script>
<script src="https://unpkg.com/[email protected]/dist/dicomParser.min.js"></script>
<!-- include the cornerstone library -->
<script src="https://unpkg.com/cornerstone-core"></script>
<script src="https://unpkg.com/cornerstone-math"></script>
<script src="https://unpkg.com/cornerstone-wado-image-loader"></script>
<!-- Why we're all here ;) -->
<script src="https://unpkg.com/cornerstone-tools@%5E4"></script>
let canvasesReady = false;
let numImagesLoaded = 0;
const firstElement = document.getElementById('topgram_element');
const secondElement = document.getElementById('chest_element');
function addReferenceLinesTool(){
const synchronizer = new cornerstoneTools.Synchronizer(
'cornerstonenewimage',
cornerstoneTools.updateImageSynchronizer
);
// These have to be added to our synchronizer before we pass it to our tool
synchronizer.add(firstElement);
synchronizer.add(secondElement);
cornerstoneTools.addTool(cornerstoneTools.ReferenceLinesTool);
cornerstoneTools.setToolEnabled('ReferenceLines', {
synchronizationContext: synchronizer,
});
}
const handleImageRendered = (evt) => {
evt.detail.element.removeEventListener('cornerstoneimagerendered', handleImageRendered)
numImagesLoaded++;
if(numImagesLoaded === 2){
addReferenceLinesTool();
}
}
firstElement.addEventListener('cornerstoneimagerendered', handleImageRendered)
secondElement.addEventListener('cornerstoneimagerendered', handleImageRendered)
// NOTE: We pull these in from packaged sources in our header,
// but here are the associated NPM packages that can be used instead
// Packages
// import Hammer from 'hammerjs';
// import dicomParser from 'dicom-parser';
// import * as cornerstone from 'cornerstone-core';
// import * as cornerstoneMath from 'cornerstone-math';
// import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader';
// import * as cornerstoneTools from '@cornerstonejs/tools';
const baseUrl =
window.ENVIRONMENT === 'development'
? 'http://localhost:4000/'
: 'https://tools.cornerstonejs.org/examples/';
_initCornerstone();
_initInterface();
const topgramElement = document.getElementById('topgram_element');
const chestElement = document.getElementById('chest_element');
const elements = [topgramElement, chestElement];
// Init CornerstoneTools
cornerstoneTools.init({
globalToolSyncEnabled: true,
});
// image enable the dicomImage element and add canvas to it
elements.forEach(element => {
cornerstone.enable(element);
});
const toolName = 'ReferenceLines';
const topgramImageIds = [
`wadouri:${baseUrl}assets/dicom/bellona/topogram/IM-0001-0001.dcm`,
];
const chestImageIds = new Array();
// up to now it is hard coded 37 chest images
for (let i = 1; i < 37; i++) {
chestImageIds.push(
`wadouri:${baseUrl}assets/dicom/bellona/chest_lung/${i}.dcm`
);
}
const chestStack = {
currentImageIdIndex: 0,
imageIds: chestImageIds,
};
const topgramStack = {
currentImageIdIndex: 0,
imageIds: topgramImageIds,
};
// Add Default tools; set them active
cornerstoneTools.addTool(cornerstoneTools.StackScrollTool);
cornerstoneTools.addTool(cornerstoneTools.StackScrollMouseWheelTool);
cornerstoneTools.setToolActive('StackScroll', { mouseButtonMask: 1 });
cornerstoneTools.setToolActive('StackScrollMouseWheel', {});
loadSeries(cornerstone, chestImageIds, chestElement, chestStack);
loadSeries(cornerstone, topgramImageIds, topgramElement, topgramStack);
function loadSeries(cornerstone, imageIds, element, stack) {
// Cache all images and metadata
imageIds.forEach(imageId => cornerstone.loadAndCacheImage(imageId));
// Load and display first image in stack
return cornerstone.loadImage(imageIds[0]).then(image => {
// display this image
cornerstone.displayImage(element, image);
// set the stack as tool state
cornerstoneTools.addStackStateManager(element, ['stack', toolName]);
cornerstoneTools.addToolState(element, 'stack', stack);
});
}
/***************************************************************************
* UI & Boilerplate setup code
**************************************************************************/
/***
*
*
*/
function _initCornerstone() {
// Externals
cornerstoneWADOImageLoader.external.cornerstone = cornerstone;
cornerstoneWADOImageLoader.external.dicomParser = dicomParser;
cornerstoneTools.external.cornerstoneMath = cornerstoneMath;
cornerstoneTools.external.cornerstone = cornerstone;
cornerstoneTools.external.Hammer = Hammer;
// Image Loader
const config = {
webWorkerPath: `${baseUrl}assets/image-loader/cornerstoneWADOImageLoaderWebWorker.js`,
taskConfiguration: {
decodeTask: {
codecsPath: `${baseUrl}assets/image-loader/cornerstoneWADOImageLoaderCodecs.js`,
},
},
};
cornerstoneWADOImageLoader.webWorkerManager.initialize(config);
}
/***
*
*
*/
function _initInterface() {
const handleClick = function(evt) {
const action = this.dataset.action;
const options = {
mouseButtonMask:
evt.buttons || convertMouseEventWhichToButtons(evt.which),
};
cornerstoneTools[`setTool${action}`](toolName, options);
// Remove active style from all buttons
const buttons = document.querySelectorAll('.set-tool-mode');
buttons.forEach(btn => {
btn.classList.remove('is-primary');
});
// Add active style to this button
this.classList.add('is-primary');
evt.preventDefault();
evt.stopPropagation();
evt.stopImmediatePropagation();
return false;
};
const buttons = document.querySelectorAll('.set-tool-mode');
buttons.forEach(btn => {
btn.addEventListener('contextmenu', handleClick);
btn.addEventListener('auxclick', handleClick);
btn.addEventListener('click', handleClick);
});
}
const convertMouseEventWhichToButtons = which => {
switch (which) {
// no button
case 0:
return 0;
// left
case 1:
return 1;
// middle
case 2:
return 4;
// right
case 3:
return 2;
}
return 0;
};
.active-mode {
color: red;
}
.cornerstone-element-wrapper {
width: 100%;
margin: 15px auto 35px auto;
height: calc(100% - 130px);
position: relative;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
}
.cornerstone-element {
display: block;
position: relative;
width: 100%;
height: 100%;
flex-basis: 320px;
min-width: 320px;
min-height: 320px;
flex-grow: 1;
border: 2px solid rgb(0, 164, 217);
}
.highlight {
margin-top: 15px;
margin-bottom: 15px;
}
/* Custom Buttons */
button.button.set-tool-mode {
-webkit-transition: background-color 0.5s;
transition: background-color 0.5s;
}
.row-label {
margin: 0 20px 0 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment