How to get/make copy of pixel data?

2,321 views
Skip to first unread message

Paul Helmuth

unread,
Jun 11, 2014, 6:41:01 PM6/11/14
to fo-d...@googlegroups.com
All,

I apologize for the simple question - but I'm somewhat new to C# and not thoroughly familiar with the Fellow Oak library.

What I would like to do, is to copy pixel data from a DicomFile object to an appropriate array.

So, for instance for OW data, copy to an array of unsigned short.

I can open the file and get to the Pixel Data Element...

DicomFile DICOM_file = Dicom.DicomFile.Open(DICOM_file_path);
var OWpixelDataEle = DICOM_file.Dataset.Get<DicomOtherWord>(DicomTag.PixelData);

...how do I reference the actual pixel data buffer to copy to a unsigned short array?

Thanks in advance,
-Paul

Chris Hafey

unread,
Jun 11, 2014, 10:58:57 PM6/11/14
to fo-d...@googlegroups.com
Something like this:

var dicomFile = DicomFile.Open(@"C:\image.dcm");
var dicomImage = new DicomImage(dicomFile.Dataset);
var pixelData = PixelDataFactory.Create(dicomImage.PixelData);
if(pixelData is GrayscalePixelDataU16) {
  var pixels = pixelData.Data;
  // access pixel data here
}

Paul Helmuth

unread,
Jun 12, 2014, 11:26:00 AM6/12/14
to fo-d...@googlegroups.com
Chris - thanks!

I'll have a look at "PixelDataFactory" and play with that code frag.

-Paul

Matias

unread,
Jun 12, 2014, 11:47:47 AM6/12/14
to fo-d...@googlegroups.com
I do it this way:
public List<ushort> Pixels16bits;

DicomDataset ds = Dicom.Imaging.Codec.DicomCodecExtensions.ChangeTransferSyntax(dicomImage.Dataset, DicomTransferSyntax.ExplicitVRLittleEndian);
bytes_image = Dicom.Imaging.DicomPixelData.Create(ds).GetFrame(0).Data;
int count = bytes_image.Length / 2;
ushort[] words = new ushort[count];

            for (int j = 0, p = 0; j < count; ++j, p += 2)
            {
                words[j] = BitConverter.ToUInt16(bytes_image, p);
            }
Pixels16bits = words.ToList();

Matias

unread,
Jun 12, 2014, 12:15:43 PM6/12/14
to fo-d...@googlegroups.com
Chris, your code doesn't work for some reason:

See, "Data" is not a member of PixelData

was there a typo?

Thanks,

Chris Hafey

unread,
Jun 12, 2014, 1:29:32 PM6/12/14
to fo-d...@googlegroups.com
Yes, I forgot to cast pixelData to GrayscalePixelDataU16 (use 'as' to do this)
Message has been deleted

Paul Helmuth

unread,
Jun 12, 2014, 2:52:21 PM6/12/14
to fo-d...@googlegroups.com
Thanks Matias and Chris for posting.

After looking things over - I believe this is the most direct way to do what I want...

[from original post]

DicomFile DICOM_file = Dicom.DicomFile.Open(DICOM_file_path);
var OWpixelDataEle = DICOM_file.Dataset.Get<DicomOtherWord>(DicomTag.PixelData);

[then add this...]

IByteBuffer IBBuff_pixelBuff = OWpixelDataEle.Buffer;

var vp = IBBuff_pixelBuff.Data;

Buffer.BlockCopy(vp, 0, rawShortBuff, 0, rawShortBuffSize*sizeof(short));  // copy the data from the IByteBuffer to the rawShortBuff array.

This seems to do exactly what I want - specifically, create an appropriately typed array containing all of the pixel data from an image.

Perhaps the library has a more elegant way to do this?
Is there anything fundamentally wrong with approach?

[making the assumption that the VR of the pixel data is known and the "endian-ness" of the target machine] 

Kind Regards,
-Paul

Message has been deleted
Message has been deleted

Matias

unread,
Jun 12, 2014, 9:56:56 PM6/12/14
to fo-d...@googlegroups.com
I tried Chris approach by doing this and it worked for me:

var PixelData = PixelDataFactory.Create(mydicomimage.PixelData,0) as GrayscalePixelDataS16;
short[] pixels = PixelData.Data;

So I think yes, assuming you know which type of image you're dealing with I think your code or Chris code will work.
You can always verify which type of image is the one you're dealing with prior to obtaining the Pixel Data with an if statement or case statement such as Chris put in his code in the initial answer of this pos

Paul Helmuth

unread,
Jun 13, 2014, 12:54:47 AM6/13/14
to fo-d...@googlegroups.com
Matias and Chris - thanks again for the posts!

Mahesh Dubey

unread,
Jun 17, 2014, 6:18:06 AM6/17/14
to fo-d...@googlegroups.com
Hello;
      

            DicomFile file = DicomFile.Open("dicomFile.dcm");
           
DicomPixelData pxd = DicomPixelData.Create(file.Dataset);
           
IByteBuffer buffer = pxd.GetFrame(0);
           
ushort[] pixels = Dicom.IO.ByteConverter.ToArray<ushort>(buffer);


Mahesh

Paul Helmuth

unread,
Jun 17, 2014, 10:21:44 AM6/17/14
to fo-d...@googlegroups.com
Mahesh,

In your example, would buffer point to a buffer with all of the pixel data, or would it be a buffer with just frame 0?

I understand that frame 0 would be the first in the pixel data, just not sure if GetFrame creates a separate single frame buffer, or if it's pointing to the first byte of frame (n).

In my case, I want all of the pixel data.

Thanks for posting this alternative (showing Dicom.IO.ByteConverter).

-Paul

Mahesh Dubey

unread,
Jun 17, 2014, 10:34:11 AM6/17/14
to fo-d...@googlegroups.com
Hello;
         Frame 0 is the first frame pointing to all pixels in that frame not a single pixel, if you are dealing with single frame images then you don't have to worry about this number just put the 0 But if you are dealing with the multiframe images then this number is the index  (frame number minus one i.e for first frame 0, second frame 1 etc) of the frame for which you want the pixels. This is a generic method which work for all images irrespective of their pixel data type or VR.

Mahesh   

Mahesh Dubey

unread,
Jun 17, 2014, 10:55:23 AM6/17/14
to fo-d...@googlegroups.com
Hello;
          If any of the above solutions suggested to you solve your problem please mark it as a answer So that other will get benefit of it .

Mahesh

Paul Helmuth

unread,
Jun 17, 2014, 4:31:51 PM6/17/14
to fo-d...@googlegroups.com
Mahesh,

I believe you misunderstood my question 

Here is the question again...

        In your example, would buffer point to a buffer with all of the pixel data, or would it be a buffer with just frame 0?

Here is your response...

Frame 0 is the first frame pointing to all pixels in that frame not a single pixel, if you are dealing with single frame images then you don't have to worry about this number just put the 0 But if you are dealing with the multiframe images then this number is the index  (frame number minus one i.e for first frame 0, second frame 1 etc) of the frame for which you want the pixels. This is a generic method which work for all images irrespective of their pixel data type or VR.

Here is the rest of the qualifying info from that post...

I understand that frame 0 would be the first in the pixel data, just not sure if GetFrame creates a separate single frame buffer, or if it's pointing to the first byte of frame (n).

In my case, I want all of the pixel data.


When I said that I wanted all of the pixel data, I meant all - as in all frames (not all pixels in a single frame).

My apologies if I wasn't clear on that point.

Thanks again for posting.
-Paul

Mahesh Dubey

unread,
Jun 18, 2014, 5:31:43 AM6/18/14
to fo-d...@googlegroups.com
Hello;
         Oops !!!  I misunderstood your question. Frame 0 points only to the first frame.
 From the above code you get only the pixels from one frame. Best way is to get the data from all the frame, is to run a loop and concatenate the output (you can use above code) considering the padding.

OR 
     For non fragmented pixel data.
            //This code only works if pixel data is not fragmented
            IByteBuffer buffer = null;
           
var dataset = dicomFile.Dataset;
           
var pixelData = dataset.Get<DicomItem>(DicomTag.PixelData);
           
if (pixelData is DicomOtherByte)
           
{
                buffer
= (pixelData as DicomOtherByte).Buffer;
           
}
           
else if (pixelData is DicomOtherWord)
           
{
                buffer
= (pixelData as DicomOtherWord).Buffer;
           
}
           
else // pixel data is fragmented.
            {
                buffer
= null;
           
}
           
if (buffer != null)
           
{

               
ushort[] pixels = Dicom.IO.ByteConverter.ToArray<ushort>(buffer);
           
}

Mahesh

Paul Helmuth

unread,
Jun 18, 2014, 2:40:56 PM6/18/14
to fo-d...@googlegroups.com
Mahesh,

No worries (about misunderstanding the original question).

Your last code post is a very nice example.

I'll have to take a look at the Dicom.IO.ByteConverter to see what details are built in to that.
Reply all
Reply to author
Forward
0 new messages