I'm trying to display multi-frame dicom images in a browser using HTML5 canvas and javascript. So far I can render single framed images just fine but I'm having trouble with multi framed images.
For parsing the file I'm using the DicomParser plugin.
When I break the data into it's fragments(frames) and try to display them the canvas just renders bars of noise. Heres an example of rendering a single frame from a multi frame image.
Below is the javscript code
// CREATE A CANVAS REFERENCE
// -------------------------------------------------------------------------------------------------
var canvas = document.getElementById( 'canvas' );
canvas.with = 200;
canvas.height = 200;
// ADD A HANDLER FOR READING FILES FROM COMPUTER
// -------------------------------------------------------------------------------------------------
var dicomFile = document.getElementById( 'dicomfile' );
dicomFile.onchange = function( evt ) {
var tgt = evt.target || window.event.srcElement,
files = tgt.files;
// FILEREADER SUPPORT
// ---------------------------------------------------------------------------------------------
if ( FileReader && files && files.length ) {
var fr = new FileReader(),
extension = files[ 0 ].name.split( '.' ).pop().toLowerCase();
// IF EXTENSION IS NOT DCM ,THEN STOP PROCESSING FURTHER AND EXIT.
if ( extension !== 'dcm' ) {
alert( 'please choose a Dicom file' );
return;
} else {
// PARSE AND PROCESS THE DICOM FILE.
fr.onload = function( e ) {
var dicomArray = new Uint8Array( e.target.result ),
// PARSE THE DICOM FILE
dataSet = dicomParser.parseDicom( dicomArray ),
// GET WIDTH AND HEIGHT OF THE DICOM IMAGE.
width = dataSet.uint16( 'x00280011' ), height = dataSet.uint16( 'x00280010' ),
// GET THE PIXEL DATA ELEMENT FROM THE DATASET.
pixelDataElement = dataSet.elements.x7fe00010;
// NOW GET THE PIXEL DATA FROM THE DICOM FILE.
var pixelData = [];
pixelDataElement.basicOffsetTable.forEach( function(offset){
pixelDataElement.fragments.forEach(function(fragment){
pixelData.push( new Uint8Array( dataSet.byteArray.buffer, offset, fragment.length ) );
});
});
// NOW WE HAVE GOT WIDTH, HEIGHT AND PIXEL DATA WHICH IS ALL IT TAKES TO RENDER A IMAGE TO THE CANVAS.
canvas.width = width;
canvas.height = height;
// GET CONTEXT
var context = canvas.getContext( '2d' ),
// GET IMAGE DATA TO UPDATE
imageData = context.getImageData( 0, 0, width, height ),
data = imageData.data;
// UPDATING ALPHA
for ( var i = 3, k = 0; i < data.byteLength; i = i + 4, k = k + 2 ) {
// CONVERT 16-BIT TO 8-BIT ,BECAUSE WE CANNOT RENDER A 16-BIT VALUE TO THE CANVAS.
var result = ((pixelData[0][ k + 1 ] & 0xFF) << 8) | (pixelData[0][ k ] & 0xFF);
result = (result & 0xFFFF) >> 8;
data[ i ] = 255 - result;
}
imageData[0] = data[0];
context.putImageData( imageData, 0, 0 );
// SHOW THE CANVAS
canvas.style.display = 'block';
};
fr.readAsArrayBuffer( this.files[ 0 ] );
}
}
};
Could anyone tell me where I'm going wrong. Any information at all, however general, would be helpful.
The end goal is to use these frames as textures for webGl and three.js to create volumetric rendering of dicom images
The image frames in your multi-frame file are likely compressed and dicomParser does not include decompression code. Take a look at CornerstoneWADOImageLoader for codecs and how to use them: https://github.com/chafey/cornerstoneWADOImageLoader