1 /*=========================================================================
4 Module: $RCSfile: PcpdenseToDicom.cxx,v $
6 Date: $Date: 2011/09/12 23:27:41 $
7 Version: $Revision: 1.11 $
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.
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.
17 =========================================================================*/
23 #if defined(__BORLANDC__)
28 #include "gdcmFileHelper.h"
29 #include "gdcmDebug.h"
30 #include "gdcmDirList.h"
32 #include "gdcmArgMgr.h"
36 * Converts the "pcpdense" ".txt" (2008 version) files into 16 bits Dicom Files,
37 * Hope they don't change soon!
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 );
43 void LoadImage(std::ifstream &from, unsigned short int *, int multFact);
45 void LoadImageX2(std::ifstream &from, unsigned short int *, int multFact);
46 void RotateImage(unsigned short int *image, unsigned short int *image2, int NX, int NY);
47 void FlipImage (unsigned short int *image, unsigned short int *image2, int NX, int NY);
49 void WholeBazar (unsigned short int *image, int NX, int NY, int numberOfSlices, std::string strStudyUID, std::string serieDescr, const char* patientName, bool multiframe, bool X2, int multFact, const char *rootfilename);
52 int main(int argc, char *argv[])
55 " \n pcpdenseToDicom :\n ",
56 " Converts the '.txt' files into 16 bits Dicom-like Files, ",
58 " pcpdenseToDicom rootfilename=... ",
59 " (e.g.. : meas_MID380_DENSE_stacked_slices_aif_FID81637)",
60 " numberOfSlices = (default : 3) ",
61 " X2 : multiply x 2 image size ",
62 " multFact = (default : 1000) multiply pixel value by ... ",
63 " m :create multiframe files instead of image stacks ",
64 " [patientname = Patient's name] ",
65 " [verbose] [debug] ",
67 " verbose : user wants to run the program in 'verbose mode' ",
68 " debug : *developer* wants to run the program in 'debug mode' ",
71 // ----- Initialize Arguments Manager ------
73 GDCM_NAME_SPACE::ArgMgr *am = new GDCM_NAME_SPACE::ArgMgr(argc, argv);
75 if (argc == 1 || am->ArgMgrDefined("usage"))
77 am->ArgMgrUsage(usage); // Display 'usage'
81 // Seems that ArgMgrWantString doesn't work on MacOS
82 if(!am->ArgMgrDefined("rootfilename"))
84 std::cout << "'rootfilename' is mandatory" << std::endl;
88 const char *rootfilename = am->ArgMgrWantString("rootfilename",usage);
89 int numberOfSlices = am->ArgMgrGetInt("numberOfSlices",3);
90 int multFact = am->ArgMgrGetInt("multFact",1000);
91 const char *patientName = am->ArgMgrGetString("patientname", "Patient^Name");
93 if (am->ArgMgrDefined("debug"))
94 GDCM_NAME_SPACE::Debug::DebugOn();
96 verbose = ( 0 != am->ArgMgrDefined("verbose") );
97 bool X2 = ( 0 != am->ArgMgrDefined("X2") );
98 bool multiframe = ( 0 != am->ArgMgrDefined("m") );
100 // if unused Param we give up
101 if ( am->ArgMgrPrintUnusedLabels() )
103 am->ArgMgrUsage(usage);
107 delete am; // we don't need Argument Manager any longer
109 // ----- Begin Processing -----
111 std::ostringstream Ecc;
112 std::ostringstream perf;
113 std::ostringstream WashoutTc;
115 std::string strSerieUID;
116 std::string strStudyUID = GDCM_NAME_SPACE::Util::CreateUniqueUID();
117 std::string /*dcmImageName,*/ textFileName, patientname, serieDescr;
118 std::string deb(rootfilename);
120 unsigned short int *image;
121 // unsigned short int *image2;
129 Ecc.str(rootfilename);
130 Ecc << Ecc.str() << "_s0" << "_Ecc.txt";
132 std::ifstream fromEcc( Ecc.str().c_str() );
135 std::cout << "Can't open file [" << Ecc.str() << "]" << std::endl;
145 std::cout << "NX, NY : " << NX << ", " << NY << std::endl;
150 WholeBazar(image, NX, NY, numberOfSlices, strStudyUID, serieDescr, patientName, multiframe, X2, multFact, rootfilename);
153 WholeBazar(image, NX, NY, numberOfSlices, strStudyUID, serieDescr, patientName, multiframe, X2, multFact, rootfilename);
155 serieDescr = "WashoutTc";
156 WholeBazar(image, NX, NY, numberOfSlices, strStudyUID, serieDescr, patientName, multiframe, X2, multFact, rootfilename);
162 // =====================================================================================================================
164 void LoadImage(std::ifstream &from, unsigned short int *image, int multFact)
166 // in any file ".txt" :
170 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
185 std::cout << "NX, NY : " << NX << ", " << NY << std::endl;
193 image[i*NX+j] = (unsigned short int)(pixelValue * multFact); // Why do we multiply by 1000? // JPR
199 // =====================================================================================================================
201 void LoadImageX2(std::ifstream &from, unsigned short int *image, int multFact )
203 // in any file ".txt" :
207 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
222 std::cout << "NX, NY : " << NX << ", " << NY << std::endl;
225 for( k=0;k<NX*NY*4;k++)
235 pixelValue*=1000.; // Why do we multiply by 1000? // JPR
236 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);
241 int lgrLigneNvlleImage = NX+NX;
242 int debLigneNvlleImage = 0;
246 pixelValue*=multFact; // Why do we multiply by 1000? // JPR
247 image[debLigneNvlleImage + j+j] =
248 image[debLigneNvlleImage + j+j +1] =
249 image[debLigneNvlleImage + lgrLigneNvlleImage +j+j] =
250 image[debLigneNvlleImage + lgrLigneNvlleImage + j+j +1] =
251 (unsigned short int)(pixelValue);
253 debLigneNvlleImage += 2*lgrLigneNvlleImage;
256 // =====================================================================================================================================
257 void RotateImage(unsigned short int *image, unsigned short int *image2, int NX, int NY)
260 for( int i=0;i<NY;i++) {
261 for(int j=0;j<NX;j++) {
262 image2[NY*j + i] = image[k];
269 // =====================================================================================================================================
270 void FlipImage(unsigned short int *image, unsigned short int *image2, int NX, int NY)
272 unsigned short int temp;
273 for(int i=0;i<NY/2;i++) {
274 for(int j=0;j<NX;j++) {
275 temp = image[NX*i + j];
276 image2[NX*i + j] = image[NX*(NY-i-1) + j];
277 image2[NX*(NY-i-1) + j] = temp;
282 // =====================================================================================================================================
284 void WholeBazar(unsigned short int *image, int NX, int NY, int numberOfSlices, std::string strStudyUID, std::string serieDescr, const char *patientName, bool multiframe, bool X2, int multFact, const char *rootfilename)
286 unsigned short int *image2;
287 std::string strSerieUID = GDCM_NAME_SPACE::Util::CreateUniqueUID();
288 std::string deb(rootfilename);
289 std::ostringstream Ecc;
290 std::ostringstream trueSerieDescr;
291 std::string dcmImageName;
300 image = new unsigned short int[NX*NY*mult*numberOfSlices];
301 image2 = new unsigned short int[NX*NY*mult*numberOfSlices];
303 image = new unsigned short int[NX*NY*mult];
304 image2 = new unsigned short int[NX*NY*mult];
308 for (int i=0; i<numberOfSlices; i++)
310 Ecc.str(rootfilename);
311 //Ecc << Ecc.str() << "_s" << i << "_Ecc.txt";
312 Ecc << Ecc.str() << "_s" << i << "_" << serieDescr << ".txt";
314 trueSerieDescr.str("");
316 trueSerieDescr << serieDescr << "_" "s" << i;
317 //std::cout << "-------------------------------------------------------" << trueSerieDescr.str() << std::endl;
319 std::ifstream fromEcc( Ecc.str().c_str() );
322 std::cout << "Can't open file [" << Ecc.str() << "]" << std::endl;
325 std::cout << "Open file [" << Ecc.str() << "] : OK" << std::endl;
326 dcmImageName = Ecc.str() + ".dcm";
330 LoadImageX2(fromEcc, image, multFact);
331 RotateImage(image, image2, NX*2, NY*2);
332 FlipImage(image2, image2, NY*2, NX*2);
333 MakeDicomImage(image, NY*2, NX*2, dcmImageName, patientName, 1, strStudyUID, strSerieUID, trueSerieDescr.str(), i, multiframe );
337 LoadImage(fromEcc, image, multFact);
338 RotateImage(image, image2, NX, NY);
339 FlipImage(image2, image2, NY, NX);
340 MakeDicomImage(image2, NY, NX, dcmImageName, patientName, 1, strStudyUID, strSerieUID, trueSerieDescr.str(), i, multiframe );
344 } // end : for (int i=0; i<numberOfSlices
348 for (int i=0; i<numberOfSlices; i++)
350 Ecc.str(rootfilename);
351 //Ecc << Ecc.str() << "_s" << i << "_Ecc.txt";
352 Ecc << Ecc.str() << "_s" << i << "_" << serieDescr << ".txt";
354 std::ifstream fromEcc( Ecc.str().c_str() );
357 std::cout << "Can't open file [" << Ecc.str() << "]" << std::endl;
361 std::cout << "Open file [" << Ecc.str() << "] : OK" << std::endl;
364 LoadImageX2(fromEcc ,&image[NX*NY*4*i] , multFact);
365 RotateImage(&image[NX*NY*4*i], &image2[NX*NY*4*i], NX*2, NY*2);
366 FlipImage( &image2[NX*NY*4*i], &image2[NX*NY*4*i], NY*2, NX*2);
370 LoadImage(fromEcc, &image[NX*NY*i], multFact );
371 RotateImage(&image[NX*NY*i], &image2[NX*NY*i], NX, NY);
372 FlipImage( &image2[NX*NY*i], &image2[NX*NY*i], NY, NX);
376 } // end : for (int i=0; i<numberOfSlices
378 // dcmImageName = deb + "_Ecc.dcm";
379 dcmImageName = deb + "_" + serieDescr + ".dcm";
381 MakeDicomImage(image2, NY*2, NX*2, dcmImageName, patientName, numberOfSlices, strStudyUID, strSerieUID, serieDescr, 0, multiframe );
383 MakeDicomImage(image2, NY, NX, dcmImageName, patientName, numberOfSlices, strStudyUID, strSerieUID, serieDescr, 0, multiframe );
384 } // end : if (multiframe)
387 //=====================================================================================================================================
389 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)
392 //std::cout << "========================> in MakeDicomImage : dcmImageName = [" << dcmImageName << "] NX= " << X << " NY= " << Y << std::endl;
393 // GDCM_NAME_SPACE::Debug::DebugOn();
395 std::ostringstream str;
397 GDCM_NAME_SPACE::File *file;
398 file = GDCM_NAME_SPACE::File::New();
400 // Set the image size
403 file->InsertEntryString(str.str(),0x0028,0x0011,"US"); // Columns
406 file->InsertEntryString(str.str(),0x0028,0x0010,"US"); // Rows
408 // Set the pixel type
410 file->InsertEntryString("16",0x0028,0x0100,"US"); // Bits Allocated
413 str << 16; // may be 12 or 16 if componentSize =16
414 file->InsertEntryString("16",0x0028,0x0101,"US"); // Bits Stored
415 file->InsertEntryString("15",0x0028,0x0102,"US"); // High Bit
417 // Set the pixel representation // 0/1 , 0=unsigned
418 file->InsertEntryString("1",0x0028,0x0103, "US"); // Pixel Representation
420 // Set the samples per pixel // 1:Grey level, 3:RGB
421 file->InsertEntryString("1",0x0028,0x0002, "US"); // Samples per Pixel
428 file->InsertEntryString(str.str(),0x0028,0x0008,"IS"); // Number of Frames
431 if (strlen(patientName) != 0)
432 file->InsertEntryString(patientName,0x0010,0x0010, "PN"); // Patient's Name
434 file->InsertEntryString(studyUID, 0x0020, 0x000d, "UI");
435 file->InsertEntryString(serieUID, 0x0020, 0x000e, "UI");
437 file->InsertEntryString(SerieDescr,0x0008,0x103e, "LO"); // Series Description
439 // 0020 0037 DS 6 Image Orientation (Patient)
440 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!)
442 // 0020 0032 DS 3 Image Position (Patient)
443 char charImagePosition[256];
444 sprintf(charImagePosition,"0.0\\0.0\\%f",(float)imgNum);
445 file->InsertEntryString(charImagePosition,0x0020,0x0032, "DS"); //0020 0032 DS 3 Image Position (Patient)
447 // 0020 0x1041 DS 1 Slice Location
448 sprintf(charImagePosition,"%f",float(imgNum));
449 file->InsertEntryString(charImagePosition,0x0020,0x1041, "DS");
451 // Set Rescale Intercept
454 file->InsertEntryString(str.str(),0x0028,0x1052,"DS");
459 file->InsertEntryString(str.str(),0x0028,0x1053,"DS");
462 GDCM_NAME_SPACE::FileHelper *fileH;
463 fileH = GDCM_NAME_SPACE::FileHelper::New(file);
464 // cast is just to avoid warnings (*no* conversion is performed)
465 //fileH->SetImageData((uint8_t *)img,int(maxX*maxY)*sizeof(uint16_t)); // troubles when maxX, mayY are *actually* float!
467 fileH->SetImageData((uint8_t *)tabVal,X*Y*nbFrames*sizeof(uint16_t));
468 fileH->SetWriteModeToRaw();
469 fileH->SetWriteTypeToDcmExplVR();
471 if( !fileH->Write(dcmImageName))
472 std::cout << "Failed for [" << dcmImageName << "]\n"
473 << " File is unwrittable" << std::endl;
480 //std::cout << "========================> out of MakeDicomImage : " << std::endl;
484 // =====================================================================================================================