I am trying to read the pixel values of an image contained in a DICOM file in my simple c++ application using the Grassroots DICOM (GDCM) library. When reading the file metadata I get the following information about the picture:
Bits allocated: 16
Bits Stored: 16
High Bit: 15
Unsigned or signed: 1
Samples pr pixel: 1
Dimensions: 2
Dimension values: 256x256
Pixel Representation: 1
SamplesPerPixel: 1
ScalarType: INT16
PhotometricInterpretation: MONOCHROME2
Pixel buffer length: 131072
Given that the image has a resolution of 256x256 and is of MONOCHROME2 type, I expected the pixel buffer length to be 256x256=65536 elements but it is in fact 131072 elements long.
If I use MATLAB instead to import the pixel data i get exactly 65536 values in the range of 0 - 850 where 0 is black and 850 is white.
When i look at the pixel buffer i get from the GDCM readout in my c++ application the pixelbuffer is 131072 elements where every even indexed element is in the range -128 to +127 and every odd indexed element is in the range 0-3. like this:
Exerpt:
PixelBuffer[120] = -35
PixelBuffer[121] = 0
PixelBuffer[122] = 51
PixelBuffer[123] = 2
PixelBuffer[124] = 71
PixelBuffer[125] = 2
PixelBuffer[126] = 9
PixelBuffer[127] = 2
PixelBuffer[128] = -80
PixelBuffer[129] = 2
PixelBuffer[130] = 87
PixelBuffer[131] = 3
PixelBuffer[132] = 121
PixelBuffer[133] = 3
PixelBuffer[134] = -27
PixelBuffer[135] = 2
PixelBuffer[136] = 27
PixelBuffer[137] = 2
PixelBuffer[138] = -111
PixelBuffer[139] = 1
PixelBuffer[140] = 75
PixelBuffer[141] = 1
PixelBuffer[142] = 103
What does this arrangement of values mean? Is this some kind of typical pixel representation for monochrome images? I have been "googeling image pixel structure" and similar but cant find what I am looking for. Is there some resource available that can help me understand this arrangement of values and how they correlate to each pixel?
INT16
means each pixel is an integer consisting of 2 bytes. – Christopher Oiclesunsigned char
instead ofchar
, or you could cast to unsigned early, or cast to unsigned late and just zero out any leftover sign-extended bits like:unsigned short c = (static_cast<unsigned short>(b) << 8) + (static_cast<unsigned short>(a) & 0xff);
. That is kind of ugly, but this technique is likely to work in most cases. – Christopher Oiclesint16_t *pixels = reinterpret_cast<int16_t *>(char_pointer);
(or useuint16_t
for unsigned data, but if I understand that header info, you have signed data). Thenint16_t pixel = pixels[256*y + x];
. This works only when both host platform and the data have the same endianness, otherwise you must swap bytes to get the correct value, or do yours((a<<8) | b)
, and fetcha
b
in correct order. – Ped7g