Why should I add my pixel values of dicom image to 2^15?

All other questions regarding DCMTK

Moderator: Moderator Team

Message
Author
MilanoFili
Posts: 12
Joined: Wed, 2013-05-29, 06:07

Why should I add my pixel values of dicom image to 2^15?

#1 Post by MilanoFili »

I'm using dcmtk to read dicom images and I have following attributes with the new samples :

(0028,0004) Photometric Interpretation: MONOCHROME2
(0028,0010) Rows: 512
(0028,0011) Columns: 512
(0028,0030) Pixel Spacing: 0.4688\0.4688
(0028,0100) Bits Allocated: 16
(0028,0101) Bits Stored: 16
(0028,0102) High Bit: 15
(0028,0103) Pixel Representation: 1
(0028,0106) Smallest Image Pixel Value: 0
(0028,0107) Largest Image Pixel Value: 2732
(0028,1050) Window Center: 1366
(0028,1051) Window Width: 2732

I use the getOutputData(16) to read int16_t data. It's surprised me, because the values are negative near to -1*(2^16) and when I added the values by 2^15 everything seems ok and I can see the images! :-(

Now I have two questions :
  • Why should I add the value to 2^15 and it goes ok? There is no padding value available on image!
  • In document of getOutputData, it's speaking about The rendered pixel data is alway unsigned.. What does it means specially when my image data is signed because the (0028,0103) attribute is saying it to me? If this method is not proper, so can I get real data by dcmtk?

Michael Onken
DCMTK Developer
Posts: 2049
Joined: Fri, 2004-11-05, 13:47
Location: Oldenburg, Germany
Contact:

Re: Why should I add my pixel values of dicom image to 2^15?

#2 Post by Michael Onken »

You cannot put unsigned 16 bit data into a 16 bit int (and interpret the int as such, i.e. signed).

Did you try to put the result into a Uint16 array and read each value as Uint16 from it?

Best,
Michael

Andreas Thiel
Posts: 18
Joined: Tue, 2007-12-18, 14:25

Re: Why should I add my pixel values of dicom image to 2^15?

#3 Post by Andreas Thiel »

What are the values of:
(0028,1052) Rescale Intercept
(0028,1053) Rescale Slope

if they are 2^15 and 1 you have to have to add 2^15 for the greyscale transformation and everthing is fine :wink:

MilanoFili
Posts: 12
Joined: Wed, 2013-05-29, 06:07

Re: Why should I add my pixel values of dicom image to 2^15?

#4 Post by MilanoFili »

@Michael

I read each value as Uint16 by this code

Code: Select all

Uint16 * data = image->getOutputData(/*16 is default here*/);
then they have always bigger than 2^15! This is the exact thing that makes me surprised. When I subtract the value from 2^15 then I should be able to see the expected image in good option. Maybe converting from signed to unsigned cause to make for me this mystery :!: .

Now I have several questions (Sorry if they are stupid) :
How can I get the real values without casting to unsigned? The values are signed and why are you casting them to unsigned always? I used your tools like this dcmj2pnm IMGName +Wm +ot x.tiff and it saves good. What functions you're using to save the images?

@Andreas

There is no attribute for Rescale. I shared the header info in https://docs.google.com/document/d/1XyQ ... sp=sharing.

Thanks a lot
Best Regards
Milano

Chung-Yueh Lien
Posts: 61
Joined: Wed, 2010-05-19, 09:27
Location: Taipei, Taiwan

Re: Why should I add my pixel values of dicom image to 2^15?

#5 Post by Chung-Yueh Lien »

MilanoFili wrote: I read each value as Uint16 by this code

Code: Select all

Uint16 * data = image->getOutputData(/*16 is default here*/);
then they have always bigger than 2^15! This is the exact thing that makes me surprised. When I subtract the value from 2^15 then I should be able to see the expected image in good option. Maybe converting from signed to unsigned cause to make for me this mystery :!: .
I do agree the problem is a unsigned/signed problem. For example, a binary value presented as binary is: 1000 0000 0000 0001
presented as uint16, the value is 2^15+1. That is the reason why they are always bigger than 2^15.
MilanoFili wrote: Now I have several questions (Sorry if they are stupid) :
How can I get the real values without casting to unsigned? The values are signed and why are you casting them to unsigned always? I used your tools like this dcmj2pnm IMGName +Wm +ot x.tiff and it saves good. What functions you're using to save the images?
It is quite simple, for instance:
uint16 x = 65535;
int16 y = (int16)x; // y = -1

By the way, please avoid do such like this.

Andreas Thiel
Posts: 18
Joined: Tue, 2007-12-18, 14:25

Re: Why should I add my pixel values of dicom image to 2^15?

#6 Post by Andreas Thiel »

MilanoFili wrote: then they have always bigger than 2^15! This is the exact thing that makes me surprised. When I subtract the value from 2^15 then I should be able to see the expected image in good option. Maybe converting from signed to unsigned cause to make for me this mystery :!: .
This behaviour is correct, because
(0028,0103) Pixel Representation: 1
means the values are stored as 2's complement.

MilanoFili
Posts: 12
Joined: Wed, 2013-05-29, 06:07

Re: Why should I add my pixel values of dicom image to 2^15?

#7 Post by MilanoFili »

Andreas Thiel wrote:
MilanoFili wrote: then they have always bigger than 2^15! This is the exact thing that makes me surprised. When I subtract the value from 2^15 then I should be able to see the expected image in good option. Maybe converting from signed to unsigned cause to make for me this mystery :!: .
This behaviour is correct, because
(0028,0103) Pixel Representation: 1
means the values are stored as 2's complement.
There is one thing that I have to say :
In two's complement notation, a non-negative number is represented by its ordinary binary representation; in this case, the most significant bit is 0.

And each value is between (0028,0106) Smallest Image Pixel Value: 0 and (0028,0107) Largest Image Pixel Value: 2202. It means the conversion from Sint16 to Uint16 without any changes! I just want to say the 16th bit in getOutputData should not be set to 1.

So can you please explain to me this behaviour more?

Best
Milano

J. Riesmeier
DCMTK Developer
Posts: 2504
Joined: Tue, 2011-05-03, 14:38
Location: Oldenburg, Germany
Contact:

Re: Why should I add my pixel values of dicom image to 2^15?

#8 Post by J. Riesmeier »

As written in the documentation, getOutputData() returns the rendered pixel data, i.e. the result of the transformation pipeline including VOI/windowing. It is not meant to get raw pixel data, Hounsfield Units or the like!

Could you please post the code fragment that creates the DicomImage instance and that calls the various methods of this class?

MilanoFili
Posts: 12
Joined: Wed, 2013-05-29, 06:07

Re: Why should I add my pixel values of dicom image to 2^15?

#9 Post by MilanoFili »

First scenario as unsigned :

Code: Select all

DicomImage *image = new DicomImage("IMG0.dcm");
if (image != NULL) {
     if (image->getStatus() == EIS_Normal) {
           if (image->isMonochrome()) {
                 // I don't want to use VOI/windowing, so I comment the below line
                 //image->setMinMaxWindow();
                 uint16_t *pixelData = image->getOutputData();
                 int cout = 0;
                 for (int i =0 ; i < image->getWidth() * image->getHeight();i++) {
                      std::cout << "pixel data : "<< *(pixelData + i) << std::endl;
                      *(pixelData+i) = *(pixelData + i) - pow(2,15); // just by this operation everything is ok
                 }
            }
      }
}
else {
    std::cerr << "Error: cannot load DICOM image (" << DicomImage::getString(image->getStatus()) << ")" << std::endl;
}
And 16th bit is always set, because it's always bigger than 2^15.

Also second scenario as signed :

Code: Select all

DicomImage *image = new DicomImage("IMG0.dcm");
if (image != NULL) {
     if (image->getStatus() == EIS_Normal) {
           if (image->isMonochrome()) {
                 // I don't want to use VOI/windowing, so I comment the below line
                 //image->setMinMaxWindow();
                 int16_t *pixelData = image->getOutputData();
                 int cout = 0;
                 for (int i =0 ; i < image->getWidth() * image->getHeight();i++) {
                      std::cout << "pixel data : "<< *(pixelData + i) << std::endl;
                      *(pixelData+i) = *(pixelData + i) + pow(2,15); // just by this operation everything is ok
                 }
            }
      }
}
else {
    std::cerr << "Error: cannot load DICOM image (" << DicomImage::getString(image->getStatus()) << ")" << std::endl;
}
And also 16th bit is always set!

I can upload the image for you in google drive by respecting to privacy. I just need your google account.

Also is there a way to read raw data by DCMTK?

Best
Milano

J. Riesmeier
DCMTK Developer
Posts: 2504
Joined: Tue, 2011-05-03, 14:38
Location: Oldenburg, Germany
Contact:

Re: Why should I add my pixel values of dicom image to 2^15?

#10 Post by J. Riesmeier »

Could you please also post the output of dcm2pnm with option -o, -v and -im for this image?

And please consider that getOutputData() always returns unsigned data. I guess that int16_t is a signed data type, right? You should also specify the output bit depth of getOutputData() explicitly, because otherwise it varies with the DICOM image loaded.

MilanoFili
Posts: 12
Joined: Wed, 2013-05-29, 06:07

Re: Why should I add my pixel values of dicom image to 2^15?

#11 Post by MilanoFili »

@J. Riesmeier

Code: Select all

I: reading DICOM file: IMG2
I: preparing pixel data
I: dumping image parameters
I:   filename            : IMG2
I:   transfer syntax     : Little Endian Explicit
I:   SOP class           : MRImageStorage
I:   SOP instance UID    : 1.2.840.113773.4.10037.11411.20130523114451.22
I:   columns x rows      : 512 x 512
I:   bits per sample     : 16
I:   color model         : MONOCHROME2
I:   pixel aspect ratio  : 1.00
I:   number of frames    : 1
I:   VOI LUT function    : <default>
I:   VOI windows in file : 1
I:   - <no explanation>
I:   VOI LUTs in file    : 0
I:   presentation shape  : <default>
I:   overlays in file    : 0
I:   maximum pixel value : 2099
I:   minimum pixel value : 0
I: cleaning up memory

J. Riesmeier
DCMTK Developer
Posts: 2504
Joined: Tue, 2011-05-03, 14:38
Location: Oldenburg, Germany
Contact:

Re: Why should I add my pixel values of dicom image to 2^15?

#12 Post by J. Riesmeier »

Could you please upload the image to some server and send the download information to me by email: forum/at/jriesmeier/dot/com

MilanoFili
Posts: 12
Joined: Wed, 2013-05-29, 06:07

Re: Why should I add my pixel values of dicom image to 2^15?

#13 Post by MilanoFili »

@J. Riesmeier

Have you got the email?

J. Riesmeier
DCMTK Developer
Posts: 2504
Joined: Tue, 2011-05-03, 14:38
Location: Oldenburg, Germany
Contact:

Re: Why should I add my pixel values of dicom image to 2^15?

#14 Post by J. Riesmeier »

No, but the above mentioned email address is correct (and working, I just checked that). Of course, you have to transform the string given in a kind of path syntax to a valid email address (I used this syntax to avoid too much SPAM on this address).

MilanoFili
Posts: 12
Joined: Wed, 2013-05-29, 06:07

Re: Why should I add my pixel values of dicom image to 2^15?

#15 Post by MilanoFili »

Please inform us when you have it[the link of sample image].

Best

Post Reply

Who is online

Users browsing this forum: Majestic-12 [Bot] and 1 guest