]> Creatis software - gdcm.git/blob - Example/PcpdenseToDicom.cxx
Some enhancements
[gdcm.git] / Example / PcpdenseToDicom.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: PcpdenseToDicom.cxx,v $
5   Language:  C++
6   Date:      $Date: 2011/08/25 14:36:02 $
7   Version:   $Revision: 1.8 $
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-like 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, 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      for (int i=0; i<numberOfSlices; i++)
162      {  
163         Ecc.str(rootfilename); 
164         Ecc << Ecc.str() << "_s" << i << "_Ecc.txt";
165       
166         std::ifstream fromEcc( Ecc.str().c_str() );             
167         if ( !fromEcc )
168         {
169            std::cout << "Can't open file [" << Ecc.str() << "]" << std::endl;
170            exit(0);
171         }
172         std::cout << "Open file [" << Ecc.str() << "] : OK" << std::endl;
173         dcmImageName = Ecc.str() + ".dcm";
174
175         if (X2)
176         {
177            LoadImageX2(fromEcc, image);
178            MakeDicomImage(image, NX*2, NY*2, dcmImageName, patientName, 1, strStudyUID, strSerieUID, serieDescr, i, multiframe );
179         }
180         else
181         {
182            LoadImage(fromEcc, image);
183            MakeDicomImage(image, NX, NY,     dcmImageName, patientName, 1, strStudyUID, strSerieUID, serieDescr, i, multiframe );
184         }         
185         fromEcc.close();
186
187      } // end : for (int i=0; i<numberOfSlices
188    }
189    
190    if (multiframe) {  
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*4*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      if (X2)     
214         MakeDicomImage(image, NX*2, NY*2, dcmImageName, patientName, numberOfSlices, strStudyUID, strSerieUID, serieDescr, 0, multiframe );
215      else
216         MakeDicomImage(image, NX, NY,     dcmImageName, patientName, numberOfSlices, strStudyUID, strSerieUID, serieDescr, 0, multiframe );   
217    }  // end : if (multiframe) 
218
219
220
221 // === perf ===
222
223    strSerieUID =  GDCM_NAME_SPACE::Util::CreateUniqueUID();
224
225    serieDescr = "perf";
226
227    if (!multiframe) {    
228      for (int i=0; i<numberOfSlices; i++)
229      {      
230         perf.str(rootfilename);
231         perf  << perf.str()    << "_s" << i << "_perf.txt";
232
233         std::ifstream fromperf( perf.str().c_str() );             
234         if ( !fromperf )
235         {
236            std::cout << "Can't open file [" << perf.str() << "]" << std::endl;
237            exit(0);
238         }
239         std::cout << "Open file [" << perf.str() << "] : OK" << std::endl;
240
241         if (X2)
242           LoadImageX2(fromperf ,image );
243         else
244           LoadImage(fromperf, image );
245       
246         fromperf.close();
247         
248         dcmImageName = perf.str() + ".dcm";
249
250         if (X2)
251            MakeDicomImage(image, NX*2, NY*2, dcmImageName, patientName, 1, strStudyUID, strSerieUID, serieDescr, i, multiframe );
252         else
253            MakeDicomImage(image, NX, NY,     dcmImageName, patientName, 1, strStudyUID, strSerieUID, serieDescr, i, multiframe ); 
254
255      } // end : for (int i=0; i<numberOfSlices
256    }
257
258
259    if (multiframe) {
260      for (int i=0; i<numberOfSlices; i++)
261      {      
262         perf.str(rootfilename);
263         perf  << perf.str()    << "_s" << i << "_perf.txt";
264
265         std::ifstream fromperf( perf.str().c_str() );             
266         if ( !fromperf )
267         {
268            std::cout << "Can't open file [" << perf.str() << "]" << std::endl;
269            exit(0);
270         }
271         std::cout << "Open file [" << perf.str() << "] : OK" << std::endl;
272
273       if (X2)
274          LoadImageX2(fromperf, &image[NX*NY*i*4]);
275       else
276          LoadImage(fromperf, &image[NX*NY*i] );
277        
278       fromperf.close();  
279    } // end : for (int i=0; i<numberOfSlices
280    
281      dcmImageName = deb + "_perf.dcm";
282      if (X2)     
283         MakeDicomImage(image, NX*2, NY*2, dcmImageName, patientName, numberOfSlices, strStudyUID, strSerieUID, serieDescr, 0, multiframe );
284      else
285         MakeDicomImage(image, NX, NY,     dcmImageName, patientName, numberOfSlices, strStudyUID, strSerieUID, serieDescr, 0, multiframe ); 
286  }
287  
288
289
290 // === WashoutTc ===
291
292
293    strSerieUID =  GDCM_NAME_SPACE::Util::CreateUniqueUID();
294
295    serieDescr = "WashoutTc";
296
297    if (!multiframe) {
298     
299    for (int i1=0; i1<numberOfSlices; i1++)
300    {     
301       WashoutTc.str(rootfilename);
302       WashoutTc <<  WashoutTc.str() << "_s" << i1 << "_WashoutTc.txt";
303  
304       std::ifstream fromWashoutTc( WashoutTc.str().c_str() );             
305       if ( !fromWashoutTc )
306       {
307          std::cout << "Can't open file [" << WashoutTc.str() << "]" << std::endl;
308          exit(0);
309       }
310
311       std::cout << "Open file [" << WashoutTc.str() << "] : OK" << std::endl;
312       if (X2)      
313          LoadImageX2(fromWashoutTc,image );
314        else
315          LoadImage(fromWashoutTc,image );
316       fromWashoutTc.close();
317        
318       dcmImageName = WashoutTc.str() + ".dcm";
319       if (X2)      
320          MakeDicomImage(image, NX*2, NY*2, dcmImageName, patientName, 1, strStudyUID, strSerieUID, serieDescr, i1, multiframe );      
321       else
322          MakeDicomImage(image, NX, NY,     dcmImageName, patientName, 1, strStudyUID, strSerieUID, serieDescr, i1, multiframe ); 
323     } // end : for (int i=0; i<numberOfSlices
324   }
325
326    if (multiframe) {    
327      for (int i=0; i<numberOfSlices; i++)
328      {     
329         WashoutTc.str(rootfilename);
330         WashoutTc <<  WashoutTc.str() << "_s" << i << "_WashoutTc.txt";
331
332         std::ifstream fromWashoutTc( WashoutTc.str().c_str() );             
333         if ( !fromWashoutTc )
334         {
335            std::cout << "Can't open file [" << WashoutTc.str() << "]" << std::endl;
336            exit(0);
337         }
338         std::cout << "Open file [" << WashoutTc.str() << "] : OK" << std::endl;
339
340         if (X2)      
341           LoadImageX2(fromWashoutTc,  &image[NX*NY*4*i]);
342         else
343           LoadImage(fromWashoutTc, &image[NX*NY*i] );
344         fromWashoutTc.close();  
345
346      } // end : for (int i=0; i<numberOfSlices
347           
348      dcmImageName = deb + "_WashoutTc.dcm";
349      if (X2)
350         MakeDicomImage(image, NX*2, NY*2, dcmImageName, patientName, numberOfSlices, strStudyUID, strSerieUID, serieDescr, 0, multiframe );     
351      else
352         MakeDicomImage(image, NX, NY,     dcmImageName, patientName, numberOfSlices, strStudyUID, strSerieUID, serieDescr, 0, multiframe );      
353    }
354  
355    delete []image;
356    return 1;            
357 }
358
359 // =====================================================================================================================
360
361 void LoadImage(std::ifstream &from,  unsigned short int *image)
362 {
363 // in any file ".txt" :
364
365 /*
366 XY Dimensions           47          50
367      0.000000     0.000000     0.000000     0.000000     0.000000     0.000000
368      ...
369 */  
370
371    if (!from)
372       return;
373    
374    std::string str1;
375
376    from >> str1;
377    from >> str1;
378     
379    int NX, NY;
380    from >> NX;
381    from >> NY;
382    std::cout << "NX, NY : " << NX << ", " << NY << std::endl; 
383
384    float pixelValue;
385      
386     int i, j;
387     for( i=0;i<NY;i++) {
388         for(j=0;j<NX;j++) {
389            from >> pixelValue;
390            image[i*NX+j] = (unsigned short int)(pixelValue * 1000.); // Why do we multiply by 1000? // JPR
391         }
392      }
393 }
394
395
396 // =====================================================================================================================
397
398 void LoadImageX2(std::ifstream &from,  unsigned short int *image )
399 {
400 // in any file ".txt" :
401
402 /*
403 XY Dimensions           47          50
404      0.000000     0.000000     0.000000     0.000000     0.000000     0.000000
405      ...
406 */  
407
408    if (!from)
409       return;
410
411    std::string str1;
412
413     from >> str1;
414     from >> str1;
415     
416     int NX, NY;
417     from >> NX;
418     from >> NY;
419     std::cout << "NX, NY : " << NX << ", " << NY << std::endl; 
420
421      int k;
422      for( k=0;k<NX*NY*4;k++)
423           image[k] = 0;
424
425     float pixelValue;
426      
427      int i, j;
428  /*
429      for( i=0;i<NY;i++) {
430            for(j=0;j<NX;j++) {
431               from >> pixelValue;
432               pixelValue*=1000.;  // Why do we multiply by 1000? // JPR
433               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);  
434            }
435      }
436  */
437  
438      int lgrLigneNvlleImage = NX+NX;
439      int debLigneNvlleImage = 0;
440      for( i=0;i<NY;i++) {
441            for(j=0;j<NX;j++) {
442               from >> pixelValue;
443               pixelValue*=1000.;  // Why do we multiply by 1000? // JPR
444               image[debLigneNvlleImage + j+j] = 
445               image[debLigneNvlleImage + j+j +1] = 
446               image[debLigneNvlleImage + lgrLigneNvlleImage +j+j] = 
447               image[debLigneNvlleImage + lgrLigneNvlleImage + j+j +1] = 
448                  (unsigned short int)(pixelValue);
449            }
450            debLigneNvlleImage += 2*lgrLigneNvlleImage;  
451      }
452 }
453 // =====================================================================================================================================
454
455
456 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)
457 {
458
459 std::cout << "in MakeDicomImage : dcmImageName = [" << dcmImageName << "]" << std::endl;
460  // GDCM_NAME_SPACE::Debug::DebugOn();
461   
462    std::ostringstream str;
463
464    GDCM_NAME_SPACE::File *file;
465    file = GDCM_NAME_SPACE::File::New();       
466       
467   // Set the image size
468    str.str(""); 
469    str << X;
470    file->InsertEntryString(str.str(),0x0028,0x0011,"US"); // Columns
471    str.str("");
472    str << Y;
473    file->InsertEntryString(str.str(),0x0028,0x0010,"US"); // Rows
474
475   // Set the pixel type
476   //      16; //8, 16, 32
477    file->InsertEntryString("16",0x0028,0x0100,"US"); // Bits Allocated
478    
479    str.str("");
480    str << 16; // may be 12 or 16 if componentSize =16
481    file->InsertEntryString("16",0x0028,0x0101,"US"); // Bits Stored
482    file->InsertEntryString("15",0x0028,0x0102,"US"); // High Bit
483
484   // Set the pixel representation // 0/1 , 0=unsigned
485    file->InsertEntryString("1",0x0028,0x0103, "US"); // Pixel Representation
486    
487   // Set the samples per pixel // 1:Grey level, 3:RGB
488    file->InsertEntryString("1",0x0028,0x0002, "US"); // Samples per Pixel
489
490
491    if (nbFrames != 1)
492    {
493       str.str("");
494       str << nbFrames;
495       file->InsertEntryString(str.str(),0x0028,0x0008,"IS"); // Number of Frames  
496    }
497   
498    if (strlen(patientName) != 0)
499       file->InsertEntryString(patientName,0x0010,0x0010, "PN"); // Patient's Name
500
501    file->InsertEntryString(studyUID, 0x0020, 0x000d, "UI");
502    file->InsertEntryString(serieUID, 0x0020, 0x000e, "UI");
503  
504    file->InsertEntryString(SerieDescr,0x0008,0x103e, "LO");  // Series Description 
505
506 // 0020 0037 DS 6 Image Orientation (Patient)   
507    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!)
508    
509 // 0020 0032 DS 3 Image Position (Patient)   
510    char charImagePosition[256];
511    sprintf(charImagePosition,"0.0\\0.0\\%f",(float)imgNum);
512    file->InsertEntryString(charImagePosition,0x0020,0x0032, "DS");  //0020 0032 DS 3 Image Position (Patient)        
513
514 // 0020 0x1041 DS 1 Slice Location 
515         sprintf(charImagePosition,"%f",float(imgNum));
516         file->InsertEntryString(charImagePosition,0x0020,0x1041, "DS");   
517 /*
518   // Set Rescale Intercept
519         str.str("");
520         str << div;  
521         file->InsertEntryString(str.str(),0x0028,0x1052,"DS");
522
523   // Set Rescale Slope
524         str.str("");
525         str << mini;  
526         file->InsertEntryString(str.str(),0x0028,0x1053,"DS");
527 */
528
529    GDCM_NAME_SPACE::FileHelper *fileH;
530    fileH = GDCM_NAME_SPACE::FileHelper::New(file);
531    // cast is just to avoid warnings (*no* conversion is performed)
532    //fileH->SetImageData((uint8_t *)img,int(maxX*maxY)*sizeof(uint16_t)); // troubles when maxX, mayY are *actually* float!
533    
534    fileH->SetImageData((uint8_t *)tabVal,X*Y*nbFrames*sizeof(uint16_t));
535    fileH->SetWriteModeToRaw(); 
536    fileH->SetWriteTypeToDcmExplVR();
537         
538    if( !fileH->Write(dcmImageName))
539       std::cout << "Failed for [" << dcmImageName << "]\n"
540                 << "           File is unwrittable" << std::endl;
541
542   // file->Print();
543            
544   // delete img;
545    file->Delete();
546    fileH->Delete();  
547 }
548
549
550
551 // =====================================================================================================================
552