]> Creatis software - gdcm.git/blob - Example/exReadPapyrus.cxx
99badbf87958d3f38cefa1e4550dc82588f40810
[gdcm.git] / Example / exReadPapyrus.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: exReadPapyrus.cxx,v $
5   Language:  C++
6   Date:      $Date: 2005/07/07 17:31:54 $
7   Version:   $Revision: 1.3 $
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.
12                                                                                 
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.
16                                                                                 
17 =========================================================================*/
18 #include "gdcmFile.h"
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"
26 #include "gdcmUtil.h"
27
28 #include "gdcmArgMgr.h"
29 #include <iostream>
30
31 //#include <fstream>
32
33 #ifndef _WIN32
34 #include <unistd.h> //for access, unlink
35 #else
36 #include <io.h> //for _access
37 #endif
38
39 // return true if the file exists
40 bool FileExists(const char *filename)
41 {
42 #ifdef _MSC_VER
43 # define access _access
44 #endif
45 #ifndef R_OK
46 # define R_OK 04
47 #endif
48   if ( access(filename, R_OK) != 0 )
49     {
50     return false;
51     }
52   else
53     {
54     return true;
55     }
56 }
57
58 bool RemoveFile(const char *source)
59 {
60 #ifdef _MSC_VER
61 #define _unlink unlink
62 #endif
63   return unlink(source) != 0 ? false : true;
64 }
65
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 // ----------------------------------------------------------------------
73
74 int main(int argc, char *argv[])
75 {
76
77    START_USAGE(usage)
78    " \n exReadPapyrus :\n",
79    " Reads a Papyrus V3 File, Writes a Multiframe Dicoim V3 File ",
80    "     (just to show gdcm can do it ...)               ",
81    "",
82    " usage: exReadPapyrus filein=inputPapyrusFileName fileout=outputDicomFileName", 
83    "                      [debug]  ", 
84    "        debug    : user wants to run the program in 'debug mode'        ",
85    FINISH_USAGE
86
87
88    // ----- Initialize Arguments Manager ------
89    
90    gdcm::ArgMgr *am = new gdcm::ArgMgr(argc, argv);
91   
92    if (am->ArgMgrDefined("usage")) 
93    {
94       am->ArgMgrUsage(usage); // Display 'usage'
95       delete am;
96       return 0;
97    }
98    char *fileName = am->ArgMgrWantString("filein",usage);
99    if ( fileName == NULL )
100    {
101       delete am;
102       return 0;
103    }
104
105    char *outputFileName = am->ArgMgrWantString("fileout",usage);
106    if ( outputFileName == NULL )
107    {
108       delete am;
109       return 0;
110    }
111
112    if (am->ArgMgrDefined("debug"))
113       gdcm::Debug::DebugOn();
114  
115    // if unused Params we give up
116    if ( am->ArgMgrPrintUnusedLabels() )
117    { 
118       am->ArgMgrUsage(usage);
119       delete am;
120       return 0;
121    }
122
123    delete am;  // we don't need Argument Manager any longer
124
125    // ----------- End Arguments Manager ---------
126
127    if( FileExists( outputFileName ) )
128    {
129       if( !RemoveFile( outputFileName ) )
130       {
131          std::cerr << "Ouch, the file exist, but I cannot remove it" << std::endl;
132          return 1;
133       }
134    }
135
136    int loadMode = 0x0; // load everything
137    gdcm::File *f = new gdcm::File();
138    f->SetLoadMode( loadMode );
139    f->SetFileName( fileName );
140    bool res = f->Load();  
141
142    if ( !res )
143    {
144       delete f;
145       return 0;
146    }
147
148    // Look for private Papyrus Sequence
149    gdcm::SeqEntry *seqPapyrus= f->GetSeqEntry(0x0041, 0x1050);
150    if (!seqPapyrus)
151    {
152       std::cout << "NOT a Papyrus File : " << fileName <<std::endl;
153       delete f;
154       return 1;
155    }
156
157 //   gdcm::FileHelper *original = new gdcm::FileHelper( fileName );
158 //   gdcm::File *h = original->GetFile();
159
160    //gdcm::FileHelper *f1 = new gdcm::FileHelper(f);
161    gdcm::SQItem *sqi = seqPapyrus->GetFirstSQItem();
162    if (sqi == 0)
163    {
164       std::cout << "NO SQItem found within private Papyrus Sequence"
165           << std::endl;
166       delete f;
167       return 1;
168    }
169       
170    std::string TransferSyntax;
171    std::string StudyDate;
172    std::string StudyTime;
173    std::string Modality;
174    std::string PatientName;
175    std::string MediaStSOPinstUID;
176
177 // Get informations on the file : 
178 //  Modality, Transfer Syntax, Study Date, Study Time
179 // Patient Name, Media Storage SOP Instance UID, etc
180
181    MediaStSOPinstUID   =  f->GetEntryValue(0x0002,0x0002);
182    TransferSyntax      =  f->GetEntryValue(0x0002,0x0010);
183    StudyDate           = sqi->GetEntryValue(0x0008,0x0020);
184    StudyTime           = sqi->GetEntryValue(0x0008,0x0030);
185    Modality            = sqi->GetEntryValue(0x0008,0x0060);
186    PatientName         = sqi->GetEntryValue(0x0010,0x0010);
187
188    std::cout << "TransferSyntax " << TransferSyntax << std::endl;
189
190    std::string Rows;
191    std::string Columns;
192    std::string SamplesPerPixel;
193    std::string BitsAllocated;
194    std::string BitsStored;
195    std::string HighBit;
196    std::string PixelRepresentation;
197    
198
199    // we brutally suppose all the images within a Papyrus file
200    // have the same caracteristics.
201    // if you're aware they have not, just move the GetEntryValue
202    // inside the loop
203
204    // Get caracteristics of the first image
205    SamplesPerPixel     = sqi->GetEntryValue(0x0028,0x0002);
206    Rows                = sqi->GetEntryValue(0x0028,0x0010);
207    Columns             = sqi->GetEntryValue(0x0028,0x0011);
208    BitsAllocated       = sqi->GetEntryValue(0x0028,0x0100);
209    BitsStored          = sqi->GetEntryValue(0x0028,0x0101);
210    HighBit             = sqi->GetEntryValue(0x0028,0x0102);
211    PixelRepresentation = sqi->GetEntryValue(0x0028,0x0103);
212
213    // just convert those needed to compute PixelArea length
214    int iRows            = (uint32_t) atoi( Rows.c_str() );
215    int iColumns         = (uint32_t) atoi( Columns.c_str() );
216    int iSamplesPerPixel = (uint32_t) atoi( SamplesPerPixel.c_str() );
217    int iBitsAllocated   = (uint32_t) atoi( BitsAllocated.c_str() );
218
219    int lgrImage = iRows*iColumns * iSamplesPerPixel * (iBitsAllocated/8);
220
221    // compute number of images
222    int nbImages = seqPapyrus->GetNumberOfSQItems();
223    std::cout <<"Number of frames :" << nbImages << std::endl;  
224
225    //  allocate enough room to get the pixels of all images.
226    uint8_t *PixelArea = new uint8_t[lgrImage*nbImages];
227    uint8_t *currentPosition = PixelArea;
228    gdcm::BinEntry *pixels;
229
230    // declare and open the file
231    std::ifstream *Fp;
232    Fp = new std::ifstream(fileName, std::ios::in | std::ios::binary);
233    if( ! *Fp )
234    {
235       std::cout <<  "Cannot open file: " << fileName << std::endl;
236       //gdcmDebugMacro( "Cannot open file: " << fileName.c_str() );
237       delete Fp;
238       Fp = 0;
239       return 0;
240    }
241    // to be sure to be at the beginning
242    Fp->seekg(0, std::ios::end);
243
244    uint32_t offset;
245    std::string previousRows = Rows;
246    sqi = seqPapyrus->GetFirstSQItem();
247    while (sqi)
248    {
249       std::cout << "One more image read. Keep waiting" << std::endl;
250       Rows = sqi->GetEntryValue(0x0028,0x0010);
251       // minimum integrity check
252       if (Rows != previousRows)
253       {
254          std::cout << "Consistency check failed " << std::endl;
255          return 1;
256       }
257       // get the images pixels
258       pixels = sqi->GetBinEntry(0x7fe0,0x0010);
259       offset = pixels->GetOffset();
260       // perform a fseek, on offset length on the 'right' length
261       Fp->seekg(offset, std::ios::beg);
262       // perform a fread into the right place
263       Fp->read((char *)currentPosition, (size_t)lgrImage);
264       currentPosition +=lgrImage;
265
266       std::string previousRowNb = Rows;
267
268       sqi =  seqPapyrus->GetNextSQItem();
269    }
270
271    // build up a new File, with file info + images info + global pixel area.
272
273    std::string NumberOfFrames = gdcm::Util::Format("%d", nbImages); 
274
275    gdcm::File *n = new gdcm::File();
276
277    n->InsertValEntry(MediaStSOPinstUID,  0x0002,0x0002);
278   // Whe keep default gdcm Transfer Syntax (Explicit VR Little Endian)
279   // since using Papyrus one (Implicit VR Little Endian) is a mess
280    //n->InsertValEntry(TransferSyntax,     0x0002,0x0010);
281    n->InsertValEntry(StudyDate,          0x0008,0x0020);
282    n->InsertValEntry(StudyTime,          0x0008,0x0030);
283    n->InsertValEntry(Modality,           0x0008,0x0060);
284    n->InsertValEntry(PatientName,        0x0010,0x0010);
285
286    n->InsertValEntry(SamplesPerPixel,    0x0028,0x0002);
287    n->InsertValEntry(NumberOfFrames,     0x0028,0x0008);
288    n->InsertValEntry(Rows,               0x0028,0x0010);
289    n->InsertValEntry(Columns,            0x0028,0x0011);
290    n->InsertValEntry(BitsAllocated,      0x0028,0x0100);
291    n->InsertValEntry(BitsStored,         0x0028,0x0101);
292    n->InsertValEntry(HighBit,            0x0028,0x0102);
293    n->InsertValEntry(PixelRepresentation,0x0028,0x0103);
294
295    // create the file
296    gdcm::FileHelper *file = new gdcm::FileHelper(n);
297
298    file->SetImageData(PixelArea,lgrImage*nbImages);
299    file->SetWriteTypeToDcmExplVR();
300
301    //file->SetPrintLevel(2);
302    n->Print();
303
304    // Write the file
305    file->Write(outputFileName); 
306    if (!file)
307    {
308       std::cout <<"Fail to open (write) file:[" << outputFileName << "]" << std::endl;;
309       return 1;  
310    }
311    return 0;
312 }