]> Creatis software - gdcm.git/blob - Example/PcpdenseToDicom.cxx
Add some explanations
[gdcm.git] / Example / PcpdenseToDicom.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: PcpdenseToDicom.cxx,v $
5   Language:  C++
6   Date:      $Date: 2011/03/29 07:35:57 $
7   Version:   $Revision: 1.7 $
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 <fstream>
20 #include <iostream>
21 //#include <values.h>
22
23 #if defined(__BORLANDC__)
24 #include <ctype.h>
25 #endif
26
27 #include "gdcmFile.h"
28 #include "gdcmFileHelper.h"
29 #include "gdcmDebug.h"
30 #include "gdcmDirList.h"
31 #include "gdcmUtil.h"
32 #include "gdcmArgMgr.h"
33
34 /**
35   * \brief   
36   *  Converts the "pcpdense" ".txt" (2008 version)  files into 16 bits Dicom Files,
37   * Hope they don't change soon!
38   */  
39
40 void MakeDicomImage(unsigned short int *tabVal, int X, int Y, std::string dcmImageName, const char * patientName, int nbFrames,
41                     std::string studyUID, std::string serieUID, std::string SerieDescr, int imgNum, bool m );
42
43 void LoadImage(std::ifstream &from,  unsigned short int * );
44
45 void LoadImageX2(std::ifstream &from, unsigned short int * );      
46 bool verbose;
47
48 int main(int argc, char *argv[])
49 {
50    START_USAGE(usage)
51    " \n pcpdenseToDicom :\n                                                   ",
52    "        Converts the '.txt' files into 16 bits Dicom Files,               ",
53    " usage:                                                                   ",
54    " pcpdenseToDicom rootfilename=...                                         ",
55    "                 (e.g.. :   meas_MID380_DENSE_stacked_slices_aif_FID81637)",
56    "                 numberOfSlices =  (default : 3)                          ",
57    "                 X2 : multiply x 2 image size                             ",
58    "                 m :create multiframe files instead of image stacks       ", 
59    "                 [patientname = Patient's name]                           ",
60    "                 [verbose] [debug]                                        ",
61    "                                                                          ",
62    " verbose  : user wants to run the program in 'verbose mode'               ",
63    " debug    : *developer*  wants to run the program in 'debug mode'         ",
64    FINISH_USAGE
65
66    // ----- Initialize Arguments Manager ------
67       
68    GDCM_NAME_SPACE::ArgMgr *am = new GDCM_NAME_SPACE::ArgMgr(argc, argv);
69   
70    if (argc == 1 || am->ArgMgrDefined("usage")) 
71    {
72       am->ArgMgrUsage(usage); // Display 'usage'
73       delete am;
74       return 0;
75    }
76    // Seems that ArgMgrWantString doesn't work on MacOS   
77    if(!am->ArgMgrDefined("rootfilename"))
78    {
79       std::cout << "'rootfilename' is mandatory" << std::endl;
80       exit(0);   
81    }
82  
83    const char *rootfilename = am->ArgMgrWantString("rootfilename",usage);
84    int numberOfSlices       = am->ArgMgrGetInt("numberOfSlices",3);
85    const char *patientName  = am->ArgMgrGetString("patientname", "Patient^Name");
86          
87    if (am->ArgMgrDefined("debug"))
88       GDCM_NAME_SPACE::Debug::DebugOn();
89
90    verbose         = ( 0 != am->ArgMgrDefined("verbose") );    
91    bool X2         = ( 0 != am->ArgMgrDefined("X2") );
92    bool multiframe = ( 0 != am->ArgMgrDefined("m") );
93
94    // if unused Param we give up
95    if ( am->ArgMgrPrintUnusedLabels() )
96    { 
97       am->ArgMgrUsage(usage);
98       delete am;
99       return 0;
100    }
101    delete am;  // we don't need Argument Manager any longer
102
103    // ----- Begin Processing -----
104    
105    std::ostringstream Ecc;
106    std::ostringstream perf;
107    std::ostringstream WashoutTc;
108
109    std::string strSerieUID; 
110    std::string strStudyUID =  GDCM_NAME_SPACE::Util::CreateUniqueUID();
111    std::string dcmImageName, textFileName, patientname,/* studyUID, serieUID, */ serieDescr ;
112    std::string deb(rootfilename);
113    
114    unsigned short int *image;
115    
116    int NX, NY;
117      
118   // Get some info
119   // -------------
120
121      {
122         Ecc.str(rootfilename); 
123         Ecc   << Ecc.str() << "_s0" << "_Ecc.txt";
124
125         std::ifstream fromEcc( Ecc.str().c_str() );             
126         if ( !fromEcc )
127         {
128            std::cout << "Can't open file [" << Ecc.str() << "]" << std::endl;
129            exit(0);
130         }
131         std::string str1;
132
133          fromEcc >> str1;
134          fromEcc >> str1;
135
136          fromEcc >> NX;
137          fromEcc >> NY;
138          std::cout << "NX, NY : " << NX << ", " << NY << std::endl; 
139    }         
140
141    int mult;
142    if (X2)
143       mult=4;
144    else
145       mult=1;
146       
147    if (multiframe)
148       image = new unsigned short int[NX*NY*mult*numberOfSlices];
149    else
150       image = new unsigned short int[NX*NY*mult];        
151    
152    
153
154    // === Ecc ===
155    
156    strSerieUID =  GDCM_NAME_SPACE::Util::CreateUniqueUID();
157
158    serieDescr = "Ecc";
159
160    if (!multiframe) {
161              
162      for (int i=0; i<numberOfSlices; i++)
163      {  
164         Ecc.str(rootfilename); 
165         Ecc   << Ecc.str()    << "_s" << i << "_Ecc.txt";
166       
167         std::ifstream fromEcc( Ecc.str().c_str() );             
168         if ( !fromEcc )
169         {
170            std::cout << "Can't open file [" << Ecc.str() << "]" << std::endl;
171            exit(0);
172         }
173         std::cout << "Open file [" << Ecc.str() << "] : OK" << std::endl;
174
175         if (X2)
176            LoadImageX2(fromEcc, image);
177         else
178            LoadImage(fromEcc, image);      
179         fromEcc.close();
180
181         dcmImageName = Ecc.str() + ".dcm";
182
183         MakeDicomImage(image, NX, NY, dcmImageName, patientName, 1, strStudyUID, strSerieUID, serieDescr, i, multiframe ); 
184    } // end : for (int i=0; i<numberOfSlices
185    delete []image;
186 }
187
188       
189    if (multiframe) {
190      
191      for (int i=0; i<numberOfSlices; i++)
192      {  
193         Ecc.str(rootfilename);
194         Ecc   << Ecc.str()    << "_s" << i << "_Ecc.txt";
195       
196         std::ifstream fromEcc( Ecc.str().c_str() );             
197         if ( !fromEcc )
198         {
199            std::cout << "Can't open file [" << Ecc.str() << "]" << std::endl;
200            exit(0);
201         }
202
203         std::cout << "Open file [" << Ecc.str() << "] : OK" << std::endl;
204         if (X2)
205           LoadImageX2(fromEcc ,&image[NX*NY*i] );
206         else
207           LoadImage(fromEcc, &image[NX*NY*i] );
208         
209         fromEcc.close();
210      } // end : for (int i=0; i<numberOfSlices
211      
212      dcmImageName = deb + "_Ecc.dcm";
213      MakeDicomImage(image, NX, NY, dcmImageName, patientName, numberOfSlices, strStudyUID, strSerieUID, serieDescr, 0, multiframe ); 
214   
215    }  // end : if (multiframe) 
216
217
218
219 // === perf ===
220
221    strSerieUID =  GDCM_NAME_SPACE::Util::CreateUniqueUID();
222
223    serieDescr = "perf";
224    if (!multiframe) {    
225      for (int i=0; i<numberOfSlices; i++)
226      {      
227         perf.str(rootfilename);
228         perf  << perf.str()    << "_s" << i << "_perf.txt";
229
230         std::ifstream fromperf( perf.str().c_str() );             
231         if ( !fromperf )
232         {
233            std::cout << "Can't open file [" << perf.str() << "]" << std::endl;
234            exit(0);
235         }
236         std::cout << "Open file [" << perf.str() << "] : OK" << std::endl;
237
238         if (X2)
239           LoadImageX2(fromperf ,image );
240         else
241           LoadImage(fromperf, image );
242       
243         fromperf.close();
244         
245         dcmImageName = Ecc.str() + ".dcm";
246         MakeDicomImage(image, NX, NY, dcmImageName, patientName, 1, strStudyUID, strSerieUID, serieDescr, i, multiframe ); 
247
248      } // end : for (int i=0; i<numberOfSlices
249    }
250
251
252    if (multiframe) {
253      for (int i=0; i<numberOfSlices; i++)
254      {      
255         perf.str(rootfilename);
256         perf  << perf.str()    << "_s" << i << "_perf.txt";
257
258         std::ifstream fromperf( perf.str().c_str() );             
259         if ( !fromperf )
260         {
261            std::cout << "Can't open file [" << perf.str() << "]" << std::endl;
262            exit(0);
263         }
264         std::cout << "Open file [" << perf.str() << "] : OK" << std::endl;
265
266       if (X2)
267          LoadImageX2(fromperf, &image[NX*NY*i]);
268       else
269          LoadImage(fromperf, &image[NX*NY*i] );
270        
271       fromperf.close();  
272    } // end : for (int i=0; i<numberOfSlices
273    
274      dcmImageName = deb + "_perf.dcm";
275      MakeDicomImage(image, NX, NY, dcmImageName, patientName, numberOfSlices, strStudyUID, strSerieUID, serieDescr, numberOfSlices, multiframe ); 
276  }
277  
278
279
280 // === WashoutTc ===
281
282
283    strSerieUID =  GDCM_NAME_SPACE::Util::CreateUniqueUID();
284
285    serieDescr = "WashoutTc";
286    
287    if (multiframe) {    
288      for (int i=0; i<numberOfSlices; i++)
289      {     
290         WashoutTc.str(rootfilename);
291         WashoutTc <<  WashoutTc.str() << "_s" << i << "_WashoutTc.txt";
292
293         std::ifstream fromWashoutTc( WashoutTc.str().c_str() );             
294         if ( !fromWashoutTc )
295         {
296            std::cout << "Can't open file [" << WashoutTc.str() << "]" << std::endl;
297            exit(0);
298         }
299         std::cout << "Open file [" << WashoutTc.str() << "] : OK" << std::endl;
300
301         if (X2)      
302           LoadImageX2(fromWashoutTc,  &image[NX*NY*i]);
303         else
304           LoadImage(fromWashoutTc, &image[NX*NY*i] );
305         fromWashoutTc.close();  
306
307      } // end : for (int i=0; i<numberOfSlices
308           
309      dcmImageName = deb + "_WashoutTc.dcm";
310      MakeDicomImage(image, NX, NY, dcmImageName, patientName, numberOfSlices, strStudyUID, strSerieUID, serieDescr, numberOfSlices, multiframe );      
311  } 
312
313
314    if (!multiframe) {
315     
316    for (int i1=0; i1<numberOfSlices; i1++)
317    {     
318       WashoutTc.str(rootfilename);
319       WashoutTc <<  WashoutTc.str() << "_s" << i1 << "_WashoutTc.txt";
320  
321       std::ifstream fromWashoutTc( WashoutTc.str().c_str() );             
322       if ( !fromWashoutTc )
323       {
324          std::cout << "Can't open file [" << WashoutTc.str() << "]" << std::endl;
325          exit(0);
326       }
327
328       std::cout << "Open file [" << WashoutTc.str() << "] : OK" << std::endl;
329       if (X2)      
330          LoadImageX2(fromWashoutTc,image );
331        else
332          LoadImage(fromWashoutTc,image );
333       fromWashoutTc.close();
334        
335       dcmImageName = Ecc.str() + ".dcm";
336       MakeDicomImage(image, NX, NY, dcmImageName, patientName, 1, strStudyUID, strSerieUID, serieDescr, i1, multiframe ); 
337     } // end : for (int i=0; i<numberOfSlices
338
339   }
340
341    delete []image;
342    return 1;            
343 }
344
345 // =====================================================================================================================
346
347 void LoadImage(std::ifstream &from,  unsigned short int *image)
348 {
349 // in any file ".txt" :
350
351 /*
352 XY Dimensions           47          50
353      0.000000     0.000000     0.000000     0.000000     0.000000     0.000000
354      ...
355 */  
356
357    if (!from)
358       return;
359
360    std::string str1;
361
362     from >> str1;
363     from >> str1;
364     
365     int NX, NY;
366     from >> NX;
367     from >> NY;
368     std::cout << "NX, NY : " << NX << ", " << NY << std::endl; 
369
370     float pixelValue;
371      
372      int i, j;
373      for( i=0;i<NY;i++)
374         for(j=0;j<NX;j++) {
375            from >> pixelValue;
376            image[i*NX+j] = (unsigned short int)(pixelValue * 1000.); // Why do we multiply by 1000? // JPR
377         }
378 }
379
380
381 // =====================================================================================================================
382
383 void LoadImageX2(std::ifstream &from,  unsigned short int *image )
384 {
385 // in any file ".txt" :
386
387 /*
388 XY Dimensions           47          50
389      0.000000     0.000000     0.000000     0.000000     0.000000     0.000000
390      ...
391 */  
392
393    if (!from)
394       return;
395
396    std::string str1;
397
398     from >> str1;
399     from >> str1;
400     
401     int NX, NY;
402     from >> NX;
403     from >> NY;
404     std::cout << "NX, NY : " << NX << ", " << NY << std::endl; 
405
406     float pixelValue;
407      
408      int i, j;
409      for( i=0;i<NY;i++) {
410            for(j=0;j<NX;j++) {
411               from >> pixelValue;
412               pixelValue*=1000.;  // Why do we multiply by 1000? // JPR
413               image[i*4*NX + j*2] = image[i*4*NX + j*2+1] =  image[(i*4+2)*NX + j*2] =  image[(i*4+2)*NX + j*2+1] = (unsigned short int)(pixelValue);  
414    }
415         }
416
417 }
418 // =====================================================================================================================================
419
420
421 void MakeDicomImage(unsigned short int *tabVal, int X, int Y, std::string dcmImageName, const char * patientName, int nbFrames, std::string studyUID, std::string serieUID, std::string SerieDescr, int imgNum, bool m)
422 {
423
424  // GDCM_NAME_SPACE::Debug::DebugOn();
425   
426    std::ostringstream str;
427
428    GDCM_NAME_SPACE::File *file;
429    file = GDCM_NAME_SPACE::File::New();       
430       
431   // Set the image size
432    str.str(""); 
433    str << X;
434    file->InsertEntryString(str.str(),0x0028,0x0011,"US"); // Columns
435    str.str("");
436    str << Y;
437    file->InsertEntryString(str.str(),0x0028,0x0010,"US"); // Rows
438
439   // Set the pixel type
440   //      16; //8, 16, 32
441    file->InsertEntryString("16",0x0028,0x0100,"US"); // Bits Allocated
442    
443    str.str("");
444    str << 16; // may be 12 or 16 if componentSize =16
445    file->InsertEntryString("16",0x0028,0x0101,"US"); // Bits Stored
446    file->InsertEntryString("15",0x0028,0x0102,"US"); // High Bit
447
448   // Set the pixel representation // 0/1 , 0=unsigned
449    file->InsertEntryString("1",0x0028,0x0103, "US"); // Pixel Representation
450    
451   // Set the samples per pixel // 1:Grey level, 3:RGB
452    file->InsertEntryString("1",0x0028,0x0002, "US"); // Samples per Pixel
453
454
455    if (nbFrames != 1)
456    {
457       str.str("");
458       str << nbFrames;
459       file->InsertEntryString(str.str(),0x0028,0x0008,"IS"); // Number of Frames  
460    }
461   
462    if (strlen(patientName) != 0)
463       file->InsertEntryString(patientName,0x0010,0x0010, "PN"); // Patient's Name
464
465    file->InsertEntryString(studyUID, 0x0020, 0x000d, "UI");
466    file->InsertEntryString(serieUID, 0x0020, 0x000e, "UI");
467  
468    file->InsertEntryString(SerieDescr,0x0008,0x103e, "LO");  // Series Description 
469
470 // 0020 0037 DS 6 Image Orientation (Patient)   
471    file->InsertEntryString("1.0\\0.0\\0.0\\0.0\\1.0\\0.0",0x0020,0x0037, "DS"); //[1\0\0\0\1\0] : Axial   (Tant pis!)
472    
473 // 0020 0032 DS 3 Image Position (Patient)   
474    char charImagePosition[256];
475    sprintf(charImagePosition,"0.0\\0.0\\%f",(float)imgNum);
476    file->InsertEntryString(charImagePosition,0x0020,0x0032, "DS");  //0020 0032 DS 3 Image Position (Patient)        
477
478 // 0020 0x1041 DS 1 Slice Location 
479         sprintf(charImagePosition,"%f",float(imgNum));
480         file->InsertEntryString(charImagePosition,0x0020,0x1041, "DS");   
481 /*
482   // Set Rescale Intercept
483         str.str("");
484         str << div;  
485         file->InsertEntryString(str.str(),0x0028,0x1052,"DS");
486
487   // Set Rescale Slope
488         str.str("");
489         str << mini;  
490         file->InsertEntryString(str.str(),0x0028,0x1053,"DS");
491 */
492
493    GDCM_NAME_SPACE::FileHelper *fileH;
494    fileH = GDCM_NAME_SPACE::FileHelper::New(file);
495    // cast is just to avoid warnings (*no* conversion is performed)
496    //fileH->SetImageData((uint8_t *)img,int(maxX*maxY)*sizeof(uint16_t)); // troubles when maxX, mayY are *actually* float!
497    
498    fileH->SetImageData((uint8_t *)tabVal,X*Y*nbFrames*sizeof(uint16_t));
499    fileH->SetWriteModeToRaw(); 
500    fileH->SetWriteTypeToDcmExplVR();
501         
502    if( !fileH->Write(dcmImageName))
503       std::cout << "Failed for [" << dcmImageName << "]\n"
504                 << "           File is unwrittable" << std::endl;
505
506   // file->Print();
507            
508   // delete img;
509    file->Delete();
510    fileH->Delete();  
511 }
512
513
514
515 // =====================================================================================================================
516