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