]> Creatis software - gdcm.git/blob - Example/ToInTag.cxx
Avoid warning
[gdcm.git] / Example / ToInTag.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: ToInTag.cxx,v $
5   Language:  C++
6   Date:      $Date: 2007/07/04 17:39:28 $
7   Version:   $Revision: 1.17 $
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 "gdcmDocEntry.h"
19 #include "gdcmDicomDir.h"
20 #include "gdcmDicomDirPatient.h"
21 #include "gdcmFile.h"
22 #include "gdcmFileHelper.h"
23 #include "gdcmDirList.h"
24 #include "gdcmDebug.h"
25 #include "gdcmArgMgr.h"
26 #include "gdcmUtil.h"
27 #include "gdcmSerieHelper.h"
28
29 #include <iostream>
30
31 /**
32   * \brief   
33   *          - explores recursively the given directory
34   *          - keeps the requested series
35   *          - orders the gdcm-readable found Files
36   *            according to their Patient/Study/Serie/Image characteristics
37   *          - fills a single level Directory with *all* the files,
38   *            converted into a Brucker-like Dicom, Intags compliant
39   */  
40
41 typedef std::map<std::string, GDCM_NAME_SPACE::File*> SortedFiles;
42
43 int main(int argc, char *argv[]) 
44 {
45    START_USAGE(usage)
46    " \n ToInTag :\n                                                           ",
47    " - explores recursively the given directory,                              ",
48    " - keeps the requested series/ drops the unrequested series               ",
49    " - orders the gdcm-readable found Files according to their                ",
50    "           (0x0010, 0x0010) Patient's Name                                ",
51    "           (0x0020, 0x000e) Series Instance UID                           ",
52    "           (0x0020, 0x0032) Image Position (Patient)                      ",
53    "           (0x0018, 0x1060) Trigger Time                                  ",
54    "           (0x0018, 0x1312) In-plane Phase Encoding Direction             ",
55    " - fills a single level (*) Directory with *all* the files,               ",
56    "           converted into a Brucker-like Dicom, InTags compliant          ",
57    "   (*) actually : creates as many directories as Patients                 ",
58    "                  -that shouldn't appear, but being carefull is better!-  ",
59    " or                                                                       ",
60    " - fills a tree-like structure of directories as :                        ",
61    "        - Patient                                                         ",
62    "        -- Serie                                                          ",
63    "        --- Position                                                      ",
64    "        ---- Images (sorted by Trigger Time /                             ",
65    "                               Encoding Direction (Row, Column)           ",
66    "                                                                          ",
67    "      Note : when (0008|1090) [Model Name ] equals 'TrioTim ' :           ",
68    "         - (0008|103e)[Series Description ] is checked for                ",
69    "            '90' (-> COL) or '0' (-> ROW)                                 ",
70    "         - (0x0020, 0x000e) [Series Instance UID] is NOT dealt with,      ",
71    "           since row an col tagging are in 2 different Series             ",
72    "           DO NOT supply a directory holding different exams              ",
73    "           for the same Slice level!                                      ",
74    "      uses :                                                              ",
75    "           0x0021, 0x1020 : 'SLICE INDEX'                                 ",
76    "           0x0021, 0x1040 : 'FRAME INDEX'                                 ",
77    "           0x0020, 0x0012 : 'SESSION INDEX'  (Acquisition Number)         ",
78    "                                                                          ",
79    " usage:                                                                   ",
80    " -----                                                                    ",
81    " ToInTag          dirin=rootDirectoryName                                 ",
82    "                  dirout=outputDirectoryName                              ",
83    "                  {  [keep= list of seriesNumber to process]              ",
84    "                   | [drop= list of seriesNumber to ignore] }             ",
85    "                  [taggrid] [skel]                                        ",
86    "                  [input = {ACR|DCM|IDO}]                                 ", 
87    "                  [extent=image suffix (.IMA, .NEMA, .DCM, ...)]          ",
88    "                  [listonly] [split] [rubout]                             ",
89    "                  [noshadowseq][noshadow][noseq] [verbose] [debug]        ",
90    "                                                                          ",
91    " dirout : will be created if doesn't exist                                ",
92    " keep : if user wants to process a limited number of series               ",
93    "            he gives the list of 'SeriesNumber' (tag 0020|0011)           ",
94    " drop : if user wants to ignore a limited number of series                ",
95    "            he gives the list of 'SeriesNumber' (tag 0020|0011)           ",   
96    "        SeriesNumber are short enough to be human readable                ",
97    "        e.g : 1030,1035,1043                                              ", 
98    " taggrid : user knows all the images are 'grid' -ie: not 'col', not 'raw'-",
99    " extent : DO NOT forget the leading '.' !                                 ",
100    " input : IDO when *realy* old libIDO images                               ",
101    " skel: name skeleton eg : patName_1.nema -> skel=patName_                 ",
102    " split: creates a tree-like structure of directories as :                 ",
103    "        - Patient                                                         ",
104    "        -- Serie                                                          ",
105    "        --- Position                                                      ",
106    "        ---- Images (sorted by Trigger Time /                             ",
107    "                               Encoding Direction (Row, Column)           ",
108    " rubout : user asks to rubout burnt-in image number                       ",
109    " noshadowseq: user doesn't want to load Private Sequences                 ",
110    " noshadow : user doesn't want to load Private groups (odd number)         ",
111    " noseq    : user doesn't want to load Sequences                           ",
112    " verbose  : user wants to run the program in 'verbose mode'               ",
113    " debug    : *developer*  wants to run the program in 'debug mode'         ",
114    FINISH_USAGE
115
116    std::cout << "inside ToInTag" << std::endl;
117    
118    // ----- Initialize Arguments Manager ------
119       
120    GDCM_NAME_SPACE::ArgMgr *am = new GDCM_NAME_SPACE::ArgMgr(argc, argv);
121   
122    if (argc == 1 || am->ArgMgrDefined("usage")) 
123    {
124       am->ArgMgrUsage(usage); // Display 'usage'
125       delete am;
126       return 0;
127    }
128
129    const char *dirNamein;   
130    dirNamein  = am->ArgMgrGetString("dirin","."); 
131
132    const char *dirNameout;   
133    dirNameout  = am->ArgMgrGetString("dirout",".");  
134    
135    int loadMode = GDCM_NAME_SPACE::LD_ALL;
136    if ( am->ArgMgrDefined("noshadowseq") )
137       loadMode |= GDCM_NAME_SPACE::LD_NOSHADOWSEQ;
138    else 
139    {
140    if ( am->ArgMgrDefined("noshadow") )
141          loadMode |= GDCM_NAME_SPACE::LD_NOSHADOW;
142       if ( am->ArgMgrDefined("noseq") )
143          loadMode |= GDCM_NAME_SPACE::LD_NOSEQ;
144    }
145
146    if (am->ArgMgrDefined("debug"))
147       GDCM_NAME_SPACE::Debug::DebugOn();
148       
149    int verbose  = am->ArgMgrDefined("verbose");
150    int split    = am->ArgMgrDefined("split");
151    int listonly = am->ArgMgrDefined("listonly");
152    
153    bool rubout = ( 0 != am->ArgMgrDefined("rubout") ); 
154            
155    int nbSeriesToKeep;
156    int *seriesToKeep = am->ArgMgrGetListOfInt("keep", &nbSeriesToKeep);
157    int nbSeriesToDrop;
158    int *seriesToDrop = am->ArgMgrGetListOfInt("drop", &nbSeriesToDrop);
159  
160    if ( nbSeriesToKeep!=0 && nbSeriesToDrop!=0)
161    {
162       std::cout << "KEEP and DROP are mutually exclusive !" << std::endl;
163       delete am;
164       return 0;         
165    }
166    
167    int taggrid = am->ArgMgrDefined("taggrid");
168    
169    int hasSkel = am->ArgMgrDefined("skel");
170    const char *skel;
171    if (hasSkel)
172       skel = am->ArgMgrGetString("skel");   
173       
174    const char *extent  = am->ArgMgrGetString("extent",".DCM");
175    const char *input  = am->ArgMgrGetString("input","DCM");
176    
177    // if unused Param we give up
178    if ( am->ArgMgrPrintUnusedLabels() )
179    { 
180       am->ArgMgrUsage(usage);
181       delete am;
182       return 0;
183    }
184    delete am;  // we don't need Argument Manager any longer
185
186    // ----- Begin Processing -----
187    
188    if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirNamein) )
189    {
190       std::cout << "KO : [" << dirNamein << "] is not a Directory." << std::endl;
191       return 0;
192
193    }
194    else
195    {
196       std::cout << "OK : [" << dirNamein << "] is a Directory." << std::endl;
197    }
198
199    std::string systemCommand;
200    
201    std::cout << "Check for output directory :[" << dirNameout << "]."
202              <<std::endl;
203    if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirNameout) )    // dirout not found
204    {
205       std::string strDirNameout(dirNameout);          // to please gcc 4
206       systemCommand = "mkdir " +strDirNameout;        // create it!
207       if (verbose)
208          std::cout << systemCommand << std::endl;
209       system (systemCommand.c_str());
210       if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirNameout) ) // be sure it worked
211       {
212           std::cout << "KO : not a dir : [" << dirNameout << "] (creation failure ?)" << std::endl;
213       return 0;
214
215       }
216       else
217       {
218         std::cout << "Directory [" << dirNameout << "] created." << std::endl;
219       }
220    }
221    else
222    {
223        std::cout << "Output Directory [" << dirNameout << "] already exists; Used as is." << std::endl;
224    }
225     
226    std::string strDirNamein(dirNamein);
227    GDCM_NAME_SPACE::DirList dirList(strDirNamein, true); // get recursively the list of files
228    
229    if (listonly)
230    {
231       std::cout << "------------List of found files ------------" << std::endl;
232       dirList.Print();
233       std::cout << std::endl;
234    }
235    
236    GDCM_NAME_SPACE::DirListType fileNames;
237    fileNames = dirList.GetFilenames();
238    GDCM_NAME_SPACE::SerieHelper *s;              // Needed to use SerieHelper::AddSeriesDetail()
239    s = GDCM_NAME_SPACE::SerieHelper::New();
240
241    std::string token = "%%%"; // Hope it's enough!
242 /*       
243    std::cout << "---------------Print Serie--------------" << std::endl; 
244    s->SetDirectory(dirNamein, true); // true : recursive exploration 
245    s->SetUseSeriesDetails(true);  
246    s->AddSeriesDetail(0x0018, 0x1312);   
247    s->Print();
248 */
249   
250    GDCM_NAME_SPACE::File *f;
251    GDCM_NAME_SPACE::FileHelper *fh;
252    std::vector<std::string> tokens;
253    std::vector<std::string> tokensForFileName;
254    
255    // For Siemens pb, we need Manufacturer's Model Name
256    
257    GDCM_NAME_SPACE::DirListType::iterator it1 = fileNames.begin();
258    f = GDCM_NAME_SPACE::File::New();
259    f->SetLoadMode(GDCM_NAME_SPACE::LD_ALL);
260    f->SetFileName( *it1 );
261    f->Load();
262    std::string modelName = f->GetEntryString(0x0008,0x1090);
263    f->Delete();   
264    
265 /*   
266    std::cout << "---------------Print Unique Series identifiers---------"  
267              << std::endl;     
268    std::string uniqueSeriesIdentifier;
269  
270    for (GDCM_NAME_SPACE::DirListType::iterator it) = fileNames.begin();  
271                                     it != fileNames.end();
272                                   ++it)
273    {
274       std::cout << "File Name : " << *it << std::endl;
275       f = GDCM_NAME_SPACE::File::New();
276       f->SetLoadMode(GDCM_NAME_SPACE::LD_ALL);
277       f->SetFileName( *it );
278       f->Load();
279         
280       uniqueSeriesIdentifier=s->CreateUniqueSeriesIdentifier(f);
281       std::cout << "                           [" <<
282                uniqueSeriesIdentifier  << "]" << std::endl;       
283       f->Delete();
284    }
285 */
286    
287    if (verbose)
288       std::cout << "------------------Print Break levels-----------------" << std::endl;
289
290    std::string userFileIdentifier; 
291    SortedFiles sf;
292
293    s->AddSeriesDetail(0x0010, 0x0010, false); // Patient's Name
294    // for Siemens TrioTim, don't deal with 'Series Instance UID'
295    if ( !GDCM_NAME_SPACE::Util::DicomStringEqual(modelName,"TrioTim") ) 
296       s->AddSeriesDetail(0x0020, 0x000e, false); // Series Instance UID
297    else
298       s->AddSeriesDetail(0x9999, 0x9999, false); // dirty trick to ignore 'Series Instance UID'
299    s->AddSeriesDetail(0x0020, 0x0032, false); // Image Position (Patient)     
300    s->AddSeriesDetail(0x0018, 0x1060, true);  // Trigger Time (true: convert to keep numerical order)
301    s->AddSeriesDetail(0x0018, 0x1312, false); // In-plane Phase Encoding Direction 
302    s->AddSeriesDetail(0x0008, 0x103e, false); // Series Description (special Siemens ...)  
303
304    //uint8_t *imageData; // Useless : pixels will not be loaded 
305                          //          (images are overwritten)
306          
307    for (GDCM_NAME_SPACE::DirListType::iterator it = fileNames.begin();  
308                                     it != fileNames.end();
309                                   ++it)
310    {
311       f = GDCM_NAME_SPACE::File::New();
312       f->SetLoadMode(loadMode);
313       f->SetFileName( *it );
314       f->Load();
315
316       std::string strSeriesNumber;
317       int seriesNumber;
318       int j;
319
320       // keep only requested Series      
321       bool keep = false;
322       if (nbSeriesToKeep != 0)
323       {     
324          strSeriesNumber = f->GetEntryString(0x0020, 0x0011 );
325          seriesNumber = atoi( strSeriesNumber.c_str() );
326          for (j=0;j<nbSeriesToKeep; j++)
327          {
328             if(seriesNumber == seriesToKeep[j])
329             {
330                keep = true;
331                break;
332             }
333          }
334          if ( !keep)
335          {
336             f->Delete();
337             continue;
338          } 
339       }
340       // drop all unrequested Series
341       bool drop = false;
342       if (nbSeriesToDrop != 0)
343       {     
344          strSeriesNumber = f->GetEntryString(0x0020, 0x0011 );
345          seriesNumber = atoi( strSeriesNumber.c_str() );
346          for (j=0;j<nbSeriesToDrop; j++)
347          {
348             if(seriesNumber == seriesToDrop[j])
349             { 
350                drop = true;
351                break;
352             }
353         }
354         if (drop)
355         {
356            f->Delete();
357            continue;
358         }
359       } 
360
361       userFileIdentifier=s->CreateUserDefinedFileIdentifier(f); 
362       tokens.clear();
363       GDCM_NAME_SPACE::Util::Tokenize (userFileIdentifier, tokens, token); 
364    
365       int imageNum; // Within FileName
366       char newName[1024];
367       
368       if ( tokens[3] == GDCM_NAME_SPACE::GDCM_UNFOUND)  // sometimes Trigger Time is not found. CreateUserDefinedFileIdentifier is not aware of the pb.
369       {
370          ///this is a trick to build up a lexicographical compliant name :
371          ///     eg : fich001.ima vs fich100.ima as opposed to fich1.ima vs fich100.ima
372          std::string name = GDCM_NAME_SPACE::Util::GetName( *it );
373          if (hasSkel)
374          {
375             GDCM_NAME_SPACE::Util::Tokenize (name, tokensForFileName, skel);
376             imageNum = atoi ( tokensForFileName[0].c_str() );
377             // probabely we could write something much more complicated using C++ !
378             sprintf (newName, "%s%06d%s", skel, imageNum, extent);
379             tokens[3] = newName;
380             tokensForFileName.clear();    
381          }
382          else
383             tokens[3] = name;
384  
385          // Patient's Name
386          // Series Instance UID
387          // Image Position (Patient)
388          // Trigger Time
389          // In-plane Phase Encoding Direction
390          // Series Description
391          // FileName
392  
393          userFileIdentifier = tokens[0] + token + tokens[1] + token + tokens[2] + token 
394                     + tokens[3] + token + tokens[4] + token + tokens[5] + token +  tokens[6] + token;
395       }
396          
397       if (verbose) 
398          std::cout << "[" << userFileIdentifier  << "] : " << *it << std::endl;
399                
400       // storing in a map ensures automatic sorting !      
401       sf[userFileIdentifier] = f;
402    }
403    
404    if (verbose)
405       std::cout << "  " << std::endl;
406       
407    std::string fullFilename, lastFilename;
408    std::string previousPatientName, currentPatientName;
409    std::string previousSerieInstanceUID, currentSerieInstanceUID;
410    std::string previousImagePosition, currentImagePosition;
411    std::string previousPhaseEncodingDirection, currentPhaseEncodingDirection;
412    std::string previousTriggerTime, currentTriggerTime;
413    
414    std::string currentStudyUID;
415    std::string seriesDescription;  
416       
417    std::string writeDir, currentWriteDir;
418    std::string currentPatientWriteDir, currentSerieWriteDir, 
419                currentPositionWriteDir, currentPhaseEncodingDirectionWriteDir;
420
421    std::string fullWriteFilename;
422    std::string strExtent(extent); 
423            
424    writeDir = GDCM_NAME_SPACE::Util::NormalizePath(dirNameout);     
425    SortedFiles::iterator it2;
426  
427    previousPatientName            = "";
428    previousSerieInstanceUID       = "";   
429    previousImagePosition          = "";
430    previousPhaseEncodingDirection = "";
431    previousTriggerTime            = "";
432    
433    int sliceIndex = 0; // Is incremented *at the beginning* of processing
434    int frameIndex;
435    if (taggrid)
436        frameIndex = 0;
437    else
438        frameIndex = 1;
439       
440    int flag       = 0;
441        
442    GDCM_NAME_SPACE::File *currentFile;
443
444    std::string defaultStudyUID =  GDCM_NAME_SPACE::Util::CreateUniqueUID();
445    std::string defaultSerieUID;
446      
447    for (it2 = sf.begin() ; it2 != sf.end(); ++it2)
448    {  
449       currentFile = it2->second;
450        
451       fullFilename =  currentFile->GetFileName();
452       lastFilename =  GDCM_NAME_SPACE::Util::GetName( fullFilename );
453       if (verbose) 
454       std::cout <<" ------------------------------------------------------------------------------" 
455                 << std::endl << " Deal with [" << it2->first << "] : ["<<fullFilename << "]" 
456                 << std::endl;
457      
458       tokens.clear();
459       GDCM_NAME_SPACE::Util::Tokenize (it2->first, tokens, token);
460       
461       currentPatientName            = tokens[0];
462       currentSerieInstanceUID       = tokens[1];
463       currentImagePosition          = tokens[2];
464       currentTriggerTime            = tokens[3];
465       currentPhaseEncodingDirection = tokens[4];
466       seriesDescription             = tokens[5];  // For Siemens pb
467
468       if ( currentImagePosition[0] == '-')
469           currentImagePosition[0] = 'M';
470       if ( currentImagePosition[0] == '+')
471           currentImagePosition[0] = 'P'; 
472
473       // Add a default ImagePositionPatient to avoid confusion at post processing time
474       if ( currentFile->GetEntryString(0x0020,0x0032) == GDCM_NAME_SPACE::GDCM_UNFOUND && 
475            currentFile->GetEntryString(0x0020,0x0030) == GDCM_NAME_SPACE::GDCM_UNFOUND )
476       {
477          currentFile->InsertEntryString("0.\\0.\\0.",0x0020, 0x0032, "DS" );
478       }
479
480       // Add a default ImagePositionPatient to avoid confusion at post processing time
481       if ( currentFile->GetEntryString(0x0020,0x0037) == GDCM_NAME_SPACE::GDCM_UNFOUND && 
482            currentFile->GetEntryString(0x0020,0x0035) == GDCM_NAME_SPACE::GDCM_UNFOUND )
483       {
484          currentFile->InsertEntryString("1.\\0.\\0.\\0.\\1.\\0.",0x0020, 0x0037, "DS" );
485       }
486       
487       if (previousPatientName != currentPatientName)
488       {      
489          if ( currentFile->GetEntryString(0x0020,0x000d) == GDCM_NAME_SPACE::GDCM_UNFOUND) // Study UID
490          {
491             if (verbose)   
492                std::cout << "--- new  Study UID created" << std::endl;
493             defaultStudyUID =  GDCM_NAME_SPACE::Util::CreateUniqueUID();
494          }
495   
496          previousPatientName = currentPatientName;
497          if (verbose)   
498             std::cout << "==== new Patient  [" << currentPatientName  << "]" << std::endl;
499     
500          previousPatientName            = currentPatientName;
501          previousSerieInstanceUID       = ""; //currentSerieInstanceUID;
502          previousImagePosition          = ""; //currentImagePosition;
503          previousTriggerTime            = "";
504          previousPhaseEncodingDirection = ""; //currentPhaseEncodingDirection;
505   
506          currentPatientWriteDir = writeDir + currentPatientName;
507          //if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(currentPatientWriteDir) )
508            {
509               systemCommand   = "mkdir " + currentPatientWriteDir;
510               if (verbose)
511                  std::cout << systemCommand << std::endl;
512               system ( systemCommand.c_str() );
513          }
514       }
515       currentFile->InsertEntryString(defaultStudyUID, 0x0020, 0x000d, "UI" );
516       
517
518       if ( GDCM_NAME_SPACE::Util::DicomStringEqual(modelName,"TrioTim") ) // for Siemens TrioTim , don't deal with 'Series Instance UID'
519
520       if (previousSerieInstanceUID != currentSerieInstanceUID)
521       {        
522          if (verbose)   
523             std::cout << "==== === new Serie [" << currentSerieInstanceUID << "]"
524                       << std::endl;
525       
526          if ( currentFile->GetEntryString(0x0020,0x000e) == GDCM_NAME_SPACE::GDCM_UNFOUND)
527          {
528             if (verbose)   
529                std::cout << "--- --- new  Serie UID created" << std::endl;
530             defaultSerieUID =  GDCM_NAME_SPACE::Util::CreateUniqueUID();
531            // currentFile->InsertEntryString(defaultSerieUID, 0x0020, 0x000e, "UI" );
532          }       
533       
534          if (split)
535          {
536              currentSerieWriteDir  = currentPatientWriteDir + GDCM_NAME_SPACE::GDCM_FILESEPARATOR
537                              + currentSerieInstanceUID;
538              systemCommand   = "mkdir " + currentSerieWriteDir;  
539              system (systemCommand.c_str());
540          }
541          previousSerieInstanceUID       = currentSerieInstanceUID;
542          previousImagePosition          = ""; //currentImagePosition;
543          previousPhaseEncodingDirection = ""; //currentPhaseEncodingDirection;
544       }
545       currentFile->InsertEntryString(defaultSerieUID, 0x0020, 0x000e, "UI" );
546             
547       // end of modelName != "TrioTim "
548    
549       if (previousImagePosition != currentImagePosition)
550       {
551          frameIndex = 1;
552          flag = 0;        
553          if (verbose)   
554             std::cout << "=== === === new Position [" << currentImagePosition  << "]"
555                       << std::endl;
556          if (split)
557          {
558              currentPositionWriteDir  = currentSerieWriteDir + GDCM_NAME_SPACE::GDCM_FILESEPARATOR
559                              + currentImagePosition;
560              systemCommand   = "mkdir " + currentPositionWriteDir;     
561              system (systemCommand.c_str()); 
562          }
563          previousImagePosition          = currentImagePosition;
564          previousPhaseEncodingDirection = ""; //currentPhaseEncodingDirection;
565          if (split)
566             sliceIndex = 1; // only *one* slice in a given directory
567          else
568             sliceIndex += 1;
569       }
570
571 // We don't split on Row/Column!
572 /*
573       if (previousPhaseEncodingDirection != currentPhaseEncodingDirection)
574       {        
575          if (verbose)   
576             std::cout << "==== === === === new PhaseEncodingDirection [" 
577                       << currentPhaseEncodingDirection  << "]" << std::endl;
578       
579          if (split)
580          {
581              currentPhaseEncodingDirectionWriteDir  = currentPositionWriteDir 
582                              + GDCM_NAME_SPACE::GDCM_FILESEPARATOR
583                              + currentPhaseEncodingDirection;
584              systemCommand   = "mkdir " + currentPhaseEncodingDirectionWriteDir;     
585              system (systemCommand.c_str());     
586          }      
587     
588          previousPhaseEncodingDirection = currentPhaseEncodingDirection;
589       } 
590 */    
591    
592       if ( GDCM_NAME_SPACE::Debug::GetDebugFlag())
593          std::cout << "--- --- --- --- --- " << it2->first << "  " 
594                    << (it2->second)->GetFileName() << " " 
595                    << GDCM_NAME_SPACE::Util::GetName( fullFilename ) << std::endl;           
596       
597       // Transform the image to be 'Brucker-Like'
598       // ----------------------------------------   
599     
600       // Deal with 0x0019, 0x1000 : 'FOV'
601       int nX = currentFile->GetXSize();
602       int nY = currentFile->GetYSize();
603       float pxSzX = currentFile->GetXSpacing();
604       float pxSzY = currentFile->GetYSpacing();
605       char fov[64];
606       sprintf(fov, "%f\\%f",nX*pxSzX, nY*pxSzY);
607       if (currentFile->IsVRCoherent(0x0019) == 1 )
608          currentFile->InsertEntryString(fov, 0x0019, 0x1000, "  ");
609       else     
610          currentFile->InsertEntryString(fov, 0x0019, 0x1000, "DS");
611
612      
613       // Deal with 0x0020, 0x0012 : 'SESSION INDEX'  (Acquisition Number)
614       std::string chSessionIndex;
615       // CLEANME
616
617       if (taggrid)
618       { 
619          chSessionIndex = "1";
620       }
621       else
622       {
623       /* for SIEMENS MRI :
624         D 0008|1090 [LO] [Manufacturer's Model Name ] [Triotim ]
625         we have to deal with :
626      
627         D 0008|103e [LO]  [Series Description ] [fl2d9_line PA 15 90deg] or anything that contains '90' !
628         D 0008|103e [LO]  [Series Description ] [fl2d9_line PA 15 0deg ]
629         (everything is flagged as 'ROW')
630       */  
631
632          if ( GDCM_NAME_SPACE::Util::DicomStringEqual(modelName,"TrioTim") )  
633          {
634             if (seriesDescription.find("90", 0) != std::string::npos)
635                chSessionIndex = "1";  // 90 deg -> COL
636             else if (seriesDescription.find("0", 0)!= std::string::npos)
637                chSessionIndex = "2";  // 0 deg -> ROW
638             else
639             {
640                std::cout << "====================== seriesDescription doesn't contain"
641                          << " neither '90' nor '0' (?!?) : ["
642                          << seriesDescription << "]" << std::endl;
643                chSessionIndex = "1";
644             }    
645          } 
646          else  // for all other 'normal' cases
647          {
648             if (currentPhaseEncodingDirection == "COL" || currentPhaseEncodingDirection == "COL " || currentPhaseEncodingDirection == " COL")
649                chSessionIndex = "1";
650             else if (currentPhaseEncodingDirection == "ROW" || currentPhaseEncodingDirection == "ROW "|| currentPhaseEncodingDirection == " ROW")
651                chSessionIndex = "2"; 
652             else
653             {
654                std::cout << "====================== PhaseEncodingDirection "
655                          << " neither COL nor ROW (?!?) : [ "
656                          << currentPhaseEncodingDirection << "]" << std::endl;
657                chSessionIndex = "1";
658             }
659          }
660       }
661       
662       if (currentFile->IsVRCoherent(0x0020) == 1 )     
663          currentFile->InsertEntryString(chSessionIndex, 0x0020, 0x0012, "  ");
664       else
665          currentFile->InsertEntryString(chSessionIndex, 0x0020, 0x0012, "IS");
666  
667       // Deal with  0x0021, 0x1020 : 'SLICE INDEX'
668       char chSliceIndex[5];
669       sprintf(chSliceIndex, "%04d", sliceIndex);
670       std::string strChSliceIndex(chSliceIndex);
671        
672       // Deal with  0x0021, 0x1040 : 'FRAME INDEX' 
673       char chFrameIndex[5];
674       sprintf(chFrameIndex, "%04d", frameIndex);
675
676       std::string stringVR;       
677       if (currentFile->IsVRCoherent(0x0021) == 1 )
678          stringVR = "  ";
679       else
680         stringVR = "IS";
681   
682       currentFile->InsertEntryString(strChSliceIndex, 0x0021, 0x1020, stringVR);
683       currentFile->InsertEntryString(chFrameIndex,    0x0021, 0x1040, stringVR);
684       
685       if (verbose) {     
686          std::cout << "0x0021, 0x1020 : strChSliceIndex " << strChSliceIndex << std::endl;
687          std::cout << "0x0021, 0x1040 : chFrameIndex  "   << chFrameIndex    << std::endl; 
688          std::cout << "0x0020, 0x0012 : chSessionIndex "  << chSessionIndex  << std::endl; 
689       }
690         
691       std::string strImagePositionPatient    = currentFile->GetEntryString(0x0020, 0x0032 );
692       if (strImagePositionPatient == GDCM_NAME_SPACE::GDCM_UNFOUND)
693       {
694          if (verbose)
695             std::cout << "Duplicate ImagePosition into ImagePositionPatient" << std::endl;
696          currentFile->InsertEntryString(currentFile->GetEntryString(0x0020, 0x0030), 0x0020, 0x0032, "DS" );
697       }  
698       
699       std::string strImageOrientationPatient = f->GetEntryString(0x0020, 0x0037 );
700       if (strImageOrientationPatient == GDCM_NAME_SPACE::GDCM_UNFOUND)
701       {
702          if (verbose)
703             std::cout << "Duplicate ImageOrientation into ImageOrientationPatient" << std::endl;          
704          currentFile->InsertEntryString(currentFile->GetEntryString(0x0020, 0x0035), 0x0020, 0x0037, "DS" );       
705       }
706        
707       if (taggrid  || strcmp(input, "IDO")==0 || strcmp(input, "ido")==0 )
708          frameIndex++;
709       else     
710       {     
711          if (flag == 0)
712          {       
713             flag = 1;
714          }
715          else
716          {
717             frameIndex++;
718             flag = 0;
719          }
720       } 
721                  
722       if (split)
723       
724          //fullWriteFilename = currentPhaseEncodingDirectionWriteDir + GDCM_NAME_SPACE::GDCM_FILESEPARATOR 
725          //                                + lastFilename + strExtent;      
726          fullWriteFilename = currentPositionWriteDir + GDCM_NAME_SPACE::GDCM_FILESEPARATOR 
727                                          + lastFilename + strExtent; 
728       else
729          fullWriteFilename = currentPatientWriteDir + GDCM_NAME_SPACE::GDCM_FILESEPARATOR 
730                                          + lastFilename + strExtent; 
731             
732       // Load the pixels in RAM.    
733       
734       fh = GDCM_NAME_SPACE::FileHelper::New(currentFile);     
735       uint8_t *imageData = fh->GetImageDataRaw(); // Don't convert (Gray Pixels + LUT) into (RGB pixels) ?!?
736       fh->SetWriteTypeToDcmExplVR();     
737       
738       if (rubout) {
739          // Put to Black the burnt-in number.
740          nX = currentFile->GetXSize();
741          nY = currentFile->GetYSize();
742          for(int y=nY-15; y<nY; y++)
743             for(int x=nX/3; x<nX/2+50; x++)
744               imageData[ y*nX*2 + x ] = 0;
745       }
746       
747       // We didn't make any computation on the pixels -> keep unchanged the following :
748       // 'Media Storage SOP Class UID' (0x0002,0x0002)
749       // 'SOP Class UID'               (0x0008,0x0016)
750       // 'Image Type'                  (0x0008,0x0008)
751       // 'Conversion Type'             (0x0008,0x0064)        
752       fh->SetContentType(GDCM_NAME_SPACE::UNMODIFIED_PIXELS_IMAGE);
753       
754       if (!fh->Write(fullWriteFilename))
755       {
756          std::cout << "Fail to write :[" << fullWriteFilename << "]"
757                    << std::endl;
758       } 
759       fh->Delete();                
760    }
761    return 0;
762  }
763