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