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