]> Creatis software - gdcm.git/blob - Example/ToMRIregister.cxx
" - Converts the Siemens Sonata MRI '*tfl2d1' DICOM files ",
[gdcm.git] / Example / ToMRIregister.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: ToMRIregister.cxx,v $
5   Language:  C++
6   Date:      $Date: 2006/07/26 17:15:27 $
7   Version:   $Revision: 1.1 $
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
19 #include "gdcmSerieHelper.h"
20 #include "gdcmFile.h"
21 #include "gdcmFileHelper.h"
22 #include "gdcmDebug.h"
23 #include "gdcmDirList.h"
24 #include "gdcmUtil.h"
25 #include "gdcmArgMgr.h"
26 #include <iostream>
27 #include <sstream>
28
29 bool AquisitionTime_0008_0032_Compare(gdcm::File *file1, gdcm::File *file2);
30
31 bool AquisitionTime_0008_0032_Compare(gdcm::File *file1, gdcm::File *file2)
32 {
33    return file1->GetEntryString(0x0008,0x0032) < file2->GetEntryString(0x0008,0x0032);
34 }
35
36 int main(int argc, char *argv[])
37 {  
38
39    START_USAGE(usage)
40    "\n ToMriregister :\n                                                      ",
41    " - Converts the Siemens Sonata MRI '*tfl2d1'                              ",
42    " to be processable by MriRegister software                                ",
43    " - May be used as a template for gdcm::SerieHelper use.                   ",
44    "                                                                          ",
45    "usage: ToMriRegister dirin=inputDirectoryName                             ",
46    "                     dirout=outputDirectoryName                           ",
47    "                     [ { [noshadowseq] | [noshadow][noseq] } ] [debug]    ",
48    "                                                                          ",
49    "       inputDirectoryName : user wants to analyze *all* the files         ",
50    "                            within the directory                          ",
51    "       noshadowseq: user doesn't want to load Private Sequences           ",
52    "       noshadow   : user doesn't want to load Private groups (odd number) ",
53    "       noseq      : user doesn't want to load Sequences                   ",
54    "       verbose    : user wants to run the program in 'verbose mode'       ",
55    "       debug      : developer wants to run the program in 'debug mode'    ",
56    FINISH_USAGE
57    
58    // ----- Initialize Arguments Manager ------
59   
60    gdcm::ArgMgr *am = new gdcm::ArgMgr(argc, argv);
61   
62    if (am->ArgMgrDefined("usage") || argc == 1) 
63    {
64       am->ArgMgrUsage(usage); // Display 'usage'
65       delete am;
66       return 0;
67    }
68
69    if (am->ArgMgrDefined("debug"))
70       gdcm::Debug::DebugOn();
71
72    int verbose  = am->ArgMgrDefined("verbose");
73          
74    int loadMode = gdcm::LD_ALL;
75    if ( am->ArgMgrDefined("noshadowseq") )
76       loadMode |= gdcm::LD_NOSHADOWSEQ;
77    else 
78    {
79       if ( am->ArgMgrDefined("noshadow") )
80          loadMode |= gdcm::LD_NOSHADOW;
81       if ( am->ArgMgrDefined("noseq") )
82          loadMode |= gdcm::LD_NOSEQ;
83    }
84
85    const char *dirIn  = am->ArgMgrGetString("dirin");
86    if (dirIn == 0)
87    {
88        std::cout <<std::endl
89                  << "'dirin=' must be present;" 
90                  <<  std::endl;
91        am->ArgMgrUsage(usage); // Display 'usage'  
92        delete am;
93        return 0;
94    }
95
96    const char *dirOut  = am->ArgMgrGetString("dirout");
97    if (dirOut == 0)
98    {
99        std::cout <<std::endl
100                  << "'dirout=' must be present;" 
101                  <<  std::endl;
102        am->ArgMgrUsage(usage); // Display 'usage'  
103        delete am;
104        return 0;
105    }     
106        
107    /* if unused Param we give up */
108    if ( am->ArgMgrPrintUnusedLabels() )
109    {
110       am->ArgMgrUsage(usage);
111       delete am;
112       return 0;
113    } 
114  
115    delete am;  // ------ we don't need Arguments Manager any longer ------
116    
117    // ======================== more checking on the params ==============
118
119    if ( ! gdcm::DirList::IsDirectory(dirIn) )
120    {
121       std::cout << "KO : [" << dirIn << "] is not a Directory." << std::endl;
122       return 0;
123
124    }
125    else
126    {
127       if (verbose)     
128          std::cout << "OK : [" << dirIn << "] is a Directory." << std::endl;
129    }
130    
131    std::string systemCommand;
132    std::string strDirNameout(dirOut);          // to please gcc 4 
133    if (verbose)
134       std::cout << "Check for output directory :[" << dirOut << "]."
135              <<std::endl;
136    if ( ! gdcm::DirList::IsDirectory(dirOut) )    // dirout not found
137    {
138       systemCommand = "mkdir " + strDirNameout;        // create it!
139       if (verbose)
140          std::cout << systemCommand << std::endl;
141       system (systemCommand.c_str());
142       if ( ! gdcm::DirList::IsDirectory(dirOut) ) // be sure it worked
143       {
144           std::cout << "KO : not a dir : [" << dirOut 
145                     << "] (creation failure ?)" << std::endl;
146       return 0;
147
148       }
149       else
150       {
151         if (verbose)
152            std::cout << "Directory [" << dirOut << "] created." << std::endl;
153       }
154    }
155    else
156    {
157       if (verbose)
158          std::cout << "Output Directory [" << dirOut 
159                    << "] already exists; Used as is." << std::endl;
160    } 
161    
162    // ========================== Now, we can do the job! ================     
163                  
164    // Just to see *all* the file names:
165    
166    gdcm::DirList dirList(dirIn,true); // gets (recursively) the file list
167    gdcm::DirListType fileList = dirList.GetFilenames();
168    for( gdcm::DirListType::iterator it  = fileList.begin();
169                                  it != fileList.end();
170                                  ++it )
171    {
172       std::cout << "file [" << it->c_str() << "]" << std::endl;  
173    }
174    
175    gdcm::SerieHelper *s;
176   
177    s = gdcm::SerieHelper::New();
178    s->SetLoadMode(gdcm::LD_NOSEQ);     // Don't load Sequences
179  
180    // we could choose to ignore some Files  
181    //gdcm::TagKey t(0x0010,0x0024);  // [Sequence Name]
182    // Keep only files where restriction is true
183    //s->AddRestriction(t, "*tfl2d1 ", gdcm::GDCM_EQUAL); 
184                                                     
185    s->SetDirectory(dirIn, true); // true : recursive exploration
186
187 /*
188    std::cout << " ---------------------------------------- "
189              << "'Single UID' Filesets found in :["
190              << dirName << "]" << std::endl;
191
192    s->Print();
193    std::cout << " ------------------------------------- Result after splitting"
194              << std::endl;
195 */
196    int nbFiles;
197    std::string fullFilename, lastFilename;
198    char fullWriteFilename[1024]; // should be enough.
199
200    std::ostringstream str;
201   
202    gdcm::XCoherentFileSetmap xcm;
203    gdcm::FileHelper *fh;
204    
205    // will be used for ordering.
206    s->SetUserLessThanFunction(AquisitionTime_0008_0032_Compare);
207    int serieNumber = 0;
208    int sliceNumber = 0;
209    int imageNumber = 0;
210          
211    // For all the Single SerieUID Files Sets of the gdcm::Serie
212    gdcm::FileList *l = s->GetFirstSingleSerieUIDFileSet();
213    while (l)
214    {   
215       nbFiles = l->size() ;
216       if ( l->size() < 8 ) // Hope we skip Scout views !
217       {
218          std::cout << "Ignore the 'Single SerieUID' FileSet :[" 
219                    << s->GetCurrentSerieUIDFileSetUID()
220                    << "]  " << nbFiles << " long" << std::endl;
221          std::cout << "-----------------------------------" << std::endl;      
222       }
223       else
224       {
225          std::cout << "Split the 'Single SerieUID' FileSet :[" 
226                    << s->GetCurrentSerieUIDFileSetUID()
227                    << "]  " << nbFiles << " long" << std::endl;
228          std::cout << "-----------------------------------" << std::endl;
229
230          xcm = s->SplitOnPosition(l);
231     
232          //int sliceNumber = 0;
233
234          for (gdcm::XCoherentFileSetmap::iterator i = xcm.begin();
235                                                   i != xcm.end();
236                                                 ++i)
237          {
238              std::cout << "Position : ";    
239              std::cout << "[" << (*i).first << "]" << std::endl;
240    
241             s->OrderFileList((*i).second);  // sort the current XCoherent Fileset
242
243             //int imageNumber = 0;    
244             for ( gdcm::FileList::iterator it =  ((*i).second)->begin();
245                                            it != ((*i).second)->end();
246                                          ++it)
247             {
248     
249             // Set the DataElements MriRegister needs to be happy
250             // Probabely one of the following (check it !):
251             /*
252                0020 0011 IS 1 Series Number
253                0020 0012 IS 1 Acquisition Number
254                0020 0013 IS 1 Instance Number
255            */
256    
257             str.str("");
258             str << serieNumber;
259             (*it)->InsertEntryString(str.str(),0x0020,0x0011, "IS"); // Series Number
260
261             str.str("");
262             str << imageNumber;
263             (*it)->InsertEntryString(str.str(),0x0020,0x0013, "IS"); // Instance Number
264    
265             // Load the pixels in RAM.    
266       
267                fh = gdcm::FileHelper::New(*it);     
268                uint8_t *imageData = fh->GetImageDataRaw(); // Don't convert (Gray Pixels + LUT) into (RGB pixels) ?!?
269                if (!imageData)
270                   std::cout << "fail to read [" << (*it)->GetFileName() << std::endl;
271                fh->SetWriteTypeToDcmExplVR();   
272                fh->SetContentType(gdcm::UNMODIFIED_PIXELS_IMAGE);
273     
274                // forge the file name
275       
276                fullFilename = (*it)->GetFileName();
277                lastFilename =  gdcm::Util::GetName( fullFilename );
278                //fullWriteFilename = strDirNameout + gdcm::GDCM_FILESEPARATOR 
279                //                                  + lastFilename;
280                sprintf(fullWriteFilename, "%s%c%04d-%04d-%04d.dcm", 
281                                       dirOut, gdcm::GDCM_FILESEPARATOR,
282                                       serieNumber, sliceNumber, imageNumber);
283                if (verbose)
284                   std::cout << fullFilename << " -> " << fullWriteFilename << std::endl;
285
286                // Write it, now
287        
288                if (!fh->Write(fullWriteFilename))
289                {
290                   std::cout << "Fail to write :[" << fullWriteFilename << "]"
291                             << std::endl;
292                }
293      
294                ///\todo FIXME segfaults if uncommented ?!?       
295                // delete(imageData);    
296                (*it)->Delete();
297                fh->Delete();
298       
299                imageNumber++;  
300        
301             } 
302             std::cout << std::endl; 
303             sliceNumber++;  
304          }
305       } 
306       serieNumber++;       
307       l = s->GetNextSingleSerieUIDFileSet();
308    }   
309    s->Delete();
310    return 0;
311 }