DicomImage can't read binary array

All other questions regarding DCMTK

Moderator: Moderator Team

Post Reply
Message
Author
pdyban
Posts: 6
Joined: Tue, 2012-01-31, 13:16
Location: Germany

DicomImage can't read binary array

#1 Post by pdyban »

Hello!
I am stuck on one problem and I need your advice on what I am doing wrong.

I want to read a segmentation mask from a DICOM SEG file. The mask is stored as a binary multi-layered image in PixelData tag. I can either access the tag by creating a DcmFileFormat object and reading the contents of the tag, or I can load this file as DicomImage and use its methods. My problem is, however, that I am not sure, how to correctly store the mask data in an aray. The segmentation mask is a binary image, BitsAllocated tag has value 1. When I read the image, I get a result in form of a void* pointer. Which variable type do I have to convert this pointer to, if I have a binary array?

Here is my code:

Code: Select all

DicomImage* dicomImage = new DicomImage( filename.c_str() );
unsigned long dataSize = dicomImage->getOutputDataSize();
const void* pData = dicomImage->getOutputData(1, dataSize );
void * buffer = new unsigned char[dataSize];
if( !dicomImage->getOutputData(buffer, dicomImage->getOutputDataSize(), dicomImage->getDepth() ) ){
  std::cerr << "DicomSRReaderWrapper::readDicomImage Error: dicomImage->getOutputData() was not successful!" << std::endl;
}
for( int i = 0; i < dataSize; ++i ) {
  if( *((unsigned char*)(buffer)+i) != 0 )
    std::cout << *((unsigned char*)(buffer)+i) << std::endl;
}
delete[] buffer;
Thank you in advance!

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

#2 Post by J. Riesmeier »

I'm not sure whether the rendered output of the DicomImage class is really appropriate for your use case, but the pixel array created by getOutputData() is always aligned to 8, 16 or 32 bit - as you can read in the documentation.

pdyban
Posts: 6
Joined: Tue, 2012-01-31, 13:16
Location: Germany

#3 Post by pdyban »

@J. Riesmeier: Thank you for your hint! Later I opened the DICOM file with a hex reader and I saw that my code had read only the first frame of the segmentation mask.

Code: Select all

dicomImage->getOutputDataSize()
returns the size of one layer of data, as opposed to

Code: Select all

dicomImage->getWidth()*dicomImage->getHeight()*dicomImage->getFrameCount()
I have modified my code in the following manner:

Code: Select all

DicomImage* dicomImage = new DicomImage( filename.c_str() );

int rows   = dicomImage->getHeight();
int cols   = dicomImage->getWidth();
int frames = dicomImage->getFrameCount();

if( buffer == 0 ) {
	try {
		buffer = new unsigned char[rows*cols*frames];
	}
	catch( std::bad_alloc& exc ){
		std::cerr << "DicomSRReaderWrapper::readDicomImage(): bad_alloc error: " << exc.what() << std::endl;
		return;
	}
}

for( int frame = 0; frame < frames; ++frame ){
	if( !dicomImage->getOutputData((void*)(buffer + frame*rows*cols), rows*cols, dicomImage->getDepth(), frame ) ){
		std::cerr << "DicomSRReaderWrapper::readDicomImage Error: dicomImage->getOutputData() was not successful!" << std::endl;
	}
}
delete dicomImage;
I am not sure if this code is 100%-correct, since I am not yet done implementing it in my project. If I find an error in my code, I will report on it on your forum.

Best regards!

pdyban
Posts: 6
Joined: Tue, 2012-01-31, 13:16
Location: Germany

#4 Post by pdyban »

Hello!
After rendering the array data from yesterday, I have established the fact that the bits have been inverted inside of their container-bytes, which means that when loading the binary array, wrong bit ordering has been chosen. Can I tell getOutputData() function, which bit ordering to use? A attach a screenshot to better explain what my question is about.

Thank you in advance!

Image

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

#5 Post by J. Riesmeier »

What do you mean by bit ordering? Your input image has 1 bit and the output image has 8 bits, i.e. a 0 in the input image is mapped to 0 in the output image and a 1 in the input image is mapped to 255 in the output image (assuming that an appropriate VOI window has been chosen).

If you want to invert the image you could e.g. use DicomImage::setPolarity().

pdyban
Posts: 6
Joined: Tue, 2012-01-31, 13:16
Location: Germany

#6 Post by pdyban »

@J.Riesmeier: Does value 1 in one bit become value 255 in a char? If you look at the example image, you will see that bits that had been located inside one byte in the raw binary data tag of the dicom file, were reversed in the output. The ordering, in which bits were extracted, seems to be reversed. Or is it my mistake in understanding?

I had to reverse the ordering in which bytes in the unsigned char array are read. My image now looks continuous and smooth. I wrote a function which runs forward 8 bytes and then takes the i%8-th byte from the right. This approach seems to work so far.

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

#7 Post by J. Riesmeier »

Does value 1 in one bit become value 255 in a char?
I thought that this has already been answered in my previous posting :-) The answer is "yes" unless you change anything like VOI windowing or polarity.

With regard to the "bit ordering": Are you sure that your test object is encoded correctly? Could you send the file to us by email (dicom/at/offis/dot/de)?

pdyban
Posts: 6
Joined: Tue, 2012-01-31, 13:16
Location: Germany

#8 Post by pdyban »

Unfortunately, I cannot send you my dicom file, but I will try and explain once again what I mean.

I can view my DICOM SEG file in a hex editor, where I can "see" the binary mask. 1's encode the mask, 0's - empty space. In the hex editor, sequences of 1's are contiguous. By lookig at the 0-1-pattern in the editor, you can almost visualize the mask. When I read this mask with getOutputData() and render it, the bits that used to constitute sequences, are now printed in reverse order, as in the image above. It seems to me that when bits inside a byte are parsed by getOutputData(), little endian encoding is used, i.e. bits are parsed from right to left instead of being parsed from left to right. Can this be the case?

Image

Thank you in advance!

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

#9 Post by J. Riesmeier »

It seems to me that when bits inside a byte are parsed by getOutputData(), little endian encoding is used, i.e. bits are parsed from right to left instead of being parsed from left to right. Can this be the case?
This has nothing to do with little or big endian byte-ordering (unless the Pixel Data element uses the VR=OW). This is just the way part 5 of the DICOM standard defines the encoding. The following excerpt is from section 8.2:
Native format Pixel Cells are encoded as the direct concatenation of the bits of each Pixel Cell, the least
significant bit of each Pixel Cell is encoded in the least significant bit of the encoded word or byte,
immediately followed by the next most significant bit of each Pixel Cell in the next most significant bit of
the encoded word or byte, successively until all bits of the Pixel Cell have been encoded, then immediately
followed by the least significant bit of the next Pixel Cell in the next most significant bit of the encoded
word or byte.

pdyban
Posts: 6
Joined: Tue, 2012-01-31, 13:16
Location: Germany

#10 Post by pdyban »

Thank you for the explanation! My issue seems to be part of the standard procedure for reading binary arrays from DICOM files, and not an error. I have implemented a work-around and it works fine!

Thank you for your support!

Post Reply

Who is online

Users browsing this forum: Google [Bot] and 1 guest