]> Creatis software - gdcm.git/blob - Example/exReadPapyrus.cxx
ENH: fix link + update info
[gdcm.git] / Example / exReadPapyrus.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: exReadPapyrus.cxx,v $
5   Language:  C++
6   Date:      $Date: 2007/05/23 14:18:05 $
7   Version:   $Revision: 1.8 $
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 "gdcmDataEntry.h"
22 #include "gdcmSeqEntry.h"
23 #include "gdcmSQItem.h"
24 #include "gdcmDebug.h"
25 #include "gdcmUtil.h"
26
27 #include "gdcmArgMgr.h"
28 #include <iostream>
29
30 //#include <fstream>
31
32 #ifndef _WIN32
33 #include <unistd.h> //for access, unlink
34 #else
35 #include <io.h> //for _access
36 #endif
37
38 // return true if the file exists
39 bool FileExists(const char *filename)
40 {
41 #ifdef _MSC_VER
42 # define access _access
43 #endif
44 #ifndef R_OK
45 # define R_OK 04
46 #endif
47   if ( access(filename, R_OK) != 0 )
48     {
49     return false;
50     }
51   else
52     {
53     return true;
54     }
55 }
56
57 bool RemoveFile(const char *source)
58 {
59 #ifdef _MSC_VER
60 #define _unlink unlink
61 #endif
62   return unlink(source) != 0 ? false : true;
63 }
64
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 // ----------------------------------------------------------------------
72
73 int main(int argc, char *argv[])
74 {
75
76    START_USAGE(usage)
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 :-(",
82    "",
83    " usage: exReadPapyrus filein=inputPapyrusFileName fileout=outputDicomFileName", 
84    "                      [debug]  ", 
85    "        debug    : developper wants to run the program in 'debug mode'        ",
86    FINISH_USAGE
87
88
89    // ----- Initialize Arguments Manager ------
90    
91    GDCM_NAME_SPACE::ArgMgr *am = new GDCM_NAME_SPACE::ArgMgr(argc, argv);
92   
93    if (am->ArgMgrDefined("usage")) 
94    {
95       am->ArgMgrUsage(usage); // Display 'usage'
96       delete am;
97       return 0;
98    }
99    char *fileName = am->ArgMgrWantString("filein",usage);
100    if ( fileName == NULL )
101    {
102       delete am;
103       return 0;
104    }
105
106    char *outputFileName = am->ArgMgrWantString("fileout",usage);
107    if ( outputFileName == NULL )
108    {
109       delete am;
110       return 0;
111    }
112
113    if (am->ArgMgrDefined("debug"))
114       GDCM_NAME_SPACE::Debug::DebugOn();
115  
116    // if unused Params we give up
117    if ( am->ArgMgrPrintUnusedLabels() )
118    { 
119       am->ArgMgrUsage(usage);
120       delete am;
121       return 0;
122    }
123
124    delete am;  // we don't need Argument Manager any longer
125
126    // ----------- End Arguments Manager ---------
127
128    if( FileExists( outputFileName ) )
129    {
130       if( !RemoveFile( outputFileName ) )
131       {
132          std::cerr << "Ouch, the file exist, but I cannot remove it" << std::endl;
133          return 1;
134       }
135    }
136
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();  
142
143    if ( !res )
144    {
145       f->Delete();
146       return 0;
147    }
148
149    // Look for private Papyrus Sequence
150    GDCM_NAME_SPACE::SeqEntry *seqPapyrus= f->GetSeqEntry(0x0041, 0x1050);
151    if (!seqPapyrus)
152    {
153       std::cout << "NOT a Papyrus File : " << fileName <<std::endl;
154       f->Delete();
155       return 1;
156    }
157
158 //   GDCM_NAME_SPACE::FileHelper *original = new GDCM_NAME_SPACE::FileHelper( fileName );
159 //   GDCM_NAME_SPACE::File *h = original->GetFile();
160
161    //GDCM_NAME_SPACE::FileHelper *f1 = new GDCM_NAME_SPACE::FileHelper(f);
162    GDCM_NAME_SPACE::SQItem *sqi = seqPapyrus->GetFirstSQItem();
163    if (sqi == 0)
164    {
165       std::cout << "NO SQItem found within private Papyrus Sequence"
166           << std::endl;
167       f->Delete();
168       return 1;
169    }
170       
171    std::string TransferSyntax;
172    std::string StudyDate;
173    std::string StudyTime;
174    std::string Modality;
175    std::string PatientName;
176    std::string MediaStSOPinstUID;
177
178 // Get informations on the file : 
179 //  Modality, Transfer Syntax, Study Date, Study Time
180 // Patient Name, Media Storage SOP Instance UID, etc
181
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);
188
189    std::cout << "TransferSyntax " << TransferSyntax << std::endl;
190
191    std::string Rows;
192    std::string Columns;
193    std::string SamplesPerPixel;
194    std::string BitsAllocated;
195    std::string BitsStored;
196    std::string HighBit;
197    std::string PixelRepresentation;
198    
199
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
203    // inside the loop
204
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);
213
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() );
219
220    int lgrImage = iRows*iColumns * iSamplesPerPixel * (iBitsAllocated/8);
221
222    // compute number of images
223    int nbImages = seqPapyrus->GetNumberOfSQItems();
224    std::cout <<"Number of frames :" << nbImages << std::endl;  
225
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;
230
231    // declare and open the file
232    std::ifstream *Fp;
233    Fp = new std::ifstream(fileName, std::ios::in | std::ios::binary);
234    if( ! *Fp )
235    {
236       std::cout <<  "Cannot open file: " << fileName << std::endl;
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->GetEntryString(0x0028,0x0010);
251       // minimum integrity check
252       if (Rows != previousRows)
253       {
254          std::cout << "Consistency check failed " << std::endl;
255          return 1;
256       }
257      
258       // get the images pixels
259       
260       // Oops! The following code assumes Pixel Data is uncompressed :-(
261       
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;
269
270       std::string previousRowNb = Rows;
271
272       sqi =  seqPapyrus->GetNextSQItem();
273    }
274
275    // build up a new File, with file info + images info + global pixel area.
276
277    std::string NumberOfFrames = GDCM_NAME_SPACE::Util::Format("%d", nbImages); 
278
279    GDCM_NAME_SPACE::File *n = GDCM_NAME_SPACE::File::New();
280
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);
289
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);
298
299    // create the file
300    GDCM_NAME_SPACE::FileHelper *file = GDCM_NAME_SPACE::FileHelper::New(n);
301
302    file->SetImageData(PixelArea,lgrImage*nbImages);
303    file->SetWriteTypeToDcmExplVR();
304
305    //file->SetPrintLevel(2);
306    n->Print();
307
308    // Write the file
309    file->Write(outputFileName); 
310    if (!file)
311    {
312       std::cout <<"Fail to open (write) file:[" << outputFileName << "]" << std::endl;;
313       n->Delete();
314       file->Delete();
315       return 1;  
316    }
317    n->Delete();
318    file->Delete();
319    return 0;
320 }