@cleerlycode/cornerstone-wado-image-loader
Version:
Cornerstone ImageLoader for DICOM WADO-URI
364 lines (326 loc) • 18.3 kB
HTML
<html>
<head>
<!-- twitter bootstrap CSS stylesheet - included to make things pretty, not needed or used by cornerstone -->
<link href="../bootstrap.min.css" rel="stylesheet">
<link href="../cornerstone.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="page-header">
<h1>Example of displaying a DICOM P10 image using Cornerstone</h1>
<p class="lead">
Enter a URL for a DICOM P10 object below to view it using cornerstone.
<button id='toggleCollapseInfo' class="btn btn-primary" type="button">
Click for more info
</button>
</p>
<ul>
<!--
<li>/cornerstoneWADOImageLoader/examples/testImages/ile/gray16.DCM</li>
<li>/cornerstoneWADOImageLoader/examples/testImages/ile/gray8.DCM</li>
<li>/cornerstoneWADOImageLoader/examples/testImages/ile/ybrFull.DCM</li>
<li>/cornerstoneWADOImageLoader/examples/testImages/rle/paletteColor.dcm</li>
<li>/cornerstoneWADOImageLoader/examples/testImages/rle/gray16.dcm</li>
<li>/cornerstoneWADOImageLoader/examples/testImages/rle/rgb.dcm</li>
<li>/cornerstoneWADOImageLoader/examples/testImages/rle/multiframe.dcm</li>
<li>/cornerstoneWADOImageLoader/examples/testImages/jpeg.50/ybrFull.dcm</li>
<li>/cornerstoneWADOImageLoader/examples/testImages/jpeg.50/ybrFull422.dcm</li>
<li>/cornerstoneWADOImageLoader/examples/testImages/jpeg.50/gray8.dcm</li>
<li>/cornerstoneWADOImageLoader/examples/testImages/jpeg.50/multiframe.dcm</li>
<li>/cornerstoneWADOImageLoader/examples/testImages/jpeg.51/grayu16.dcm</li>
<li>/cornerstoneWADOImageLoader/examples/testImages/jpeg.57/grayu16.dcm</li>
<li>/cornerstoneWADOImageLoader/examples/testImages/jpeg.70/gray8.dcm</li>
<li>/cornerstoneWADOImageLoader/examples/testImages/jpeg.70/grays16.dcm</li>
<li>/cornerstoneWADOImageLoader/examples/testImages/jpeg2000.90/grayu16.dcm</li>
<li>/cornerstoneWADOImageLoader/examples/testImages/jpeg2000.90/grays16.dcm</li>
<li>/cornerstoneWADOImageLoader/examples/testImages/jpeg2000.90/ybrrct.dcm</li>
<li>/cornerstoneWADOImageLoader/examples/testImages/jpeg2000.91/grays16.dcm</li>
<li>/cornerstoneWADOImageLoader/examples/testImages/jpeg2000.91/grayu16.dcm</li>
<li>/cornerstoneWADOImageLoader/examples/testImages/jpeg2000.91/ybrict.dcm</li>
-->
</ul>
</div>
<div id="collapseInfo" class="collapse" style="display:none;">
<p>
This example illustrates how to use the cornerstoneWADOImageLoader to get a DICOM P10
SOP instance using HTTP and display it in your web browser using cornerstone.
Not all transfer syntaxes are currently supported,
<a href="https://github.com/cornerstonejs/cornerstoneWADOImageLoader/blob/master/docs/TransferSyntaxes.md">
click here for the full list.
</a>
For WADO-URI requests,
you can request that the server return the SOP Instance in explicit little endian by
appending the following query string to your URL:
<code>&transferSyntax=1.2.840.10008.1.2.1</code>
</p>
<P>
Use the query string parameter <i>frame</i> to specify which frame to display from a multiframe
object (defaults to the first frame if not specified). <code>?frame=2</code>
</P>
<strong>If you get an HTTP error and your URL is correct, it is probably because the server is not configured to
allow <a href="http://en.wikipedia.org/wiki/Cross-origin_resource_sharing">Cross Origin Requests</a>.
Most browsers will allow you to enable cross domain requests via settings or command line switches,
you can start chrome with the command line switch <code>--disable-web-security</code> to allow cross origin requests.
See the <a href="http://enable-cors.org/">Enable CORS site</a> for information about CORS.
</strong>
<br>
<br>
<p>
Looking for a CORS proxy? Try <a href="https://www.npmjs.com/package/corsproxy">CORSProxy</a>
</p>
<strong>Use of this example require IE10+ or any other modern browser.</strong>
<hr>
</div>
<div id="loadProgress">Image Load Progress:</div>
<div class="row">
<form id="form" class="form-horizontal">
<div class="form-group">
<label class="control-label col-sm-1" for="wadoURL">URL</label>
<div class="col-sm-8">
<input class="form-control" type="text" id="wadoURL" placeholder="Enter WADO URL" value="https://raw.githubusercontent.com/cornerstonejs/cornerstoneWADOImageLoader/master/testImages/CT2_J2KR">
</div>
<div class="col-sm-3">
<button class="form-control" type="button" id="downloadAndView" class="btn btn-primary">Download and View</button>
</div>
</div>
<div class="form-group">
<div class="col-sm-2">
<button class="form-control" type="button" id="load" class="btn btn-primary">Load</button>
</div>
<div class="col-sm-2">
<button class="form-control" type="button" id="unload" class="btn btn-primary">Unload</button>
</div>
<div class="col-sm-2">
<button class="form-control" type="button" id="purge" class="btn btn-primary">Purge Cache</button>
</div>
</div>
</form>
</div>
<input type="checkbox" id="toggleModalityLUT">Apply Modality LUT</input>
<input type="checkbox" id="toggleVOILUT">Apply VOI LUT</input>
<br>
<div class="row">
<div class="col-md-6">
<div style="width:512px;height:512px;position:relative;color: white;display:inline-block;border-style:solid;border-color:black;"
oncontextmenu="return false"
class='disable-selection noIbar'
unselectable='on'
onselectstart='return false;'
onmousedown='return false;'>
<div id="dicomImage"
style="width:512px;height:512px;top:0px;left:0px; position:absolute">
</div>
</div>
</div>
<div class="col-md-6">
<span>Transfer Syntax: </span><span id="transferSyntax"></span><br>
<span>SOP Class: </span><span id="sopClass"></span><br>
<span>Samples Per Pixel: </span><span id="samplesPerPixel"></span><br>
<span>Photometric Interpretation: </span><span id="photometricInterpretation"></span><br>
<span>Number Of Frames: </span><span id="numberOfFrames"></span><br>
<span>Planar Configuration: </span><span id="planarConfiguration"></span><br>
<span>Rows: </span><span id="rows"></span><br>
<span>Columns: </span><span id="columns"></span><br>
<span>Pixel Spacing: </span><span id="pixelSpacing"></span><br>
<span>Bits Allocated: </span><span id="bitsAllocated"></span><br>
<span>Bits Stored: </span><span id="bitsStored"></span><br>
<span>High Bit: </span><span id="highBit"></span><br>
<span>Pixel Representation: </span><span id="pixelRepresentation"></span><br>
<span>WindowCenter: </span><span id="windowCenter"></span><br>
<span>WindowWidth: </span><span id="windowWidth"></span><br>
<span>RescaleIntercept: </span><span id="rescaleIntercept"></span><br>
<span>RescaleSlope: </span><span id="rescaleSlope"></span><br>
<span>Basic Offset Table Entries: </span><span id="basicOffsetTable"></span><br>
<span>Fragments: </span><span id="fragments"></span><br>
<span>Max Stored Pixel Value: </span><span id="minStoredPixelValue"></span><br>
<span>Min Stored Pixel Value: </span><span id="maxStoredPixelValue"></span><br>
<span>Total Time: </span><span id="totalTime"></span><br>
<span>Load Time: </span><span id="loadTime"></span><br>
<span>Decode Time: </span><span id="decodeTime"></span><br>
</div>
</div>
</div>
</body>
<!-- include the cornerstone library -->
<script src="../cornerstone.min.js"></script>
<SCRIPT src="../cornerstoneMath.min.js"></SCRIPT>
<SCRIPT src="../cornerstoneTools.min.js"></SCRIPT>
<!-- include the dicomParser library as the WADO image loader depends on it -->
<script src="../dicomParser.min.js"></script>
<!-- BEGIN Optional Codecs -->
<!-- OpenJPEG based jpeg 2000 codec -->
<script src="../../codecs/openJPEG-FixedMemory.js"></script>
<!-- PDF.js based jpeg 2000 codec -->
<!-- NOTE: do not load the OpenJPEG codec if you use this one -->
<!-- <script src="../../codecs/jpx.min.js"></script> -->
<!-- JPEG-LS codec -->
<script src="../../codecs/charLS-FixedMemory-browser.js"></script>
<!-- JPEG Lossless codec -->
<script src="../../codecs/jpegLossless.js"></script>
<!-- JPEG Baseline codec -->
<script src="../../codecs/jpeg.js"></script>
<!-- Deflate transfer syntax codec -->
<script src="../../codecs/pako.min.js"></script>
<!-- END Optional Codecs -->
<!-- include the cornerstoneWADOImageLoader library -->
<script src="../../dist/cornerstoneWADOImageLoader.js"></script>
<script src="../dicomfile/uids.js"></script>
<script>
cornerstoneWADOImageLoader.external.cornerstone = cornerstone;
cornerstoneWADOImageLoader.configure({
beforeSend: function(xhr) {
// Add custom headers here (e.g. auth tokens)
//xhr.setRequestHeader('APIKEY', 'my auth token');
}
});
var loaded = false;
function loadAndViewImage(imageId) {
var element = document.getElementById('dicomImage');
try {
var start = new Date().getTime();
cornerstone.loadAndCacheImage(imageId).then(function(image) {
console.log(image);
var viewport = cornerstone.getDefaultViewportForImage(element, image);
document.getElementById('toggleModalityLUT').checked = (viewport.modalityLUT !== undefined);
document.getElementById('toggleVOILUT').checked = (viewport.voiLUT !== undefined);
cornerstone.displayImage(element, image, viewport);
if(loaded === false) {
cornerstoneTools.mouseInput.enable(element);
cornerstoneTools.mouseWheelInput.enable(element);
cornerstoneTools.wwwc.activate(element, 1); // ww/wc is the default tool for left mouse button
cornerstoneTools.pan.activate(element, 2); // pan is the default tool for middle mouse button
cornerstoneTools.zoom.activate(element, 4); // zoom is the default tool for right mouse button
cornerstoneTools.zoomWheel.activate(element); // zoom is the default tool for middle mouse wheel
loaded = true;
}
function getTransferSyntax() {
const value = image.data.string('x00020010');
return value + ' [' + uids[value] + ']';
}
function getSopClass() {
const value = image.data.string('x00080016');
return value + ' [' + uids[value] + ']';
}
function getPixelRepresentation() {
const value = image.data.uint16('x00280103');
if(value === undefined) {
return;
}
return value + (value === 0 ? ' (unsigned)' : ' (signed)');
}
function getPlanarConfiguration() {
const value = image.data.uint16('x00280006');
if(value === undefined) {
return;
}
return value + (value === 0 ? ' (pixel)' : ' (plane)');
}
document.getElementById('transferSyntax').textContent = getTransferSyntax();
document.getElementById('sopClass').textContent = getSopClass();
document.getElementById('samplesPerPixel').textContent = image.data.uint16('x00280002');
document.getElementById('photometricInterpretation').textContent = image.data.string('x00280004');
document.getElementById('numberOfFrames').textContent = image.data.string('x00280008');
document.getElementById('planarConfiguration').textContent = getPlanarConfiguration();
document.getElementById('rows').textContent = image.data.uint16('x00280010');
document.getElementById('columns').textContent = image.data.uint16('x00280011');
document.getElementById('pixelSpacing').textContent = image.data.string('x00280030');
document.getElementById('bitsAllocated').textContent = image.data.uint16('x00280100');
document.getElementById('bitsStored').textContent = image.data.uint16('x00280101');
document.getElementById('highBit').textContent = image.data.uint16('x00280102');
document.getElementById('pixelRepresentation').textContent = getPixelRepresentation();
document.getElementById('windowCenter').textContent = image.data.string('x00281050');
document.getElementById('windowWidth').textContent = image.data.string('x00281051');
document.getElementById('rescaleIntercept').textContent = image.data.string('x00281052');
document.getElementById('rescaleSlope').textContent = image.data.string('x00281053');
document.getElementById('basicOffsetTable').textContent = image.data.elements.x7fe00010.basicOffsetTable ? image.data.elements.x7fe00010.basicOffsetTable.length : '';
document.getElementById('fragments').textContent = image.data.elements.x7fe00010.fragments ? image.data.elements.x7fe00010.fragments.length : '';
document.getElementById('minStoredPixelValue').textContent = image.minPixelValue;
document.getElementById('maxStoredPixelValue').textContent = image.maxPixelValue;
var end = new Date().getTime();
var time = end - start;
document.getElementById('totalTime').textContent = time + "ms";
document.getElementById('loadTime').textContent = image.loadTimeInMS + "ms";
document.getElementById('decodeTime').textContent = image.decodeTimeInMS + "ms";
}, function(err) {
alert(err);
});
}
catch(err) {
alert(err);
}
}
function downloadAndView() {
let url = document.getElementById('wadoURL').value;
// prefix the url with wadouri: so cornerstone can find the image loader
url = "wadouri:" + url;
// image enable the dicomImage element and activate a few tools
loadAndViewImage(url);
}
cornerstone.events.addEventListener('cornerstoneimageloadprogress', function(event) {
const eventData = event.detail;
const loadProgress = document.getElementById('loadProgress');
loadProgress.textContent = `Image Load Progress: ${eventData.percentComplete}%`;
});
function getUrlWithoutFrame() {
var url = document.getElementById('wadoURL').value;
var frameIndex = url.indexOf('frame=');
if(frameIndex !== -1) {
url = url.substr(0, frameIndex-1);
}
return url;
}
var element = document.getElementById('dicomImage');
cornerstone.enable(element);
document.getElementById('downloadAndView').addEventListener('click', function(e) {
downloadAndView();
});
document.getElementById('load').addEventListener('click', function(e) {
var url = getUrlWithoutFrame();
cornerstoneWADOImageLoader.wadouri.dataSetCacheManager.load(url);
});
document.getElementById('unload').addEventListener('click', function(e) {
var url = getUrlWithoutFrame();
cornerstoneWADOImageLoader.wadouri.dataSetCacheManager.unload(url);
});
document.getElementById('purge').addEventListener('click', function(e) {
cornerstone.imageCache.purgeCache();
});
const form = document.getElementById('form');
form.addEventListener('submit', function() {
downloadAndView();
return false;
});
document.getElementById('toggleModalityLUT').addEventListener('click', function() {
var applyModalityLUT = document.getElementById('toggleModalityLUT').checked;
console.log('applyModalityLUT=', applyModalityLUT);
var image = cornerstone.getImage(element);
var viewport = cornerstone.getViewport(element);
if(applyModalityLUT) {
viewport.modalityLUT = image.modalityLUT;
} else {
viewport.modalityLUT = undefined;
}
cornerstone.setViewport(element, viewport);
});
document.getElementById('toggleVOILUT').addEventListener('click', function() {
var applyVOILUT = document.getElementById('toggleVOILUT').checked;
console.log('applyVOILUT=', applyVOILUT);
var image = cornerstone.getImage(element);
var viewport = cornerstone.getViewport(element);
if(applyVOILUT) {
viewport.voiLUT = image.voiLUT;
} else {
viewport.voiLUT = undefined;
}
cornerstone.setViewport(element, viewport);
});
document.getElementById('toggleCollapseInfo').addEventListener('click', function() {
if (document.getElementById('collapseInfo').style.display === 'none') {
document.getElementById('collapseInfo').style.display = 'block';
} else {
document.getElementById('collapseInfo').style.display = 'none';
}
});
</script>
</html>