How to prevent changing photometric interpretation?

All other questions regarding DCMTK

Moderator: Moderator Team

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

How to prevent changing photometric interpretation?

#1 Post by faisal_tum »

I'm now able to modify the pixel data and dicom headers using DCMTK properly. But I noticed that when I change the pixel data it also changes the photometric interpretation in the new copy of the modified DICOM file. For example the photometric interpretation changes from YBR_FULL_422 to YBR_FULL.

Is it possible to prevent that?

An sample code of how I change the pixel data of particular Dicom file is as below. I provided the full code that can be built and run when you include the libraries in your C++ project dependencies.

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 "dcmtk/dcmdata/dcpxitem.h"
#include "dcmtk/dcmjpeg/djrplol.h"
#include "dcmtk/dcmdata/dcistrmf.h"
#include "dcmtk/dcmdata/dcostrmf.h"
#include "dcmtk/dcmjpeg/djrploss.h"
#include <mdfdsman.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h> 

using namespace std;
int main()
{
	int index=0;
	int ymin=0;//minimum rows
	int ymax=50;//maximum rows
	int xmin=86;//Minimum columns
	int xmax=186;//Maximum columns
	DJDecoderRegistration::registerCodecs();
	DJEncoderRegistration::registerCodecs();
	DcmFileFormat fileformat;
	//Loading the file
	if (fileformat.loadFile("SEN042_4CH_01.dcm").good())
	{
		DcmDataset *dataset = fileformat.getDataset();
		E_TransferSyntax xfer= dataset->getOriginalXfer();
		//Decompressing the Dicom file
		OFCondition chRep = dataset->chooseRepresentation(EXS_LittleEndianExplicit, NULL);
		if(chRep == EC_Normal)
		{
			if(EC_Normal==dataset->chooseRepresentation(EXS_LittleEndianExplicit, NULL))
			{
				if(dataset->canWriteXfer(EXS_LittleEndianExplicit))
				{
					cout<<"Originally it's a compressed image, but now decompressed!\n";
				}
			}
		}
		DcmElement* element=NULL;
		if(EC_Normal==dataset->findAndGetElement(DCM_PixelData,element))
		{
			Uint32 sizeF=0;
			//Getting the size of the frame
			if(EC_Normal==element->getUncompressedFrameSize(dataset,sizeF))
			{
				OFString decompressedColorModel=NULL;
				if(EC_Normal==element->getDecompressedColorModel(dataset,decompressedColorModel))
				{
					Uint16 rows = 0;
					//Getting the number of rows
					if(EC_Normal==dataset->findAndGetUint16(DCM_Rows, rows))
					{
						Uint16 cols = 0;
						//Getting the number columns
						if(EC_Normal==dataset->findAndGetUint16(DCM_Columns, cols))
						{
							Uint16 samplePerPixel = 0;
							//Getting the number of samples per pixel
							if(EC_Normal==dataset->findAndGetUint16(DCM_SamplesPerPixel,samplePerPixel))
							{	
								Uint16 planarConfiguration = 0;
								//Getting the planar configuration
								if(EC_Normal==dataset->findAndGetUint16(DCM_PlanarConfiguration,planarConfiguration))
								{
									long int numOfFrames=0;
									//Getting the number of frames
									if(EC_Normal==dataset->findAndGetLongInt(DCM_NumberOfFrames,numOfFrames))
									{
										if(planarConfiguration == 0)
										{
											Uint8 * fullBuffer = new Uint8[(int(sizeF*numOfFrames))];
											for(int i=0;i<numOfFrames;i++)
											{
												Uint8 * buffer = new Uint8[int(sizeF)];
												DcmFileCache * cache=NULL;
												Uint32 startFragment=0;
												OFCondition cond=element->getUncompressedFrame(dataset,i,startFragment,buffer,sizeF,decompressedColorModel,cache);
												//I get the uncompressed individual frame pixel data 
												if(buffer != NULL)
												{
													for(unsigned long y = (unsigned long)ymin; y < (unsigned long)ymax ; y++)
													{
														for(unsigned long x = (unsigned long)xmin; x < (unsigned long)xmax; x++)
														{
															index=((int)x + ((int)y*(int)cols))*(int)samplePerPixel;
															if(index<int(sizeF)-2)
															{
																buffer[index] = 0;
																buffer[index + 1] = 0;
																buffer[index + 2] = 0;
															}
														}
													}
													memcpy(fullBuffer+(i*sizeF),buffer,sizeF);
													delete [] buffer;
												}													
											}
											//Putting the modified pixel data to the original dataset
											OFCondition fullcopy=dataset->putAndInsertUint8Array(DCM_PixelData,fullBuffer,sizeF*numOfFrames,true);
											if(fullcopy==EC_Normal)
											{
												DcmItem *metaInfo = fileformat.getMetaInfo();
												//Compressing the pixel data
												OFCondition compressing;
												if(xfer == 12 || xfer == 11 || xfer == 24 || xfer == 19 || xfer == 20 || xfer == 21 || xfer == 22 || xfer == 23 || xfer == 25 || xfer == 26 || xfer == 30)
												{
													DJ_RPLossless params;
													compressing = dataset->chooseRepresentation(xfer, &params);
													if(compressing != EC_Normal)
													{
														cout<<"Something wrong with compressing!\n";
													}
												}
												// Still compression methods 28, 29, 31, 32, 33 not covered. Potential bug exists.
												else if(xfer == 4 || xfer == 5 || xfer == 6 || xfer == 7 || xfer == 8 || xfer == 9 || xfer == 10 || xfer == 13 || xfer == 14 || xfer == 15 || xfer == 16 || xfer == 17 || xfer == 18 || xfer == 27)
												{
													DJ_RPLossy params;
													compressing = dataset->chooseRepresentation(xfer, &params);
													if(compressing != EC_Normal)
													{
														cout<<"Something wrong with compressing!\n";
													}
												}
												if(xfer==0)
												{
													xfer = EXS_LittleEndianExplicit;
												}
												if(dataset->canWriteXfer(xfer))
												{
													delete metaInfo->remove(DCM_MediaStorageSOPClassUID);
													delete metaInfo->remove(DCM_MediaStorageSOPInstanceUID);
													//Saving the Dicom file as a new copy
													OFCondition newCond=fileformat.saveFile("newTest.dcm",xfer);
													if(newCond!=EC_Normal)
													{
														cout<<"Something wrong in saving\n";
													}
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
		DJDecoderRegistration::cleanup();
		DJEncoderRegistration::cleanup();
		return 0;
	}
}
It would be very kind of you if can let me know how I can prevent this change in photometric interpretation. Thanks.

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

Re: How to prevent changing photometric interpretation?

#2 Post by J. Riesmeier »

What about setting appropriate codec parameters? E.g. one of the following (excerpt from the documentation):

Code: Select all

pCompressionCSConversion	color conversion mode for compression
[...]
pWriteYBR422	flag indicating whether a compressed YBR color stream should be marked as YBR_FULL or YBR_FULL_422 on DICOM level

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

Re: How to prevent changing photometric interpretation?

#3 Post by faisal_tum »

J. Riesmeier wrote:What about setting appropriate codec parameters? E.g. one of the following (excerpt from the documentation):

Code: Select all

pCompressionCSConversion	color conversion mode for compression
[...]
pWriteYBR422	flag indicating whether a compressed YBR color stream should be marked as YBR_FULL or YBR_FULL_422 on DICOM level
Thanks! It works now.

Post Reply

Who is online

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