rii-mango / Daikon

A JavaScript DICOM reader.
Other
220 stars 54 forks source link

Example show a dicom frame in the browser #9

Closed ewoutreinders closed 6 years ago

ewoutreinders commented 7 years ago

I am writing a NodeJS application that reads dicom images using your library. Everything works fine and the library is easy to use. Tnx for that! 👍

I was only wondering if it is also possible with Daikon extract frames and write them to disk as a readable format, like jpeg, png or bmp. I want to use one of these formats to show in the browser within an tag. Your example shows how to extract pixeldata/frames, but I only miss the last step (writing them to disk like jpeg, png or bmp).

Is this possible to do with Daikon or do I need some other libraries for this?

martinezmj-ims commented 7 years ago

At least currently, you'd have to use another library -- something like this maybe: https://github.com/niegowski/node-pngjs

Another option, if you can send the raw voxel data to the browser, then you can convert it to RGBA and paint it to a canvas, which can then easily be converted to a PNG.

spiropan commented 6 years ago

Thank you again for your help so far. Related to this topic, I would like to convert a DICOM file that has been parsed into a daikon series image frame to a base64 dataURL that can be used within a tag and where the base46 string is interpreted as an image (i.e. https://codebeautify.org/base64-to-image-converter). What do you think would be the best/simplest approach for this? Thanks in advance!

spiropan commented 6 years ago

The below code (variation of the second option you mentioned above, seems to work OK). I'm pasting here in case it's useful and/or if you have anything to add or suggest that is simpler/better.

    HTML
    <canvas id=c width=128 height=128></canvas>

    JAVASCRIPT
    // assuming a series with one parsed image
    var obj = series.images[0].getInterpretedData(false, true);
    var width=obj.numCols;
    var height=obj.numRows;

    // Create array view
    var array = new Uint8ClampedArray( obj.data ); 

    // Create context from canvas
    var ctx = c.getContext("2d");

    // Create ImageData object
    var imgData = ctx.createImageData(width, height); // width x height
    var data = imgData.data;
    console.log(data.byteLength)

    // updating alpha (from http://www.studyjs.com/html5/dicom.html)
    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 = ((array[k + 1] & 0xFF) << 8) | (array[k] & 0xFF); 
            result = (result & 0xFFFF) >> 8;
            data[i] = 255-result;
    }

    // now we can draw our imagedata onto the canvas
    ctx.putImageData(imgData, 0, 0);

    // Here generate the base64 string
    base64 = c.toDataURL())
rii-mango commented 6 years ago

@spiropan Nice! I think a getPNG() function building on top of getInterpretedData() could be really useful. There are probably lots of edge cases to worry about, but the basic way you went about it looks right to me.