1 /*=========================================================================
4 Module: $RCSfile: exReadPapyrus.cxx,v $
6 Date: $Date: 2005/06/27 15:46:27 $
7 Version: $Revision: 1.2 $
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 "gdcmValEntry.h"
22 #include "gdcmBinEntry.h"
23 #include "gdcmSeqEntry.h"
24 #include "gdcmSQItem.h"
25 #include "gdcmDebug.h"
28 #include "gdcmArgMgr.h"
34 #include <unistd.h> //for access, unlink
36 #include <io.h> //for _access
39 // return true if the file exists
40 bool FileExists(const char *filename)
43 # define access _access
48 if ( access(filename, R_OK) != 0 )
58 bool RemoveFile(const char *source)
61 #define _unlink unlink
63 return unlink(source) != 0 ? false : true;
66 // ----------------------------------------------------------------------
67 // Here we load a supposed to be Papyrus File (gdcm::File compliant)
68 // and then try to get the pixels, using low-level SeqEntry accessors.
69 // Since it's not a general purpose Papyrus related program
70 // (just a light example) we suppose *everything* is clean
71 // and we don't perform any integrity check
72 // ----------------------------------------------------------------------
74 int main(int argc, char *argv[])
78 " \n exReadPapyrus :\n",
79 " Reads a Papyrus V3 File, Writes a Multiframe Dicoim V3 File ",
80 " (just to show gdcm can do it ...) ",
82 " usage: exReadPapyrus filein=inputPapyrusFileName fileout=outputDicomFileName",
84 " debug : user wants to run the program in 'debug mode' ",
88 // ----- Initialize Arguments Manager ------
90 gdcm::ArgMgr *am = new gdcm::ArgMgr(argc, argv);
92 if (am->ArgMgrDefined("usage"))
94 am->ArgMgrUsage(usage); // Display 'usage'
98 char *fileName = am->ArgMgrWantString("filein",usage);
99 if ( fileName == NULL )
105 char *outputFileName = am->ArgMgrWantString("fileout",usage);
106 if ( outputFileName == NULL )
112 if (am->ArgMgrDefined("debug"))
113 gdcm::Debug::DebugOn();
115 // if unused Params we give up
116 if ( am->ArgMgrPrintUnusedLabels() )
118 am->ArgMgrUsage(usage);
123 delete am; // we don't need Argument Manager any longer
125 // ----------- End Arguments Manager ---------
127 if( FileExists( outputFileName ) )
129 if( !RemoveFile( outputFileName ) )
131 std::cerr << "Ouch, the file exist, but I cannot remove it" << std::endl;
136 int loadMode = 0x0; // load everything
137 gdcm::File *e1 = new gdcm::File();
138 e1->SetLoadMode(loadMode);
140 bool res = e1->Load( fileName );
147 // Look for private Papyrus Sequence
148 gdcm::SeqEntry *seqPapyrus= e1->GetSeqEntry(0x0041, 0x1050);
151 std::cout << "NOT a Papyrus File : " << fileName <<std::endl;
156 // gdcm::FileHelper *original = new gdcm::FileHelper( fileName );
157 // gdcm::File *h = original->GetFile();
159 //gdcm::FileHelper *f1 = new gdcm::FileHelper(e1);
160 gdcm::SQItem *sqi = seqPapyrus->GetFirstSQItem();
163 std::cout << "NO SQItem found within private Papyrus Sequence"
169 std::string TransferSyntax;
170 std::string StudyDate;
171 std::string StudyTime;
172 std::string Modality;
173 std::string PatientName;
174 std::string MediaStSOPinstUID;
176 // Get informations on the file :
177 // Modality, Transfer Syntax, Study Date, Study Time
178 // Patient Name, Media Storage SOP Instance UID, etc
180 MediaStSOPinstUID = e1->GetEntryValue(0x0002,0x0002);
181 TransferSyntax = e1->GetEntryValue(0x0002,0x0010);
182 StudyDate = sqi->GetEntryValue(0x0008,0x0020);
183 StudyTime = sqi->GetEntryValue(0x0008,0x0030);
184 Modality = sqi->GetEntryValue(0x0008,0x0060);
185 PatientName = sqi->GetEntryValue(0x0010,0x0010);
187 std::cout << "TransferSyntax " << TransferSyntax << std::endl;
191 std::string SamplesPerPixel;
192 std::string BitsAllocated;
193 std::string BitsStored;
195 std::string PixelRepresentation;
198 // we brutally suppose all the images within a Papyrus file
199 // have the same caracteristics.
200 // if you're aware they have not, just move the GetEntryValue
203 // Get caracteristics of the first image
204 SamplesPerPixel = sqi->GetEntryValue(0x0028,0x0002);
205 Rows = sqi->GetEntryValue(0x0028,0x0010);
206 Columns = sqi->GetEntryValue(0x0028,0x0011);
207 BitsAllocated = sqi->GetEntryValue(0x0028,0x0100);
208 BitsStored = sqi->GetEntryValue(0x0028,0x0101);
209 HighBit = sqi->GetEntryValue(0x0028,0x0102);
210 PixelRepresentation = sqi->GetEntryValue(0x0028,0x0103);
212 // just convert those needed to compute PixelArea length
213 int iRows = (uint32_t) atoi( Rows.c_str() );
214 int iColumns = (uint32_t) atoi( Columns.c_str() );
215 int iSamplesPerPixel = (uint32_t) atoi( SamplesPerPixel.c_str() );
216 int iBitsAllocated = (uint32_t) atoi( BitsAllocated.c_str() );
218 int lgrImage = iRows*iColumns * iSamplesPerPixel * (iBitsAllocated/8);
220 // compute number of images
221 int nbImages = seqPapyrus->GetNumberOfSQItems();
222 std::cout <<"Number of frames :" << nbImages << std::endl;
224 // allocate enough room to get the pixels of all images.
225 uint8_t *PixelArea = new uint8_t[lgrImage*nbImages];
226 uint8_t *currentPosition = PixelArea;
227 gdcm::BinEntry *pixels;
229 // declare and open the file
231 Fp = new std::ifstream(fileName, std::ios::in | std::ios::binary);
234 std::cout << "Cannot open file: " << fileName << std::endl;
235 //gdcmDebugMacro( "Cannot open file: " << fileName.c_str() );
240 // to be sure to be at the beginning
241 Fp->seekg(0, std::ios::end);
244 std::string previousRows = Rows;
245 sqi = seqPapyrus->GetFirstSQItem();
248 std::cout << "One more image read. Keep waiting" << std::endl;
249 Rows = sqi->GetEntryValue(0x0028,0x0010);
250 // minimum integrity check
251 if (Rows != previousRows)
253 std::cout << "Consistency check failed " << std::endl;
256 // get the images pixels
257 pixels = sqi->GetBinEntry(0x7fe0,0x0010);
258 offset = pixels->GetOffset();
259 // perform a fseek, on offset length on the 'right' length
260 Fp->seekg(offset, std::ios::beg);
261 // perform a fread into the right place
262 Fp->read((char *)currentPosition, (size_t)lgrImage);
263 currentPosition +=lgrImage;
265 std::string previousRowNb = Rows;
267 sqi = seqPapyrus->GetNextSQItem();
270 // build up a new File, with file info + images info + global pixel area.
272 std::string NumberOfFrames = gdcm::Util::Format("%d", nbImages);
274 gdcm::File *n = new gdcm::File();
276 n->InsertValEntry(MediaStSOPinstUID, 0x0002,0x0002);
277 // Whe keep default gdcm Transfer Syntax (Explicit VR Little Endian)
278 // since using Papyrus one (Implicit VR Little Endian) is a mess
279 //n->InsertValEntry(TransferSyntax, 0x0002,0x0010);
280 n->InsertValEntry(StudyDate, 0x0008,0x0020);
281 n->InsertValEntry(StudyTime, 0x0008,0x0030);
282 n->InsertValEntry(Modality, 0x0008,0x0060);
283 n->InsertValEntry(PatientName, 0x0010,0x0010);
285 n->InsertValEntry(SamplesPerPixel, 0x0028,0x0002);
286 n->InsertValEntry(NumberOfFrames, 0x0028,0x0008);
287 n->InsertValEntry(Rows, 0x0028,0x0010);
288 n->InsertValEntry(Columns, 0x0028,0x0011);
289 n->InsertValEntry(BitsAllocated, 0x0028,0x0100);
290 n->InsertValEntry(BitsStored, 0x0028,0x0101);
291 n->InsertValEntry(HighBit, 0x0028,0x0102);
292 n->InsertValEntry(PixelRepresentation,0x0028,0x0103);
295 gdcm::FileHelper *file = new gdcm::FileHelper(n);
297 file->SetImageData(PixelArea,lgrImage*nbImages);
298 file->SetWriteTypeToDcmExplVR();
300 //file->SetPrintLevel(2);
304 file->Write(outputFileName);
307 std::cout <<"Fail to open (write) file:[" << outputFileName << "]" << std::endl;;