]> Creatis software - gdcm.git/blob - Example/exPresentationState.cxx
minor improvements
[gdcm.git] / Example / exPresentationState.cxx
1  
2  /*=========================================================================
3                                                                                 
4   Program:   gdcm
5   Module:    $RCSfile: exPresentationState.cxx,v $
6   Language:  C++
7   Date:      $Date: 2009/05/28 15:44:34 $
8   Version:   $Revision: 1.3 $
9                                                                                 
10   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
11   l'Image). All rights reserved. See Doc/License.txt or
12   http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
13                                                                                 
14      This software is distributed WITHOUT ANY WARRANTY; without even
15      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16      PURPOSE.  See the above copyright notices for more information.
17                                                                                 
18 =========================================================================*/
19
20 #include "gdcmFile.h"
21 // ----------
22 //#include "gdcmValEntry.h"
23 #include "gdcmDataEntry.h"
24 // ----------
25 #include "gdcmSeqEntry.h"
26 #include "gdcmSQItem.h"
27 #include "gdcmDocEntrySet.h"
28 #include "gdcmSerieHelper.h"
29 #include "gdcmDirList.h"
30 #include "gdcmUtil.h"
31
32 #include "gdcmArgMgr.h"
33   
34   GDCM_NAME_SPACE::SeqEntry *CheckIfSequenceExists(GDCM_NAME_SPACE::File *fPS,  uint16_t gr, uint16_t el);
35   GDCM_NAME_SPACE::SeqEntry *CheckIfSequenceExists(GDCM_NAME_SPACE::SQItem *si, uint16_t gr, uint16_t el);   
36   bool dealWithTopLevelItem(GDCM_NAME_SPACE::SQItem* currentItem);
37   bool dealWithEndLevelItem(GDCM_NAME_SPACE::SQItem* currentItem);
38   void displaySeekResult(GDCM_NAME_SPACE::SeqEntry* currentItem, uint16_t g, uint16_t e);
39   void dealWithSequence(GDCM_NAME_SPACE::SeqEntry* se);
40 // -------------------------------------------------------------------------------------------------------
41
42 int main(int argc, char *argv[])
43 {
44    START_USAGE(usage)
45    "\n exPresentationState :\n                                                ",
46    "Extracts and displays the Graphic annotation / Text Objet Sequences of gdcm-parsable Dicom file",
47    "                                                                          ",
48    "usage: exPresentationState {filein=inputFileName|dirin=inputDirectoryName}",
49    "                       [ { [noshadowseq] | [noshadow][noseq] } ] [debug]  ",
50    "       filein : Name of the image  file                                   ",
51    "       PSFile : Name of the PresentationState  file :                     ", 
52    "       noshadowseq: user doesn't want to load Private Sequences           ",
53    "       noshadow   : user doesn't want to load Private groups (odd number) ",
54    "       noseq      : user doesn't want to load Sequences                   ",
55    "       verbose    : developper wants to run the program in 'verbose mode' ",
56    "       debug      : developper wants to run the program in 'debug mode'   ",
57    "                                                                          ",
58    " you can use it as :                                                      ",
59    " for i in `ls PS*`; do exPresentationState PSFile=$i; done                ",
60    " just to see ...                                                          ",
61    FINISH_USAGE
62
63    // ----- Initialize Arguments Manager ------
64   
65    GDCM_NAME_SPACE::ArgMgr *am = new GDCM_NAME_SPACE::ArgMgr(argc, argv);
66   
67    if (am->ArgMgrDefined("usage") || argc == 1) 
68    {
69       am->ArgMgrUsage(usage); // Display 'usage'
70       delete am;
71       return 0;
72    }
73    
74       if (am->ArgMgrDefined("debug"))
75       GDCM_NAME_SPACE::Debug::DebugOn();
76
77    bool verbose = am->ArgMgrDefined("verbose");
78    
79    const char *fileName = am->ArgMgrGetString("filein");
80    const char *PSName   = am->ArgMgrGetString("PSfile");  
81    
82       /* if unused Param we give up */
83    if ( am->ArgMgrPrintUnusedLabels() )
84    {
85       am->ArgMgrUsage(usage);
86       delete am;
87       return 0;
88    }  
89    delete am;  // ------ we don't need Arguments Manager any longer ------
90
91 // ============================================================
92 //   Read the input image.
93 // ============================================================ 
94
95    GDCM_NAME_SPACE::File *f = GDCM_NAME_SPACE::File::New( );
96
97 /*
98    //f->SetLoadMode(GDCM_NAME_SPACE::LD_NOSEQ | GDCM_NAME_SPACE::LD_NOSHADOW);
99    f->SetFileName( fileName );
100    f->SetMaxSizeLoadEntry(0xffff);
101    bool res = f->Load();  
102
103    if( GDCM_NAME_SPACE::Debug::GetDebugFlag())
104    {
105       std::cout << "---------------------------------------------" << std::endl;
106       f->Print();
107       std::cout << "---------------------------------------------" << std::endl;
108    }
109    if (!res) {
110        std::cerr << "Sorry, " << fileName << " not a gdcm-readable "
111            << "DICOM / ACR File"
112            << std::endl;
113       f->Delete();
114       return 1;
115    }
116    std::cout << " ... is readable " << std::endl;
117 */
118
119 // =================================================================================
120
121    GDCM_NAME_SPACE::File *fPS = GDCM_NAME_SPACE::File::New( );
122    fPS->SetFileName( PSName );
123    fPS->SetMaxSizeLoadEntry(0xffff);
124    bool res2 = fPS->Load();
125            
126    if (!res2) {
127        std::cout << "Sorry, " << PSName << " not a gdcm-readable "
128            << "DICOM / ACR File"
129            << std::endl;
130       f->Delete();
131       return 1;
132    }
133    
134    GDCM_NAME_SPACE::SeqEntry *se;
135    
136    se = CheckIfSequenceExists( fPS, 0x0070, 0x0001);
137    //displaySeekResult(se, 0x0070, 0x0001);
138    if (!se)
139    {
140          std::cout << "[" << PSName << "] : Hopeless (" << std::hex <<  0x0070 << "|" << 0x0001 << std::dec << " doesn't exist...)" <<std::endl;
141          exit (0);      
142    }
143    std::cout << "\n\n =========================================================================================" <<std::endl;       
144    std::cout << "[" << PSName << "] is a gdcm-readable PresentationState file, "
145              << "that (probabely?) holds one or more 'ROI' within [0070|0001] (Graphic Annotation Sequence)"   <<std::endl; 
146    std::cout << " =========================================================================================\n\n" <<std::endl;
147
148    GDCM_NAME_SPACE::SQItem* currentItem = se->GetFirstSQItem(); // Get the first 'ROI'
149    if (currentItem == NULL)
150    {
151       std::cout << "======== Deal With NOTHING! (Sequence 0070|0001 [Graphic Annotation Sequence] has NO item ?!?)" << std::endl;
152    }
153    int i =0;
154    while (currentItem != NULL)
155    {
156         std::cout << "======== Deal With 'ROI' n." << i << std::endl;
157
158         // do what you want with the current 'ROI'
159          dealWithTopLevelItem(currentItem);
160         //...
161
162         currentItem = se->GetNextSQItem(); // Get the next 'ROI'
163         i++;
164    }
165    
166  /*         
167   bool res3 = TestPresentationState(f, fPS);
168   
169   if (res3)
170   {
171      std::cout << "[" << PSName << "] is a gdcm-readable PresentationState file" <<std::endl; 
172   }
173   else
174   {
175      std::cout << "Sorry, [" << PSName << "] is not a gdcm-readable PresentationState file" <<std::endl; 
176   }
177 */
178    
179    
180    f->Delete();
181    fPS->Delete();
182    
183    std::cout << "\n\n"  <<std::endl;  
184 return 0;
185 }
186
187 //----------------------------------------------------------------------------------------------------
188  
189 bool dealWithTopLevelItem(GDCM_NAME_SPACE::SQItem* currentItem)
190 {
191   // probably this list should be cleaned up.
192   // (I didn't find the exact architecture of Presentation State)
193    int tabElement[] = {         0x0008, 0x0009, 0x005a, 0x0060, 0x0086, 
194                         0x0308, 0x0309, 0x030A, 0x030d, 0x0311, 0x0314, 
195                         0x0318, 0x031c, 0x031e, 0x0402, 0x0404, 0x0000 };
196
197    bool res = false;
198    GDCM_NAME_SPACE::SeqEntry *se;
199    
200    se = CheckIfSequenceExists(currentItem, 0x0008, 0x1140);
201    displaySeekResult(se, 0x0008, 0x1140); 
202    if (se != 0)
203    {
204       res = true;
205       dealWithSequence(se);
206    }
207       
208    for(int i=0; tabElement[i]!=0x0000; i++)
209    {
210       se = CheckIfSequenceExists(currentItem, 0x0070, tabElement[i]);
211       //displaySeekResult(se, 0x0070, tabElement[i]);       
212       if (se != 0)
213       {
214          res = true;
215          dealWithSequence(se);
216       }
217    } 
218    return (res);
219 }
220
221
222 //----------------------------------------------------------------------------------------------------
223  
224 bool dealWithEndLevelItem(GDCM_NAME_SPACE::SQItem* currentItem)
225 {
226   // probably this list should be cleaned up, too.
227   // (I didn't find the exact architecture of Presentation State)
228    int tabElement[] = {         0x0008, 0x0009, 0x005a, 0x0060, 0x0086, 
229                         0x0308, 0x0309, 0x030A, 0x030d, 0x0311, 0x0314, 
230                         0x0318, 0x031c, 0x031e, 0x0402, 0x0404, 0x0000 };
231
232    bool res = false;
233    GDCM_NAME_SPACE::SeqEntry *se;
234    
235    se = CheckIfSequenceExists(currentItem, 0x0008, 0x1140);
236    displaySeekResult(se, 0x0008, 0x1140); 
237    if (se != 0)
238    {
239       res = true;
240       dealWithSequence(se);
241    }
242       
243    for(int i=0; tabElement[i]!=0x0000; i++)
244    {
245       se = CheckIfSequenceExists(currentItem, 0x0070, tabElement[i]);
246       displaySeekResult(se, 0x0070, tabElement[i]);       
247       if (se != 0)
248       {
249          res = true;
250          dealWithSequence(se);
251       }
252    } 
253    return (res);
254 }
255 //----------------------------------------------------------------------------------------------------
256
257 void dealWithSequence(GDCM_NAME_SPACE::SeqEntry* se)
258 {    
259    uint16_t g = se->GetGroup();
260    uint16_t e = se->GetElement();
261    std::cout << std::hex << "\n------------------------ deal with " << g <<"|" << e <<  std::dec 
262              << "  " << se->GetName() << std::endl;
263      
264    GDCM_NAME_SPACE::SQItem *si = se->GetFirstSQItem();
265    if (!si) {
266       std::cout << "Sequence " << std::hex << g <<"|" << e <<  std::dec <<  "has no Item ?!?" << std::endl;
267       return;
268    }
269    
270    if (g == 0x0008) {
271
272       si->Print(std::cout);
273    } else if (g == 0x0070) {
274    
275       si->Print(std::cout);   
276    } else {
277       std::cout << "Unexpected Group " << std::hex << g << std::hex << std::endl;
278    }
279    
280    si =  se->GetNextSQItem();
281    if (si)
282    {
283       std::cout << "Sequence " << std::hex << g <<"|" << e <<  std::dec <<  "should have only ONE Item ?!?" << std::endl;
284       si->Print(std::cout);
285       return;
286    }
287 }
288
289 //----------------------------------------------------------------------------------------------------
290
291 void displaySeekResult(GDCM_NAME_SPACE::SeqEntry* se, uint16_t g, uint16_t e)
292 {  
293       if (se)
294       {
295         // std::cout << std::hex <<  g << "|" << e << std::dec << " [" << se->GetName() << "] exists" <<std::endl;
296       }
297       else
298       {
299          std::cout << " No " << std::hex <<  g << "|" << e << std::dec << " found" <<std::endl;
300       }
301 }
302       
303 //----------------------------------------------------------------------------------------------------  
304
305 bool TestPresentationState(GDCM_NAME_SPACE::File *f, GDCM_NAME_SPACE::File *fPS)
306 {
307
308 /*------------------------------------------------------
309
310 0070 0001 SQ 1 Graphic Annotation Sequence
311 0070 0008 SQ 1 Text Object Sequence
312 0070 0009 SQ 1 Graphic Object Sequence
313 0070 005a SQ 1 Displayed Area Selection Sequence
314 0070 0060 SQ 1 Graphic Layer Sequence
315 0070 0086 SQ 1 Content Creator's Identification Code Sequence
316 0070 0308 SQ 1 Registration Sequence
317 0070 0309 SQ 1 Matrix Registration Sequence
318 0070 030a SQ 1 Matrix Sequence
319 0070 030d SQ 1 Registration Type Code Sequence
320 0070 0311 SQ 1 Fiducial Identifier Code Sequence
321 0070 0314 SQ 1 Used Fiducials Sequence
322 0070 0318 SQ 1 Graphic Coordinates Data Sequence
323 0070 031c SQ 1 Fiducial Set Sequence
324 0070 031e SQ 1 Fiducial Sequence
325 0070 0402 SQ 1 Blending Sequence
326 0070 0404 SQ 1 Referenced Spatial Registration Sequence
327 ------------------------------------------------------- */
328
329 /*------------------------------------------------------
330 Relevant part of Dicom V3 Dict
331
332 0070 0000 UL 1 Group Length
333 0070 0001 SQ 1 Graphic Annotation Sequence
334 0070 0002 CS 1 Graphic Layer
335 0070 0003 CS 1 Bounding Box Annotation Units
336 0070 0004 CS 1 Anchor Point Annotation Units
337 0070 0005 CS 1 Graphic Annotation Units
338 0070 0006 ST 1 Unformatted Text Value
339 0070 0008 SQ 1 Text Object Sequence
340 0070 0009 SQ 1 Graphic Object Sequence
341 0070 0010 FL 2 Bounding Box Top Left Hand Corner
342 0070 0011 FL 2 Bounding Box Bottom Right Hand Corner
343 0070 0012 CS 1 Bounding Box Text Horizontal Justification
344 0070 0014 FL 2 Anchor Point
345 0070 0015 CS 1 Anchor Point Visibility
346 0070 0020 US 1 Graphic Dimensions
347 0070 0021 US 1 Number of Graphic Points
348 0070 0022 FL 2-2n Graphic Data
349 0070 0023 CS 1 Graphic Type
350 0070 0024 CS 1 Graphic Filled
351 0070 0041 CS 1 Image Horizontal Flip
352 0070 0042 US 1 Image Rotation
353 0070 0052 SL 2 Displayed Area Top Left Hand Corner
354 0070 0053 SL 2 Displayed Area Bottom Right Hand Corner
355 0070 005a SQ 1 Displayed Area Selection Sequence
356 0070 0060 SQ 1 Graphic Layer Sequence
357 0070 0062 IS 1 Graphic Layer Order
358 0070 0066 US 1 Graphic Layer Recommended Display Grayscale Value
359 0070 0067 US 3 Graphic Layer Recommended Display RGB Value (RET)
360 0070 0068 LO 1 Graphic Layer Description
361 0070 0080 CS 1 Content Label
362 0070 0081 LO 1 Content Description
363 0070 0082 DA 1 Presentation Creation Date
364 0070 0083 TM 1 Presentation Creation Time
365 0070 0084 PN 1 Content Creator's Name
366 0070 0086 SQ 1 Content Creator's Identification Code Sequence
367 0070 0100 CS 1 Presentation Size Mode
368 0070 0101 DS 2 Presentation Pixel Spacing
369 0070 0102 IS 2 Presentation Pixel Aspect Ratio
370 0070 0103 FL 1 Presentation Pixel Magnification Ratio
371 0070 0306 CS 1 Shape Type
372 0070 0308 SQ 1 Registration Sequence
373 0070 0309 SQ 1 Matrix Registration Sequence
374 0070 030a SQ 1 Matrix Sequence
375 0070 030c CS 1 Frame of Reference Transformation Matrix Type
376 0070 030d SQ 1 Registration Type Code Sequence
377 0070 030f ST 1 Fiducial Description
378 0070 0310 SH 1 Fiducial Identifier
379 0070 0311 SQ 1 Fiducial Identifier Code Sequence
380 0070 0312 FD 1 Contour Uncertainty Radius
381 0070 0314 SQ 1 Used Fiducials Sequence
382 0070 0318 SQ 1 Graphic Coordinates Data Sequence
383 0070 031a UI 1 Fiducial UID
384 0070 031c SQ 1 Fiducial Set Sequence
385 0070 031e SQ 1 Fiducial Sequence
386 0070 0401 US 3 Graphic Layer Recommended Display CIELab Value
387 0070 0402 SQ 1 Blending Sequence
388 0070 0403 FL 1 Relative Opacity
389 0070 0404 SQ 1 Referenced Spatial Registration Sequence
390 0070 0405 CS 1 Blending Position
391 ------------------------------------------------------- */
392
393 }
394
395
396 // ----------------------------------------------------------------------------------
397
398
399
400 // ----------------------------------------------------------------------------------
401
402
403 GDCM_NAME_SPACE::SeqEntry *CheckIfSequenceExists( GDCM_NAME_SPACE::File *fPS, uint16_t gr, uint16_t el)
404 {
405    GDCM_NAME_SPACE::SeqEntry *se= fPS->GetSeqEntry(gr, el);
406    return se;     
407 }
408
409 // ----------------------------------------------------------------------------------
410   
411 GDCM_NAME_SPACE::SeqEntry *CheckIfSequenceExists( GDCM_NAME_SPACE::SQItem *si, uint16_t gr, uint16_t el)
412 {
413    GDCM_NAME_SPACE::SeqEntry *se= si->GetSeqEntry(gr, el);
414    return se;     
415 }