tags:

views:

427

answers:

3

Hello, I'm using mDCM with C# to view dicom tags, but I'm trying to convert the pixel data to a Bitmap and eventually out to a JPG file. I have read all of the posts on the mDCM Google Group on the subject and all of the code examples either don't work or are missing important lines of code. The image I am working with is a 16 bit monochrome1 (that's the format mentioned, but it's actually 16 bit grayscale). I have tried using LockBits, SetPixel, and unsafe code in order to convert the pixel data to a Bitmap but all attempts fail. Does anyone have any code that could make this work.

Here is my latest attempt using SetPixel:

DcmElement pixelData = this.currentFileFormat.Dataset.GetElement(new DcmTag(DcmConstTags.PixelData));
ushort[] pixels = this.currentPixelData.GetFrameDataU16(0);
this.currentImage = new Bitmap(this.currentPixelData.ImageWidth, this.currentPixelData.ImageHeight, PixelFormat.Format16bppRgb555);
int resample = (int)Math.Pow(2, (this.currentPixelData.BitsStored - 8));

int pxCounter = 0;
int min = ushort.MaxValue;
int max = 0;

for (int c = 0; c < this.currentPixelData.ImageHeight; c++)
{
    for (int r = 0; r < this.currentPixelData.ImageWidth; r++)
    {
        ushort pxColor = pixels[pxCounter];
        int temp = 255 - (pxColor / resample);
        if (temp < min) min = temp;
        if (temp > max) max = temp;
        this.currentImage.SetPixel(r, c, Color.FromArgb(temp, temp, temp));
        pxCounter++;
    }
}

UPDATE: I have gotten closer by using LockBits and Marshal.Copy, but the image comes out in a rainbow of colors instead of grayscale. So I'm guessing I need a way to convert the grayscale data to RBG format:

byte[] pixels = this.currentPixelData.GetFrameDataU8(frameIndex);
this.currentImage = new Bitmap(this.currentPixelData.ImageWidth, this.currentPixelData.ImageHeight, PixelFormat.Format16bppRgb555);
BitmapData bitmapData = this.currentImage.LockBits(new Rectangle(0, 0, this.currentImage.Width, this.currentImage.Height), ImageLockMode.ReadWrite, this.currentImage.PixelFormat);
System.Runtime.InteropServices.Marshal.Copy(pixels, 0, bitmapData.Scan0, this.currentImage.Width * this.currentImage.Height * 2);
this.currentImage.UnlockBits(bitmapData);

Thanks in advance

P.S. Before anyone suggests trying something else like ClearCanvas, know that mDCM is the only library that suits my needs and ClearCanvas is WAY too bloated for what I need to do.

A: 

Too bad you are not using GDCM with C#. This would be a 5-lines piece of code:

http://gdcm.sourceforge.net/html/ExtractEncapsulatedFile.cs-example.html

malat
A: 

I eventually figured it out, so if anyone else stumbles onto this problem, I was able to display and save the 16-bit grayscale images using code from a CodeProject article. Here's a link to that article:

http://www.codeproject.com/KB/graphics/Image16bit.aspx?msg=3210733

Ross Peoples
hi ross,i stuck on the same issue.i am unable to solved,are you method proper work for initial window level values.how you will do that.thanks
prashant
A: 

I work for Atalasoft and we have an imaging component that will do this for you:

DicomDecoder decoder = new DicomDecoder();
using (AtalaImage image = decoder.Read(stream, frameIndex, null)) {
    AtalaImage imageToSave = null;
    if (image.PixelFormat == PixelFormat.Pixel16bppGrayscale) {
        imageToSave = image.GetChangedPixelFormat(PixelFormat.Pixel8bppGrayscale);
    }
    else if (image.PixelFormat == PixelFormat.Pixel48bppBgr) {
        imageToSave = image.GetChangedPixelFormat(PixelFormat.Pixel24bppBgr);
    }
    else {
        imageToSave = image;
    }
    imageToSave.Save(outputStream, new JpegEncoder(), null);
    if (imageToSave != image)
        imageToSave.Dispose();
}

This is a little wordier than it strictly needs to be - I would factor out a routine to return an image in a format suitable for the encoder you want to use. Jpeg, in general, is a fairly limited pixel formats it can handle, whereas dicom can encapsulate some fairly wide formats. TIFF would probably be a better choice for an output file format.

I bring this up because the DicomDecoder object automatically handles dicom's more esoteric pixel formats, allows you to do window and leveling (aka, brightness and contrast) in the image's raw space, as well as get at the tags, and we give you win/web form controls for displaying AtalaImages, which would probably cut your app size way down.

There are, of course, a set of reasonable reasons why you might be constrained to use mDCM, but I thought it might help you (or others) to see another option.

plinth