1 /*=========================================================================
4 Module: $RCSfile: exReadPapyrus.cxx,v $
6 Date: $Date: 2007/05/23 14:18:05 $
7 Version: $Revision: 1.8 $
9 Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10 l'Image). All rights reserved. See Doc/License.txt or
11 http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
13 This software is distributed WITHOUT ANY WARRANTY; without even
14 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 PURPOSE. See the above copyright notices for more information.
17 =========================================================================*/
19 #include "gdcmFileHelper.h"
20 #include "gdcmDocument.h"
21 #include "gdcmDataEntry.h"
22 #include "gdcmSeqEntry.h"
23 #include "gdcmSQItem.h"
24 #include "gdcmDebug.h"
27 #include "gdcmArgMgr.h"
33 #include <unistd.h> //for access, unlink
35 #include <io.h> //for _access
38 // return true if the file exists
39 bool FileExists(const char *filename)
42 # define access _access
47 if ( access(filename, R_OK) != 0 )
57 bool RemoveFile(const char *source)
60 #define _unlink unlink
62 return unlink(source) != 0 ? false : true;
65 // ----------------------------------------------------------------------
66 // Here we load a supposed to be Papyrus File (GDCM_NAME_SPACE::File compliant)
67 // and then try to get the pixels, using low-level SeqEntry accessors.
68 // Since it's not a general purpose Papyrus related program
69 // (just a light example) we suppose *everything* is clean
70 // and we don't perform any integrity check
71 // ----------------------------------------------------------------------
73 int main(int argc, char *argv[])
77 " \n exReadPapyrus :\n ",
78 " Reads a Papyrus V3 File, Writes a Multiframe Dicom V3 File ",
79 " (just to show gdcm can do it ...) ",
80 " ==> Well ... It does, but not too much! ",
81 " ==> This code assumes that Pixel Data is uncompressed; no check is performed :-(",
83 " usage: exReadPapyrus filein=inputPapyrusFileName fileout=outputDicomFileName",
85 " debug : developper wants to run the program in 'debug mode' ",
89 // ----- Initialize Arguments Manager ------
91 GDCM_NAME_SPACE::ArgMgr *am = new GDCM_NAME_SPACE::ArgMgr(argc, argv);
93 if (am->ArgMgrDefined("usage"))
95 am->ArgMgrUsage(usage); // Display 'usage'
99 char *fileName = am->ArgMgrWantString("filein",usage);
100 if ( fileName == NULL )
106 char *outputFileName = am->ArgMgrWantString("fileout",usage);
107 if ( outputFileName == NULL )
113 if (am->ArgMgrDefined("debug"))
114 GDCM_NAME_SPACE::Debug::DebugOn();
116 // if unused Params we give up
117 if ( am->ArgMgrPrintUnusedLabels() )
119 am->ArgMgrUsage(usage);
124 delete am; // we don't need Argument Manager any longer
126 // ----------- End Arguments Manager ---------
128 if( FileExists( outputFileName ) )
130 if( !RemoveFile( outputFileName ) )
132 std::cerr << "Ouch, the file exist, but I cannot remove it" << std::endl;
137 int loadMode = 0x0; // load everything
138 GDCM_NAME_SPACE::File *f = GDCM_NAME_SPACE::File::New();
139 f->SetLoadMode( loadMode );
140 f->SetFileName( fileName );
141 bool res = f->Load();
149 // Look for private Papyrus Sequence
150 GDCM_NAME_SPACE::SeqEntry *seqPapyrus= f->GetSeqEntry(0x0041, 0x1050);
153 std::cout << "NOT a Papyrus File : " << fileName <<std::endl;
158 // GDCM_NAME_SPACE::FileHelper *original = new GDCM_NAME_SPACE::FileHelper( fileName );
159 // GDCM_NAME_SPACE::File *h = original->GetFile();
161 //GDCM_NAME_SPACE::FileHelper *f1 = new GDCM_NAME_SPACE::FileHelper(f);
162 GDCM_NAME_SPACE::SQItem *sqi = seqPapyrus->GetFirstSQItem();
165 std::cout << "NO SQItem found within private Papyrus Sequence"
171 std::string TransferSyntax;
172 std::string StudyDate;
173 std::string StudyTime;
174 std::string Modality;
175 std::string PatientName;
176 std::string MediaStSOPinstUID;
178 // Get informations on the file :
179 // Modality, Transfer Syntax, Study Date, Study Time
180 // Patient Name, Media Storage SOP Instance UID, etc
182 MediaStSOPinstUID = f->GetEntryString(0x0002,0x0002);
183 TransferSyntax = f->GetEntryString(0x0002,0x0010);
184 StudyDate = sqi->GetEntryString(0x0008,0x0020);
185 StudyTime = sqi->GetEntryString(0x0008,0x0030);
186 Modality = sqi->GetEntryString(0x0008,0x0060);
187 PatientName = sqi->GetEntryString(0x0010,0x0010);
189 std::cout << "TransferSyntax " << TransferSyntax << std::endl;
193 std::string SamplesPerPixel;
194 std::string BitsAllocated;
195 std::string BitsStored;
197 std::string PixelRepresentation;
200 // we brutally suppose all the images within a Papyrus file
201 // have the same caracteristics.
202 // if you're aware they have not, just move the GetEntryString
205 // Get caracteristics of the first image
206 SamplesPerPixel = sqi->GetEntryString(0x0028,0x0002);
207 Rows = sqi->GetEntryString(0x0028,0x0010);
208 Columns = sqi->GetEntryString(0x0028,0x0011);
209 BitsAllocated = sqi->GetEntryString(0x0028,0x0100);
210 BitsStored = sqi->GetEntryString(0x0028,0x0101);
211 HighBit = sqi->GetEntryString(0x0028,0x0102);
212 PixelRepresentation = sqi->GetEntryString(0x0028,0x0103);
214 // just convert those needed to compute PixelArea length
215 int iRows = (uint32_t) atoi( Rows.c_str() );
216 int iColumns = (uint32_t) atoi( Columns.c_str() );
217 int iSamplesPerPixel = (uint32_t) atoi( SamplesPerPixel.c_str() );
218 int iBitsAllocated = (uint32_t) atoi( BitsAllocated.c_str() );
220 int lgrImage = iRows*iColumns * iSamplesPerPixel * (iBitsAllocated/8);
222 // compute number of images
223 int nbImages = seqPapyrus->GetNumberOfSQItems();
224 std::cout <<"Number of frames :" << nbImages << std::endl;
226 // allocate enough room to get the pixels of all images.
227 uint8_t *PixelArea = new uint8_t[lgrImage*nbImages];
228 uint8_t *currentPosition = PixelArea;
229 GDCM_NAME_SPACE::DataEntry *pixels;
231 // declare and open the file
233 Fp = new std::ifstream(fileName, std::ios::in | std::ios::binary);
236 std::cout << "Cannot open file: " << fileName << std::endl;
241 // to be sure to be at the beginning
242 Fp->seekg(0, std::ios::end);
245 std::string previousRows = Rows;
246 sqi = seqPapyrus->GetFirstSQItem();
249 std::cout << "One more image read. Keep waiting" << std::endl;
250 Rows = sqi->GetEntryString(0x0028,0x0010);
251 // minimum integrity check
252 if (Rows != previousRows)
254 std::cout << "Consistency check failed " << std::endl;
258 // get the images pixels
260 // Oops! The following code assumes Pixel Data is uncompressed :-(
262 pixels = sqi->GetDataEntry(0x7fe0,0x0010);
263 offset = pixels->GetOffset();
264 // perform a fseek, on offset length on the 'right' length
265 Fp->seekg(offset, std::ios::beg);
266 // perform a fread into the right place
267 Fp->read((char *)currentPosition, (size_t)lgrImage);
268 currentPosition +=lgrImage;
270 std::string previousRowNb = Rows;
272 sqi = seqPapyrus->GetNextSQItem();
275 // build up a new File, with file info + images info + global pixel area.
277 std::string NumberOfFrames = GDCM_NAME_SPACE::Util::Format("%d", nbImages);
279 GDCM_NAME_SPACE::File *n = GDCM_NAME_SPACE::File::New();
281 n->InsertEntryString(MediaStSOPinstUID, 0x0002,0x0002);
282 // Whe keep default gdcm Transfer Syntax (Explicit VR Little Endian)
283 // since using Papyrus one (Implicit VR Little Endian) is a mess
284 //n->InsertEntryString(TransferSyntax, 0x0002,0x0010);
285 n->InsertEntryString(StudyDate, 0x0008,0x0020);
286 n->InsertEntryString(StudyTime, 0x0008,0x0030);
287 n->InsertEntryString(Modality, 0x0008,0x0060);
288 n->InsertEntryString(PatientName, 0x0010,0x0010);
290 n->InsertEntryString(SamplesPerPixel, 0x0028,0x0002);
291 n->InsertEntryString(NumberOfFrames, 0x0028,0x0008);
292 n->InsertEntryString(Rows, 0x0028,0x0010);
293 n->InsertEntryString(Columns, 0x0028,0x0011);
294 n->InsertEntryString(BitsAllocated, 0x0028,0x0100);
295 n->InsertEntryString(BitsStored, 0x0028,0x0101);
296 n->InsertEntryString(HighBit, 0x0028,0x0102);
297 n->InsertEntryString(PixelRepresentation,0x0028,0x0103);
300 GDCM_NAME_SPACE::FileHelper *file = GDCM_NAME_SPACE::FileHelper::New(n);
302 file->SetImageData(PixelArea,lgrImage*nbImages);
303 file->SetWriteTypeToDcmExplVR();
305 //file->SetPrintLevel(2);
309 file->Write(outputFileName);
312 std::cout <<"Fail to open (write) file:[" << outputFileName << "]" << std::endl;;