Problem with DicomImage class?

Compilation and installation of DCMTK

Moderator: Moderator Team

Post Reply
Message
Author
faisal_tum
Posts: 33
Joined: Fri, 2013-01-11, 15:37

Problem with DicomImage class?

#1 Post by faisal_tum »

I'm trying to test a small program using dcmtk where I try to count the number of frames in the dicom image. The code is as the following. The transfer syntax UID of the dicom image is 1.2.840.10008.1.2.4.50.

Code: Select all

#include "dcmtk/config/osconfig.h"
#include "dcmtk/dcmdata/dctk.h"
#include "dcmtk/dcmimgle/dcmimage.h"
#include <iostream>

using namespace std;
int main()
{
 DicomImage* inputImage= new DicomImage("test.dcm",0,0,0);
  EI_Status someStatus=inputImage->getStatus();
  cout<<someStatus<<endl;
  unsigned long no_of_frames=inputImage->getFrameCount();
  cout<<"The Number of frames in the image is: "<<no_of_frames<<endl;

return 0;
}
But everytime it gives the following error:
E: can't determine 'PhotometricInterpretation' of decompressed image
E: mandatory attribute 'PhotometricInterpretation' is missing or can't be determined
E: can't change to unencapsulated representation for pixel data
E: can't determine 'PhotometricInterpretation' of decompressed image
E: mandatory attribute 'PhotometricInterpretation' is missing or can't be determined
And the EI Status is 3. What does EI Status 3 mean? I also checked using the example given in the this link:
http://support.dcmtk.org/wiki/dcmtk/howto/multiframe

Even in that case also I have exactly the same error. But when I tried to get a Jpeg image using the dcmj2pnm.exe file it works properly. I also checked the transfer syntax that are possible to be dealt by dcmtk and the transfer syntax of the images seems to be fine in that regard. I've just noticed that similar kind of error is present in using dcm2pnm.exe instead of dcmj2pnm.exe. So, what is the difference as per the programming between these two programs and what makes dcmj2pnm getting rid of the problem that dcm2pnm has? Could you please say what mistake am I doing there?

faisal_tum
Posts: 33
Joined: Fri, 2013-01-11, 15:37

Re: Problem with DicomImage class?

#2 Post by faisal_tum »

Anyways found the solution :lol: I just have to change this line:

Code: Select all

DicomImage* inputImage= new DicomImage("test.dcm",EPI_YBR_Full_422,0,0);
Just needed to mention which photometric interpretation it has.

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

Re: Problem with DicomImage class?

#3 Post by J. Riesmeier »

As far as I can see, there is no such constructor for the DicomImage class!? If you want to access compressed pixel data, you have to register the appropriate decoders first.

And, btw, why don't you just check the value of the NumberOfFrames (0028,0008) data element?

faisal_tum
Posts: 33
Joined: Fri, 2013-01-11, 15:37

Re: Problem with DicomImage class?

#4 Post by faisal_tum »

Thanks Riesmeier for replying. Yes it doesn't work for compressed images. I naively thought it was solved. Now, I'm trying to load a compressed multiframe dicom image, decompress it and get a Bit map image from the pixel that I get from the first frame.

The code is as below:

Code: Select all

#include "dcmtk/config/osconfig.h"
#include "dcmtk/dcmdata/dctk.h"
#include "dcmtk/dcmimgle/dcmimage.h"
#include "dcmtk/dcmimage/diregist.h"
#include "dcmtk/dcmjpeg/djencode.h"
#include "dcmtk/dcmjpeg/djdecode.h"
#include <mdfdsman.h>
#include <iostream>
#include <stdio.h>      /* printf, fgets */
#include <stdlib.h> 

using namespace std;
int main()
{
	DJDecoderRegistration::registerCodecs();// register JPEG codecs
	DcmFileFormat fileformat;
	if (fileformat.loadFile("test.dcm").good())
	{
		DcmDataset *dataset = fileformat.getDataset();
		OFCondition a=dataset->chooseRepresentation(EXS_LittleEndianExplicit, NULL);
		if (dataset->canWriteXfer(EXS_LittleEndianExplicit))
		{
			a=dataset->loadAllDataIntoMemory();
			DicomImage bmImg(dataset,dataset->getOriginalXfer());
			Uint16 bitNum=0;
			dataset->findAndGetUint16(DCM_BitsAllocated,bitNum);
			int b=bmImg.writeBMP("testBmp.bmp",bitNum,1);// Trying to get the bitmap image from the first frame
			// using the documentation mentioned in http://support.dcmtk.org/docs/classDicomImage.html#265cb0e6b974b2cd1b5544a6c22245ff
		}
		return 0;
	}
}
But even though I do manage to decompress the image and even I can also store the pixel data of the first frame or any frame in a variable if I want I cannot produce that Bitmap image.

Code: Select all

bmImg.writeBMP("testBmp.bmp",bitNum,1);
is not working. Please suggest me what I could do?

I would also like to ask another question. I have already managed to modify the pixel data of a dicom image if it's a single frame via the following code:

Code: Select all

#include "dcmtk/config/osconfig.h"
#include "dcmtk/dcmdata/dctk.h"
#include "dcmtk/dcmimgle/dcmimage.h"
#include "dcmtk/dcmimage/diregist.h"
#include <mdfdsman.h>
#include <iostream>
#include <stdio.h>      /* printf, fgets */
#include <stdlib.h> 

using namespace std;
int main()
{
	MdfDatasetManager FiLe;
	if(EC_Normal==FiLe.loadFile("test1.dcm",ERM_autoDetect,EXS_Unknown))
	{
		FiLe.getDataset()->loadAllDataIntoMemory();
		E_TransferSyntax xfer = FiLe.getDataset()->getOriginalXfer();
		FiLe.getDataset()->chooseRepresentation(xfer, NULL);

		int ymin=50;//minimum ros
		int ymax=500;//maximum rows
		int xmin=100;//Minimum columns
		int xmax=600;//Maximum columns
		const Uint8* pixelValues=0;
		int index=0;
		Uint16 rows = 0;
		Uint16 cols = 0;
		Uint16 samplePerPixel = 0;
		Uint16 planarConfiguration = 0;
		unsigned long * count=NULL;
		const OFBool searchIntoSub=OFFalse; 
		OFCondition Cond=FiLe.getDataset()->findAndGetUint8Array(DCM_PixelData, pixelValues, count,searchIntoSub);
		if(EC_Normal==FiLe.getDataset()->findAndGetUint16(DCM_Rows, rows))
		{
			if(EC_Normal==FiLe.getDataset()->findAndGetUint16(DCM_Columns, cols))
			{
				if(EC_Normal==FiLe.getDataset()->findAndGetUint16(DCM_SamplesPerPixel,samplePerPixel))
				{	
					if(EC_Normal==FiLe.getDataset()->findAndGetUint16(DCM_PlanarConfiguration,planarConfiguration))
					{

						int count = (unsigned long)rows * cols * samplePerPixel;
						Uint8 * newPixelValues = new Uint8[count];
						Uint16 area=(unsigned long)rows * cols;
						if(pixelValues != NULL)
						{
							for(unsigned long y = 0; y < rows; y++)
							{
								for(unsigned long x = 0; x < cols; x++)
								{
									if(x>xmin && x<xmax && y>ymin && y<ymax)
									{
										index=(x + y +  y*(cols-1))*samplePerPixel;
										newPixelValues[index]  = 0;
										newPixelValues[index + 1]  = 0;
										newPixelValues[index +2]  = 0;
									}
									else
									{
										index=(x + y +  y*(cols-1))*samplePerPixel;
										newPixelValues[index]  = pixelValues[index];
										newPixelValues[index + 1]  = pixelValues[index + 1];
										newPixelValues[index + 2]  = pixelValues[index + 2];
									}
									
								}
							}
							int a=0;
							if(FiLe.getDataset()->putAndInsertUint8Array(DCM_PixelData, (const Uint8 *)newPixelValues, rows * cols * samplePerPixel,true) == EC_Normal)
							{
								DicomImage bmpImg(FiLe.getDataset(), FiLe.getDataset()->getOriginalXfer());
								bmpImg.writeBMP("newImage.bmp");
							    if(EC_Normal==FiLe.saveFile("test1.dcm",EXS_Unknown,EET_UndefinedLength,EGL_recalcGL,EPD_noChange,0,0,OFFalse))
								{
									cout<<"File saved properly"<<endl;
								}
								else
								{
									cout<<"Error in program"<<endl;
								}
								
							}
						}
						newPixelValues=NULL;
						delete newPixelValues;
					}
				}
			}
		}
		pixelValues=NULL;
		delete pixelValues;
	}
return 0;
}
What change should I make for a multiframe image in that program? I mean it was very easy to take the pixel data using

Code: Select all

findAndGetUint8Array(DCM_PixelData, pixelValues, count,searchIntoSub)
and than modify it and insert it via

Code: Select all

putAndInsertUint8Array(DCM_PixelData, (const Uint8 *)newPixelValues, rows * cols * samplePerPixel,true)
but I can't see any option in

Code: Select all

DcmDataSet
class that offers me to extract the pixel data using the frame index and also insert new modified pixel data using the frame index. So, how do you think I should adapt my program for Multiframe dicom images?

Thanks a lot for your attention.

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

Re: Problem with DicomImage class?

#5 Post by J. Riesmeier »

Regarding the first part of your posting: You haven't read the documentation of DicomImage::writeBMP() very thoroughly, right? Here's the description of the relevant parameter:

Code: Select all

bits 	number of bits used for output of pixel data (8, 24 or 32, default (0): 8 for monochrome and 24 for color images)
So, if BitsAllocated (bitNum) is 16 in your example file, writeBMP() will fail. The DICOM encoding of the pixel data has nothing to do with the output format! (ok, whether the image is color or grayscale might be relevant ;-)

Also, you do not have to call chooseRepresentation(), loadAllDataIntoMemory() and the like. All this is handled totally transparently by the DicomImage class. What you should do is checking the return value of DicomImage::getStatus() after creating the DicomImage instance.

faisal_tum
Posts: 33
Joined: Fri, 2013-01-11, 15:37

Re: Problem with DicomImage class?

#6 Post by faisal_tum »

Anyways now I have managed to produce a Bitmap image taking one single frame by modifying my code to the following.
:)

Code: Select all

#include "dcmtk/config/osconfig.h"
#include "dcmtk/dcmdata/dctk.h"
#include "dcmtk/dcmimgle/dcmimage.h"
#include "dcmtk/dcmimage/diregist.h"
#include "dcmtk/dcmjpeg/djencode.h"
#include "dcmtk/dcmjpeg/djdecode.h"
#include <mdfdsman.h>
#include <iostream>
#include <stdio.h>      /* printf, fgets */
#include <stdlib.h> 

using namespace std;
int main()
{
	DJDecoderRegistration::registerCodecs();// register JPEG codecs
	DcmFileFormat fileformat;
	if (fileformat.loadFile("test.dcm").good())
	{
		DcmDataset *dataset = fileformat.getDataset();
		OFCondition a=dataset->chooseRepresentation(EXS_LittleEndianExplicit, NULL);
		if (dataset->canWriteXfer(EXS_LittleEndianExplicit))
		{
			DcmElement* element=NULL;
			if(EC_Normal==dataset->findAndGetElement(DCM_PixelData,element))
			{
				Uint32 startFragment=0;
				Uint32 sizeF=0;
				element->getUncompressedFrameSize(dataset,sizeF);
				Uint8 * buffer = new Uint8[int(sizeF)];
				OFString decompressedColorModel=NULL;
				DcmFileCache * cache=NULL;
				OFCondition cond=element->getUncompressedFrame(dataset,0,startFragment,buffer,sizeF,decompressedColorModel,cache);
				cond=dataset->putAndInsertUint8Array(DCM_PixelData,buffer,sizeF,true);
				cond=dataset->saveFile("newTest.dcm",EXS_LittleEndianExplicit);
				DicomImage bmImg(dataset,EXS_LittleEndianExplicit);
				int b=bmImg.writeBMP("testBmp.bmp");// Trying to get the bitmap image from the first frame
				// using the documentation mentioned in 
				//http://support.dcmtk.org/docs/classDicomImage.html#265cb0e6b974b2cd1b5544a6c22245ff
		
			}
		}
		return 0;
	}
}
As you can see I'm new to C++ and very new to Dcmtk, I'd be glad if you can suggest me if I need to do more changes in the code I've just shown here. Thanks for reading :).
Last edited by faisal_tum on Fri, 2013-06-07, 10:14, edited 2 times in total.

faisal_tum
Posts: 33
Joined: Fri, 2013-01-11, 15:37

Re: Problem with DicomImage class?

#7 Post by faisal_tum »

Oops! I didn't you see your reply before putting my previous one. Okay I understand and I'll make those changes. Thanks a lot :).

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest