]> Creatis software - gdcm.git/blob - Example/BrukerToMhd.cxx
comments
[gdcm.git] / Example / BrukerToMhd.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: BrukerToMhd.cxx,v $
5   Language:  C++
6   Date:      $Date: 2010/09/01 14:40:00 $
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 /**
20  * Writes an old style Bruker Dicom file, InTag compliant, from a Raw File
21  * User has to supply parameters. 
22  * 
23  */
24 #include "gdcmFile.h"
25 #include "gdcmFileHelper.h"
26 #include "gdcmDebug.h"
27 #include "gdcmUtil.h"
28 #include "gdcmDirList.h"
29
30 #include "gdcmArgMgr.h"
31
32 #include <iostream>
33 #include <sstream>
34
35 void DealWithNiveau1(std::string level1Directory);
36 void DealWithNiveau2(std::string level2Directory);
37 void DealWithNiveau3(std::string level3Directory);
38 /**
39   * \brief   
40   *          - explores  the given root directory e.g. :
41   *            B67d1.Bp1
42   *              subject
43   *              AdjStatePerStudy
44   *              1
45   *                 acqp
46   *                 fid
47   *                 imnd
48   *                 pulseprogram
49   *                 spnam0
50   *                 spnam1
51   *                 pdata
52   *                    1
53   *                       2dseq
54   *                       d3proc
55   *                       isa
56   *                       meta
57   *                       procs
58   *                       roi
59   *                    2
60   *                       ...                   
61   * 
62   *              2
63   *                 acqp
64   *                 fid
65   *                 ...
66   *                 pdata
67   *              3         
68   *                ...
69   *          - fills a single level Directory with *all* the files,
70   *            converted into a Brucker-like Dicom, Intags compliant
71   */  
72   
73
74
75
76 int main(int argc, char *argv[])
77 {
78    START_USAGE(usage)
79    " \n BrukerToMhd : \n                                                      ",
80    " - explores the given directory, at the 3 levels,                         ",
81    " - fills an equivalent Directory with the MHD files,                      ",
82    "           converted into a Brucker-like Dicom, InTags compliant          ",
83    " usage: BrukerToMhd dirin=rootDirectoryName                               ",
84    "                   dirout=outputDirectoryName                             ",
85    "                   [{b|l}] b:BigEndian,l:LittleEndian default : l         ",
86    "                   [debug] [verbose] [listonly]                           ",
87    "                                                                          ",
88    "  debug      : developper wants to run the program in 'debug mode'        ",
89    FINISH_USAGE
90    
91
92    // ------------ Initialize Arguments Manager ----------------  
93    GDCM_NAME_SPACE::ArgMgr *am= new GDCM_NAME_SPACE::ArgMgr(argc, argv);
94   
95    if (argc == 1 || am->ArgMgrDefined("usage") )
96    {
97       am->ArgMgrUsage(usage); // Display 'usage'
98       delete am;
99       return 1;
100    }
101
102    const char *dirNamein;   
103    dirNamein  = am->ArgMgrGetString("dirin",".");
104
105    const char *dirNameout;   
106    dirNameout  = am->ArgMgrGetString("dirout",".");
107    
108    int b = am->ArgMgrDefined("b");
109    int l = am->ArgMgrDefined("l");
110    
111    if (am->ArgMgrDefined("debug"))
112       GDCM_NAME_SPACE::Debug::DebugOn();
113
114    int verbose  = am->ArgMgrDefined("verbose");      
115    int listonly = am->ArgMgrDefined("listonly");
116    
117    /* if unused Param we give up */
118    if ( am->ArgMgrPrintUnusedLabels() )
119    {
120       am->ArgMgrUsage(usage);
121       delete am;
122       return 1;
123    } 
124
125    delete am;  // we don't need Argument Manager any longer
126
127    // ----------- End Arguments Manager ---------
128    
129
130    // ----- Begin Processing -----
131
132
133    bool bigEndian = GDCM_NAME_SPACE::Util::IsCurrentProcessorBigEndian();
134
135  
136    if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirNamein) )
137    {
138       std::cout << "KO : [" << dirNamein << "] is not a Directory." << std::endl;
139       return 0;
140
141    }
142    else
143    {
144       std::cout << "OK : [" << dirNamein << "] is a Directory." << std::endl;
145    }
146  
147    std::string systemCommand;
148    
149    std::cout << "Check for output directory :[" << dirNameout << "]."
150              <<std::endl;
151    if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirNameout) )    // dirout not found
152    {
153       std::string strDirNameout(dirNameout);          // to please gcc 4
154       systemCommand = "mkdir " +strDirNameout;        // create it!
155       if (verbose)
156          std::cout << systemCommand << std::endl;
157       system (systemCommand.c_str());
158       if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirNameout) ) // be sure it worked
159       {
160           std::cout << "KO : not a dir : [" << dirNameout << "] (creation failure ?)" << std::endl;
161       return 0;
162
163       }
164       else
165       {
166         std::cout << "Directory [" << dirNameout << "] created." << std::endl;
167       }
168    }
169    else
170    {
171        std::cout << "Output Directory [" << dirNameout << "] already exists; Used as is." << std::endl;
172    }
173
174    std::string strDirNamein(dirNamein);
175    GDCM_NAME_SPACE::DirList dirList(strDirNamein, false, true); // DON'T get recursively the list of files
176    std::string strDirNameout(dirNameout);   
177    
178    if (listonly)
179    {
180       std::cout << "------------List of found files ------------" << std::endl;
181       dirList.Print();
182       std::cout << std::endl;
183       return 1;
184    }
185
186
187    GDCM_NAME_SPACE::DirListType fileNames;
188    fileNames = dirList.GetFilenames();
189
190   // GDCM_NAME_SPACE::File *f;
191   // GDCM_NAME_SPACE::FileHelper *fh;
192
193    std::string outputFileName;
194
195    // -----------------------------------------------------
196    // Iterate to ALL the objets(files/directories) found in the input directory
197    // -----------------------------------------------------
198    GDCM_NAME_SPACE::DirListType::iterator it;
199    
200    for (it = fileNames.begin();
201         it != fileNames.end();
202       ++it)
203    {
204       if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(*it) )
205       { 
206          std::cout << "[" << *it << "] is a file" << std::endl;
207       }
208       
209    }
210    
211     for (it = fileNames.begin();
212          it != fileNames.end();
213        ++it)
214    {
215       if ( GDCM_NAME_SPACE::DirList::IsDirectory(*it) )
216       { 
217          std::cout << "[" << *it << "] is a directory" << std::endl;
218          DealWithNiveau1(*it);
219       }
220    }
221    
222    /*
223    
224  // Open the Raw file
225    std::ifstream *Fp = new std::ifstream((*it).c_str(), std::ios::in | std::ios::binary);
226    if ( ! *Fp )
227    {
228       std::cout << "Cannot open file: [" << *it << "]" << std::endl;
229       delete Fp;
230       Fp = 0;
231       return 0;
232    }
233    if (verbose)
234       std::cout << "Success to open file: [" << *it << "]" << std::endl;
235
236    // Read the pixels
237
238    int singlePlaneDataSize =  nX*nY*samplesPerPixel*pixelSizeOut;
239    int dataSizeIn          =  nX*nY*samplesPerPixel*pixelSize*nZ;
240
241    uint8_t *pixels         = new uint8_t[dataSizeIn];
242    uint8_t *planePixelsOut = new uint8_t[singlePlaneDataSize];
243
244    Fp->read((char*)pixels, (size_t)dataSizeIn);
245
246    if ( pixelSize !=1 && ( (l && bigEndian) || (b && ! bigEndian) ) )
247    {  
248       ConvertSwapZone(pixelSize, pixels, dataSizeIn);
249    }
250
251 if (verbose)
252    std::cout << "After ConvertSwapZone" << std::endl;
253
254 // Copy (and convert) pixels of a single plane
255
256      switch ( pixelTypeCode )
257      {
258        case 8    : CFR(PU8);  break;
259        case -8   : CFR(PS8);  break;
260        case -16  : CFR(PU16); break;
261        case 16   : CFR(PS16); break;
262        case -32  : CFR(PS32); break;
263        case 32   : CFR(PU32); break;
264        case 33   : CFR(PF32); break;
265        case 64   : CFR(PD64); break;
266      }
267
268 if (verbose)
269    std::cout << "After CFR" << std::endl;
270    
271 // Create an empty FileHelper
272
273    GDCM_NAME_SPACE::FileHelper *fileH = GDCM_NAME_SPACE::FileHelper::New();
274  
275  // Get the (empty) image header.
276    GDCM_NAME_SPACE::File *fileToBuild = fileH->GetFile();
277
278    // 'Study Instance UID'
279    // The user is allowed to create his own Study, 
280    //          keeping the same 'Study Instance UID' for various images
281    // The user may add images to a 'Manufacturer Study',
282    //          adding new Series to an already existing Study
283
284    fileToBuild->InsertEntryString(strStudyUID,0x0020,0x000d,"UI");  //  Study UID   
285
286    // 'Serie Instance UID'
287    // The user is allowed to create his own Series, 
288    // keeping the same 'Serie Instance UID' for various images
289    // The user shouldn't add any image to a 'Manufacturer Serie'
290    // but there is no way no to prevent him for doing that
291    
292    fileToBuild->InsertEntryString(strSerieUID,0x0020,0x000e,"UI");  //  Serie UID
293    
294    std::ostringstream str;
295
296    // Set the image size
297    str.str("");
298    str << nX;
299    fileToBuild->InsertEntryString(str.str(),0x0028,0x0011, "US"); // Columns
300    str.str("");
301    str << nY;
302    fileToBuild->InsertEntryString(str.str(),0x0028,0x0010, "US"); // Rows
303    
304        if (verbose)
305          std::cout << "before  debut des choses serieuses2"<< std::endl;      
306   
307 //   str.str("");
308 //   str << nZ;
309 //   fileToBuild->InsertEntryString(str.str(),0x0028,0x0008, "IS"); // Number of Frames
310
311    // Set the pixel type
312    
313    str.str("");
314    str << pixelSizeOut*8;
315    fileToBuild->InsertEntryString(str.str(),0x0028,0x0100, "US"); // Bits Allocated
316
317    str.str("");
318    str << pixelSizeOut*8;
319    fileToBuild->InsertEntryString(str.str(),0x0028,0x0101, "US"); // Bits Stored
320
321    str.str("");
322    str << ( pixelSizeOut*8 - 1 );
323    fileToBuild->InsertEntryString(str.str(),0x0028,0x0102, "US"); // High Bit
324
325    str.str("");
326    str << pixelSign;
327    fileToBuild->InsertEntryString(str.str(),0x0028,0x0103, "US"); // Pixel Representation
328
329 // If you deal with a Serie of images, as slices of a volume,
330 // it's up to you to tell gdcm, for each image, what are the values of :
331 // 
332 // 0020 0032 DS 3 Image Position (Patient)
333 // 0020 0037 DS 6 Image Orientation (Patient)
334
335    str.str("");
336    str << "0.0\\0.0\\0.0";
337
338 // take Frame Index as position (we don't know anything else) NO!
339
340    fileToBuild->InsertEntryString(str.str(),0x0020,0x0032, "DS");
341
342    fileToBuild->InsertEntryString("1.0\\0.0\\0.0\\0.0\\1.0\\0.0",0x0020,0x0037, "DS"); //[1\0\0\0\1\0] : Axial
343    
344    
345    
346    
347    str.str("");
348    str << samplesPerPixel;
349    fileToBuild->InsertEntryString(str.str(),0x0028,0x0002, "US"); // Samples per Pixel
350
351    if (strlen(patientName) != 0)
352       fileToBuild->InsertEntryString(patientName,0x0010,0x0010, "PN"); // Patient's Name
353     
354    //  0=white  
355    if(monochrome1)
356       fileH->SetPhotometricInterpretationToMonochrome1();
357
358 // Special InTag, now.
359
360       fileH->InsertEntryString(chSessionIndex, 0x0020, 0x0012, "IS");
361
362       // Deal with  0x0021, 0x1020 : 'SLICE INDEX'
363       // will stay to 0, since the stuff deals with single slice directories
364       char chSliceIndex[5];
365       sprintf(chSliceIndex, "%04d", sliceIndex);
366       std::string strChSliceIndex(chSliceIndex);
367
368       // Deal with  0x0021, 0x1040 : 'FRAME INDEX'
369
370       str.str("");
371       str << frameIndex;
372       frameIndex++;  // be ready for next one 
373
374       fileH->InsertEntryString(strChSliceIndex, 0x0021, 0x1020, "IS");
375       fileH->InsertEntryString(str.str(),    0x0021, 0x1040, "IS");
376
377       // Pixel Size
378       /// \TODO Ask user to supply 'Pixel Size' value
379       float pxSzX = 1.0;
380       float pxSzY = 1.0;
381
382       // Field of view
383       char fov[64];
384       sprintf(fov, "%f\\%f",nX*pxSzX, nY*pxSzY);
385       fileH->InsertEntryString(fov, 0x0019, 0x1000, "DS");
386
387
388 // Set the image Pixel Data
389    fileH->SetImageData(planePixelsOut,singlePlaneDataSize);
390
391 // Set the writting mode and write the image
392    fileH->SetWriteModeToRaw();
393    
394    
395
396  // Write a DICOM Explicit VR file
397    fileH->SetWriteTypeToDcmExplVR();
398
399
400    outputFileName = strDirNameout +  GDCM_NAME_SPACE::GDCM_FILESEPARATOR + *it + "_ForInTag.dcm";
401    if( !fileH->Write(outputFileName ) )
402    {
403       std::cout << "Failed for [" << outputFileName << "]\n"
404                 << "           File is unwrittable\n";
405    }
406
407 // End of :    for (GDCM_NAME_SPACE::DirListType::iterator it = fileNames.begin() ... 
408
409
410   
411    fileH->Delete();
412
413    delete[] pixels;
414    delete[] planePixelsOut;
415   }
416 */
417   // return 1;
418  } // end of : for (GDCM_NAME_SPACE::DirListType::iterator it
419
420
421
422 void DealWithNiveau1(std::string level1Directory){
423
424    GDCM_NAME_SPACE::DirList dirList(level1Directory, false, true); // DON'T get recursively the list of files
425
426    GDCM_NAME_SPACE::DirListType fileNames;
427    fileNames = dirList.GetFilenames();
428    // -----------------------------------------------------
429    // Iterate to ALL the objets(files/directories) found in the input directory
430    // -----------------------------------------------------
431    GDCM_NAME_SPACE::DirListType::iterator it;
432    
433    for (it = fileNames.begin();
434         it != fileNames.end();
435       ++it)
436    {
437       if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(*it) )
438       { 
439          std::cout << "--- [" << *it << "] is a file" << std::endl;
440       }
441       
442    }
443    
444     for (it = fileNames.begin();
445          it != fileNames.end();
446        ++it)
447    {
448       if ( GDCM_NAME_SPACE::DirList::IsDirectory(*it) )
449       { 
450          std::cout << "--- [" << *it << "] is a directory" << std::endl;
451          DealWithNiveau2(*it);
452       }
453    }
454 }
455
456
457 void DealWithNiveau2(std::string level2Directory){
458
459    GDCM_NAME_SPACE::DirList dirList(level2Directory, false, true); // DON'T get recursively the list of files
460
461    GDCM_NAME_SPACE::DirListType fileNames;
462    fileNames = dirList.GetFilenames();
463
464    // -----------------------------------------------------
465    // Iterate to ALL the objets(files/directories) found in the input directory
466    // -----------------------------------------------------
467    GDCM_NAME_SPACE::DirListType::iterator it;
468    
469    for (it = fileNames.begin();
470         it != fileNames.end();
471       ++it)
472    {
473       if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(*it) )
474       { 
475          std::cout << "--- --- [" << *it << "] is a file" << std::endl;
476       }
477       
478    }
479    
480    for (it = fileNames.begin();
481          it != fileNames.end();
482        ++it)
483    {
484       if ( GDCM_NAME_SPACE::DirList::IsDirectory(*it) )
485       { 
486          std::cout << "--- --- [" << *it << "] is a directory" << std::endl;
487          DealWithNiveau3(*it);
488       }
489     }
490 }
491
492
493 void DealWithNiveau3(std::string level3Directory){
494
495    GDCM_NAME_SPACE::DirList dirList(level3Directory, false, true); // DON'T get recursively the list of files
496
497    GDCM_NAME_SPACE::DirListType fileNames;
498    fileNames = dirList.GetFilenames();
499
500    // -----------------------------------------------------
501    // Iterate fo ALL the directories found in the input directory
502    // -----------------------------------------------------
503
504    for (GDCM_NAME_SPACE::DirListType::iterator it = fileNames.begin();
505                                     it != fileNames.end();
506                                   ++it)
507    {
508
509       if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(*it) )
510       {
511          std::cout << "--- --- --- [" << *it << "] is a file" << std::endl;
512       }
513       else
514       {
515          std::cout << "--- --- --- [" << *it << "] is a directory" << std::endl;
516       
517       }
518     }
519 }