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