]> Creatis software - gdcm.git/blob - Example/PrintFile.cxx
* Rename the NO_SEQ, NO_SHADOW, NO_SHADOWSEQ to
[gdcm.git] / Example / PrintFile.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: PrintFile.cxx,v $
5   Language:  C++
6   Date:      $Date: 2005/08/30 14:40:28 $
7   Version:   $Revision: 1.49 $
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 "gdcmDocument.h"
20 #include "gdcmSeqEntry.h"
21 #include "gdcmSQItem.h"
22 #include "gdcmBinEntry.h"
23
24 #include "gdcmFileHelper.h"
25 #include "gdcmDebug.h"
26 #include "gdcmDirList.h"
27
28 #include "gdcmArgMgr.h"
29
30 #include <iostream>
31
32
33 void ShowLutData(gdcm::File *f);
34
35 void ShowLutData(gdcm::File *f)
36 {
37      // Nothing is written yet to get LUT Data user friendly
38      // The following is to be moved into a PixelReadConvert method
39      // Let here, waiting for a clever idea on the way to do it.
40   
41       gdcm::SeqEntry *modLutSeq = f->GetSeqEntry(0x0028,0x3000);
42       if ( modLutSeq !=0 )
43       {
44          gdcm::SQItem *sqi= modLutSeq->GetFirstSQItem();
45          if ( sqi != 0 )
46          {
47             std::string lutDescriptor = sqi->GetEntryValue(0x0028,0x3002);
48            if (   /*lutDescriptor   == GDCM_UNFOUND*/ 0 )
49            {
50               //gdcmWarningMacro( "LUT Descriptor is missing" );
51               std::cout << "LUT Descriptor is missing" << std::endl;
52               return;
53             }
54             int length;   // LUT length in Bytes
55             int deb;      // Subscript of the first Lut Value
56             int nbits;    // Lut item size (in Bits)
57
58             int nbRead;    // nb of items in LUT descriptor (must be = 3)
59
60             nbRead = sscanf( lutDescriptor.c_str(),
61                               "%d\\%d\\%d",
62                                &length, &deb, &nbits );
63            std::cout << "length " << length 
64                      << " deb " << deb 
65                      << " nbits " << nbits
66                      << std::endl;
67             if ( nbRead != 3 )
68             {
69                 //gdcmWarningMacro( "Wrong LUT descriptor" );
70                 std::cout << "Wrong LUT descriptor" << std::endl;
71             }
72             //LUT Data (CTX dependent)    
73             gdcm::BinEntry *b = sqi->GetBinEntry(0x0028,0x3006); 
74             if ( b != 0 )
75             { 
76                int BitsAllocated = f->GetBitsAllocated();
77                if ( BitsAllocated <= 8 )
78                { 
79                   int mult;
80                   if ( ( nbits == 16 ) && ( BitsAllocated == 8 ) )
81                   {
82                   // when LUT item size is different than pixel size
83                      mult = 2; // high byte must be = low byte
84                   }
85                   else
86                   {
87                   // See PS 3.3-2003 C.11.1.1.2 p 619
88                      mult = 1;
89                   }
90                   uint8_t *lut = b->GetBinArea();
91                   for( int i=0; i < length; ++i )
92                   {
93                      std::cout << i+deb << " : \t"
94                                << (int) (lut[i*mult + 1]) << std::endl;
95                   }
96                }
97                else
98                {
99                   uint16_t *lut = (uint16_t *)(b->GetBinArea());  
100                   for( int i=0; i < length; ++i )
101                   {
102                      std::cout << i+deb << " : \t"
103                                << (int) (((uint16_t *)lut)[i])
104                                << std::endl;
105                   }             
106                }
107             }  
108             else
109                std::cout << "No LUT Data BinEntry (0x0028,0x3006) found?!? " 
110                          << std::endl;
111          }
112          else
113             std::cout << "No First SQ Item within (0x0028,0x3000) ?!? " 
114                       << std::endl;      
115       }
116       else
117          std::cout << "No LUT Data SeqEntry (0x0028,0x3000) found " 
118                    << std::endl;
119    }
120
121 int main(int argc, char *argv[])
122 {
123
124    START_USAGE(usage)
125    " \n PrintFile : \n                                                        ",
126    " Display the header of a ACR-NEMA/PAPYRUS/DICOM File                      ",
127    " usage: PrintFile {filein=inputFileName|dirin=inputDirectoryName}[level=n]",
128    "                       [forceload=listOfElementsToForceLoad]              ",
129    "                       [ { [noshadowseq] | [noshadow][noseq] } ] [debug]  ",
130    "      level = 0,1,2 : depending on the amount of details user wants to see",
131    "      listOfElementsToForceLOad : group-elem,g2-e2,... (in hexa, no space)",
132    "                                of Elements to load whatever their length ",
133    "        noshadowseq: user doesn't want to load Private Sequences          ",
134    "        noshadow   : user doesn't want to load Private groups (odd number)",
135    "        noseq      : user doesn't want to load Sequences                  ",
136    "        debug      : user wants to run the program in 'debug mode'        ",
137    "        showlut :user wants to display the Palette Color (as an int array)",
138    FINISH_USAGE
139
140    // Initialize Arguments Manager   
141    gdcm::ArgMgr *am= new gdcm::ArgMgr(argc, argv);
142   
143    if (argc == 1 || am->ArgMgrDefined("usage") )
144    {
145       am->ArgMgrUsage(usage); // Display 'usage'
146       delete am;
147       return 0;
148    }
149
150    char *fileName = am->ArgMgrGetString("filein",(char *)0);
151    char *dirName  = am->ArgMgrGetString("dirin",(char *)0);
152
153    if ( (fileName == 0 && dirName == 0)
154         ||
155         (fileName != 0 && dirName != 0) )
156    {
157        std::cout <<std::endl
158                  << "Either 'filein=' or 'dirin=' must be present;" 
159                  << std::endl << "Not both" << std::endl;
160        am->ArgMgrUsage(usage); // Display 'usage'  
161        delete am;
162        return 0;
163  }
164
165    if (am->ArgMgrDefined("debug"))
166       gdcm::Debug::DebugOn();
167  
168    int loadMode = GDCM_LD_ALL;
169    if ( am->ArgMgrDefined("noshadowseq") )
170       loadMode |= GDCM_LD_NOSHADOWSEQ;
171    else 
172    {
173    if ( am->ArgMgrDefined("noshadow") )
174          loadMode |= GDCM_LD_NOSHADOW;
175       if ( am->ArgMgrDefined("noseq") )
176          loadMode |= GDCM_LD_NOSEQ;
177    }
178
179    int level = am->ArgMgrGetInt("level", 2);
180
181    int forceLoadNb;
182    uint16_t *elemsToForceLoad 
183                         = am->ArgMgrGetXInt16Enum("forceload", &forceLoadNb);
184
185    bool showlut = ( 0 != am->ArgMgrDefined("SHOWLUT") );
186
187    /* if unused Param we give up */
188    if ( am->ArgMgrPrintUnusedLabels() )
189    {
190       am->ArgMgrUsage(usage);
191       delete am;
192       return 0;
193    } 
194
195    delete am;  // we don't need Argument Manager any longer
196
197    // ----------- End Arguments Manager ---------
198
199    if ( fileName != 0 ) // ====== Deal with a single file ======
200    { 
201       // gdcm::File::IsReadable() is no usable here, because we deal with
202       // any kind of gdcm-Parsable *document* 
203       // not only gdcm::File (as opposed to gdcm::DicomDir)
204
205       gdcm::File *f = new gdcm::File();
206       f->SetLoadMode(loadMode);
207       f->SetFileName( fileName );
208
209       for (int ri=0; ri<forceLoadNb; ri++)
210       {
211          f->AddForceLoadElement((uint32_t)elemsToForceLoad[2*ri], 
212                                 (uint32_t)elemsToForceLoad[2*ri+1] ); 
213       }
214
215       bool res = f->Load();
216
217       if ( !res )
218       {
219          std::cout << "Cannot process file [" << fileName << "]" << std::endl;
220          std::cout << "Either it doesn't exist, or it's read protected " 
221                    << std::endl;
222          std::cout << "or it's not a Dicom File, or its 'header' is bugged" 
223                    << std::endl;
224          std::cout << "use 'PrintFile filein=... debug' to try to guess the pb"
225                    << std::endl;
226          delete f;
227          return 0;
228       }
229
230       gdcm::FileHelper *fh = new gdcm::FileHelper(f);
231       fh->SetPrintLevel( level );
232
233       fh->Print();
234
235       std::cout << "\n\n" << std::endl; 
236
237       std::cout <<std::endl;
238       std::cout <<" dataSize    " << fh->GetImageDataSize()    << std::endl;
239       std::cout <<" dataSizeRaw " << fh->GetImageDataRawSize() << std::endl;
240
241       int nX,nY,nZ,sPP,planarConfig;
242       std::string pixelType;
243       nX=f->GetXSize();
244       nY=f->GetYSize();
245       nZ=f->GetZSize();
246       std::cout << " DIMX=" << nX << " DIMY=" << nY << " DIMZ=" << nZ << std::endl;
247
248       pixelType    = f->GetPixelType();
249       sPP          = f->GetSamplesPerPixel();
250       planarConfig = f->GetPlanarConfiguration();
251
252       std::cout << " pixelType= ["            << pixelType 
253                 << "] SamplesPerPixel= ["     << sPP
254                 << "] PlanarConfiguration= [" << planarConfig 
255                 << "] "<< std::endl 
256                 << " PhotometricInterpretation= [" 
257                                 << f->GetEntryValue(0x0028,0x0004)
258                 << "] "<< std::endl;
259
260       int numberOfScalarComponents=f->GetNumberOfScalarComponents();
261       std::cout << " NumberOfScalarComponents = " << numberOfScalarComponents 
262                 <<std::endl
263                 << " LUT = " << (f->HasLUT() ? "TRUE" : "FALSE")
264                 << std::endl;
265
266       if ( f->GetEntryValue(0x0002,0x0010) == gdcm::GDCM_NOTLOADED ) 
267       {
268          std::cout << "Transfer Syntax not loaded. " << std::endl
269                    << "Better you increase MAX_SIZE_LOAD_ELEMENT_VALUE"
270                 << std::endl;
271          return 0;
272       }
273   
274       std::string transferSyntaxName = f->GetTransferSyntaxName();
275       std::cout << " TransferSyntaxName= [" << transferSyntaxName << "]" 
276                 << std::endl;
277       std::cout << " SwapCode= " << f->GetSwapCode() << std::endl;
278
279       //std::cout << "\n\n" << std::endl; 
280       //std::cout << "X spacing " << f->GetXSpacing() << std::endl;
281       //std::cout << "Y spacing " << f->GetYSpacing() << std::endl;
282       //std::cout << "Z spacing " << f->GetZSpacing() << std::endl;
283
284       // Display the LUT as an int array (for debugging purpose)
285       if ( f->HasLUT() && showlut )
286       {
287          uint8_t* lutrgba = fh->GetLutRGBA();
288          if ( lutrgba == 0 )
289          {
290             std::cout << "Lut RGBA (Palette Color) not built " << std::endl;
291  
292            // Nothing is written yet to get LUT Data user friendly
293            // The following is to be moved into a PixelRedaConvert method
294   
295             gdcm::SeqEntry *modLutSeq = f->GetSeqEntry(0x0028,0x3000);
296             if ( modLutSeq !=0 )
297             {
298                gdcm::SQItem *sqi= modLutSeq->GetFirstSQItem();
299                if ( !sqi )
300                {
301                std::string lutDescriptor = sqi->GetEntryValue(0x0028,0x3002);
302                   int length;   // LUT length in Bytes
303                   int deb;      // Subscript of the first Lut Value
304                   int nbits;    // Lut item size (in Bits)
305                   int nbRead;    // nb of items in LUT descriptor (must be = 3)
306
307                   nbRead = sscanf( lutDescriptor.c_str(),
308                                     "%d\\%d\\%d",
309                                      &length, &deb, &nbits );
310                   if ( nbRead != 3 )
311                   {
312                       //gdcmWarningMacro( "Wrong LUT descriptor" );
313                       std::cout << "Wrong LUT descriptor" << std::endl;
314                   }                                                  
315                   gdcm::BinEntry *b = sqi->GetBinEntry(0x0028,0x3006);
316                   if ( b != 0 )
317                   {
318                      if ( b->GetLength() != 0 )
319                      {
320                         std::cout << "---------------------------------------"
321                                << " We should never reach this point      "
322                                << std::endl;
323                         //LoadEntryBinArea(b);    //LUT Data (CTX dependent)
324                      }   
325                  }
326               }      
327             }
328             else
329                std::cout << "No LUT Data (0x0028,0x3000) found " << std::endl;
330         }
331          else
332          {
333             if ( fh->GetLutItemSize() == 8 )
334             {
335                for (int i=0;i<fh->GetLutItemNumber();i++)
336                   std::cout << i << " : \t"
337                          << (int)(lutrgba[i*4])   << " "
338                          << (int)(lutrgba[i*4+1]) << " "
339                          << (int)(lutrgba[i*4+2]) << std::endl;
340             }
341             else // LutItemSize assumed to be = 16
342             {
343                uint16_t* lutrgba16 = (uint16_t*)lutrgba;
344                for (int i=0;i<fh->GetLutItemNumber();i++)
345                   std::cout << i << " : \t"
346                          << (int)(lutrgba16[i*4])   << " "
347                          << (int)(lutrgba16[i*4+1]) << " "
348                          << (int)(lutrgba16[i*4+2]) << std::endl;
349             }
350          }
351       }
352       else if (showlut)
353       {
354          std::cout << "Try LUT Data "<< std::endl;
355          ShowLutData(f);
356       }
357      
358       if (f->IsReadable())
359          std::cout <<std::endl<<fileName<<" is Readable"<<std::endl;
360       else
361          std::cout <<std::endl<<fileName<<" is NOT Readable"<<std::endl;
362       std::cout<<std::flush;
363       delete f;
364       delete fh;
365       return 0;
366    }
367    else  // ====== Deal with a Directory ======
368    {
369       std::cout << "dirName [" << dirName << "]" << std::endl;
370       gdcm::DirList dirList(dirName,1); // gets recursively the file list
371       gdcm::DirListType fileList = dirList.GetFilenames();
372       gdcm::File *f;
373       bool res;
374       for( gdcm::DirListType::iterator it  = fileList.begin();
375                                  it != fileList.end();
376                                  ++it )
377       {
378          f = new gdcm::File();
379          f->SetLoadMode(loadMode);
380          f->SetFileName( it->c_str() );
381
382          for (int ri=0; ri<forceLoadNb; ri++)
383          {
384             printf("%04x,%04x\n",elemsToForceLoad[2*ri], elemsToForceLoad[2*ri+1]);
385             f->AddForceLoadElement((uint32_t)elemsToForceLoad[2*ri], 
386                                    (uint32_t)elemsToForceLoad[2*ri+1]); 
387          }
388          res = f->Load();
389
390          if ( !res )
391          {
392             std::cout << "Cannot process file [" << it->c_str() << "]" 
393                       << std::endl;
394             std::cout << "Either it doesn't exist, or it's read protected " 
395                       << std::endl;
396             std::cout << "or it's not a Dicom File, or its 'header' is bugged" 
397                       << std::endl;
398             std::cout << "use 'PrintFile filein=... debug' to try to guess the pb"
399                    << std::endl;
400             delete f;
401             continue;
402          }
403
404          gdcm::FileHelper *fh = new gdcm::FileHelper(f);
405          fh->SetPrintLevel( level );
406
407          fh->Print();
408
409          if (f->IsReadable())
410             std::cout <<std::endl<<it->c_str()<<" is Readable"<<std::endl;
411          else
412             std::cout <<std::endl<<it->c_str()<<" is NOT Readable"<<std::endl;
413          std::cout << "\n\n" << std::endl;
414          delete f;
415          delete fh;
416       }
417       std::cout<<std::flush;
418    }
419 }