1 /*=========================================================================
4 Module: $RCSfile: BrukerToMhd.cxx,v $
6 Date: $Date: 2010/09/01 14:40:00 $
7 Version: $Revision: 1.1 $
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 =========================================================================*/
20 * Writes an old style Bruker Dicom file, InTag compliant, from a Raw File
21 * User has to supply parameters.
25 #include "gdcmFileHelper.h"
26 #include "gdcmDebug.h"
28 #include "gdcmDirList.h"
30 #include "gdcmArgMgr.h"
35 void DealWithNiveau1(std::string level1Directory);
36 void DealWithNiveau2(std::string level2Directory);
37 void DealWithNiveau3(std::string level3Directory);
40 * - explores the given root directory e.g. :
69 * - fills a single level Directory with *all* the files,
70 * converted into a Brucker-like Dicom, Intags compliant
76 int main(int argc, char *argv[])
79 " \n BrukerToMhd : \n ",
80 " - explores the given directory, at the 3 levels, ",
81 " - fills an equivalent Directory with the MHD files, ",
82 " converted into a Brucker-like Dicom, InTags compliant ",
83 " usage: BrukerToMhd dirin=rootDirectoryName ",
84 " dirout=outputDirectoryName ",
85 " [{b|l}] b:BigEndian,l:LittleEndian default : l ",
86 " [debug] [verbose] [listonly] ",
88 " debug : developper wants to run the program in 'debug mode' ",
92 // ------------ Initialize Arguments Manager ----------------
93 GDCM_NAME_SPACE::ArgMgr *am= new GDCM_NAME_SPACE::ArgMgr(argc, argv);
95 if (argc == 1 || am->ArgMgrDefined("usage") )
97 am->ArgMgrUsage(usage); // Display 'usage'
102 const char *dirNamein;
103 dirNamein = am->ArgMgrGetString("dirin",".");
105 const char *dirNameout;
106 dirNameout = am->ArgMgrGetString("dirout",".");
108 int b = am->ArgMgrDefined("b");
109 int l = am->ArgMgrDefined("l");
111 if (am->ArgMgrDefined("debug"))
112 GDCM_NAME_SPACE::Debug::DebugOn();
114 int verbose = am->ArgMgrDefined("verbose");
115 int listonly = am->ArgMgrDefined("listonly");
117 /* if unused Param we give up */
118 if ( am->ArgMgrPrintUnusedLabels() )
120 am->ArgMgrUsage(usage);
125 delete am; // we don't need Argument Manager any longer
127 // ----------- End Arguments Manager ---------
130 // ----- Begin Processing -----
133 bool bigEndian = GDCM_NAME_SPACE::Util::IsCurrentProcessorBigEndian();
136 if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirNamein) )
138 std::cout << "KO : [" << dirNamein << "] is not a Directory." << std::endl;
144 std::cout << "OK : [" << dirNamein << "] is a Directory." << std::endl;
147 std::string systemCommand;
149 std::cout << "Check for output directory :[" << dirNameout << "]."
151 if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirNameout) ) // dirout not found
153 std::string strDirNameout(dirNameout); // to please gcc 4
154 systemCommand = "mkdir " +strDirNameout; // create it!
156 std::cout << systemCommand << std::endl;
157 system (systemCommand.c_str());
158 if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirNameout) ) // be sure it worked
160 std::cout << "KO : not a dir : [" << dirNameout << "] (creation failure ?)" << std::endl;
166 std::cout << "Directory [" << dirNameout << "] created." << std::endl;
171 std::cout << "Output Directory [" << dirNameout << "] already exists; Used as is." << std::endl;
174 std::string strDirNamein(dirNamein);
175 GDCM_NAME_SPACE::DirList dirList(strDirNamein, false, true); // DON'T get recursively the list of files
176 std::string strDirNameout(dirNameout);
180 std::cout << "------------List of found files ------------" << std::endl;
182 std::cout << std::endl;
187 GDCM_NAME_SPACE::DirListType fileNames;
188 fileNames = dirList.GetFilenames();
190 // GDCM_NAME_SPACE::File *f;
191 // GDCM_NAME_SPACE::FileHelper *fh;
193 std::string outputFileName;
195 // -----------------------------------------------------
196 // Iterate to ALL the objets(files/directories) found in the input directory
197 // -----------------------------------------------------
198 GDCM_NAME_SPACE::DirListType::iterator it;
200 for (it = fileNames.begin();
201 it != fileNames.end();
204 if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(*it) )
206 std::cout << "[" << *it << "] is a file" << std::endl;
211 for (it = fileNames.begin();
212 it != fileNames.end();
215 if ( GDCM_NAME_SPACE::DirList::IsDirectory(*it) )
217 std::cout << "[" << *it << "] is a directory" << std::endl;
218 DealWithNiveau1(*it);
225 std::ifstream *Fp = new std::ifstream((*it).c_str(), std::ios::in | std::ios::binary);
228 std::cout << "Cannot open file: [" << *it << "]" << std::endl;
234 std::cout << "Success to open file: [" << *it << "]" << std::endl;
238 int singlePlaneDataSize = nX*nY*samplesPerPixel*pixelSizeOut;
239 int dataSizeIn = nX*nY*samplesPerPixel*pixelSize*nZ;
241 uint8_t *pixels = new uint8_t[dataSizeIn];
242 uint8_t *planePixelsOut = new uint8_t[singlePlaneDataSize];
244 Fp->read((char*)pixels, (size_t)dataSizeIn);
246 if ( pixelSize !=1 && ( (l && bigEndian) || (b && ! bigEndian) ) )
248 ConvertSwapZone(pixelSize, pixels, dataSizeIn);
252 std::cout << "After ConvertSwapZone" << std::endl;
254 // Copy (and convert) pixels of a single plane
256 switch ( pixelTypeCode )
258 case 8 : CFR(PU8); break;
259 case -8 : CFR(PS8); break;
260 case -16 : CFR(PU16); break;
261 case 16 : CFR(PS16); break;
262 case -32 : CFR(PS32); break;
263 case 32 : CFR(PU32); break;
264 case 33 : CFR(PF32); break;
265 case 64 : CFR(PD64); break;
269 std::cout << "After CFR" << std::endl;
271 // Create an empty FileHelper
273 GDCM_NAME_SPACE::FileHelper *fileH = GDCM_NAME_SPACE::FileHelper::New();
275 // Get the (empty) image header.
276 GDCM_NAME_SPACE::File *fileToBuild = fileH->GetFile();
278 // 'Study Instance UID'
279 // The user is allowed to create his own Study,
280 // keeping the same 'Study Instance UID' for various images
281 // The user may add images to a 'Manufacturer Study',
282 // adding new Series to an already existing Study
284 fileToBuild->InsertEntryString(strStudyUID,0x0020,0x000d,"UI"); // Study UID
286 // 'Serie Instance UID'
287 // The user is allowed to create his own Series,
288 // keeping the same 'Serie Instance UID' for various images
289 // The user shouldn't add any image to a 'Manufacturer Serie'
290 // but there is no way no to prevent him for doing that
292 fileToBuild->InsertEntryString(strSerieUID,0x0020,0x000e,"UI"); // Serie UID
294 std::ostringstream str;
296 // Set the image size
299 fileToBuild->InsertEntryString(str.str(),0x0028,0x0011, "US"); // Columns
302 fileToBuild->InsertEntryString(str.str(),0x0028,0x0010, "US"); // Rows
305 std::cout << "before debut des choses serieuses2"<< std::endl;
309 // fileToBuild->InsertEntryString(str.str(),0x0028,0x0008, "IS"); // Number of Frames
311 // Set the pixel type
314 str << pixelSizeOut*8;
315 fileToBuild->InsertEntryString(str.str(),0x0028,0x0100, "US"); // Bits Allocated
318 str << pixelSizeOut*8;
319 fileToBuild->InsertEntryString(str.str(),0x0028,0x0101, "US"); // Bits Stored
322 str << ( pixelSizeOut*8 - 1 );
323 fileToBuild->InsertEntryString(str.str(),0x0028,0x0102, "US"); // High Bit
327 fileToBuild->InsertEntryString(str.str(),0x0028,0x0103, "US"); // Pixel Representation
329 // If you deal with a Serie of images, as slices of a volume,
330 // it's up to you to tell gdcm, for each image, what are the values of :
332 // 0020 0032 DS 3 Image Position (Patient)
333 // 0020 0037 DS 6 Image Orientation (Patient)
336 str << "0.0\\0.0\\0.0";
338 // take Frame Index as position (we don't know anything else) NO!
340 fileToBuild->InsertEntryString(str.str(),0x0020,0x0032, "DS");
342 fileToBuild->InsertEntryString("1.0\\0.0\\0.0\\0.0\\1.0\\0.0",0x0020,0x0037, "DS"); //[1\0\0\0\1\0] : Axial
348 str << samplesPerPixel;
349 fileToBuild->InsertEntryString(str.str(),0x0028,0x0002, "US"); // Samples per Pixel
351 if (strlen(patientName) != 0)
352 fileToBuild->InsertEntryString(patientName,0x0010,0x0010, "PN"); // Patient's Name
356 fileH->SetPhotometricInterpretationToMonochrome1();
358 // Special InTag, now.
360 fileH->InsertEntryString(chSessionIndex, 0x0020, 0x0012, "IS");
362 // Deal with 0x0021, 0x1020 : 'SLICE INDEX'
363 // will stay to 0, since the stuff deals with single slice directories
364 char chSliceIndex[5];
365 sprintf(chSliceIndex, "%04d", sliceIndex);
366 std::string strChSliceIndex(chSliceIndex);
368 // Deal with 0x0021, 0x1040 : 'FRAME INDEX'
372 frameIndex++; // be ready for next one
374 fileH->InsertEntryString(strChSliceIndex, 0x0021, 0x1020, "IS");
375 fileH->InsertEntryString(str.str(), 0x0021, 0x1040, "IS");
378 /// \TODO Ask user to supply 'Pixel Size' value
384 sprintf(fov, "%f\\%f",nX*pxSzX, nY*pxSzY);
385 fileH->InsertEntryString(fov, 0x0019, 0x1000, "DS");
388 // Set the image Pixel Data
389 fileH->SetImageData(planePixelsOut,singlePlaneDataSize);
391 // Set the writting mode and write the image
392 fileH->SetWriteModeToRaw();
396 // Write a DICOM Explicit VR file
397 fileH->SetWriteTypeToDcmExplVR();
400 outputFileName = strDirNameout + GDCM_NAME_SPACE::GDCM_FILESEPARATOR + *it + "_ForInTag.dcm";
401 if( !fileH->Write(outputFileName ) )
403 std::cout << "Failed for [" << outputFileName << "]\n"
404 << " File is unwrittable\n";
407 // End of : for (GDCM_NAME_SPACE::DirListType::iterator it = fileNames.begin() ...
414 delete[] planePixelsOut;
418 } // end of : for (GDCM_NAME_SPACE::DirListType::iterator it
422 void DealWithNiveau1(std::string level1Directory){
424 GDCM_NAME_SPACE::DirList dirList(level1Directory, false, true); // DON'T get recursively the list of files
426 GDCM_NAME_SPACE::DirListType fileNames;
427 fileNames = dirList.GetFilenames();
428 // -----------------------------------------------------
429 // Iterate to ALL the objets(files/directories) found in the input directory
430 // -----------------------------------------------------
431 GDCM_NAME_SPACE::DirListType::iterator it;
433 for (it = fileNames.begin();
434 it != fileNames.end();
437 if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(*it) )
439 std::cout << "--- [" << *it << "] is a file" << std::endl;
444 for (it = fileNames.begin();
445 it != fileNames.end();
448 if ( GDCM_NAME_SPACE::DirList::IsDirectory(*it) )
450 std::cout << "--- [" << *it << "] is a directory" << std::endl;
451 DealWithNiveau2(*it);
457 void DealWithNiveau2(std::string level2Directory){
459 GDCM_NAME_SPACE::DirList dirList(level2Directory, false, true); // DON'T get recursively the list of files
461 GDCM_NAME_SPACE::DirListType fileNames;
462 fileNames = dirList.GetFilenames();
464 // -----------------------------------------------------
465 // Iterate to ALL the objets(files/directories) found in the input directory
466 // -----------------------------------------------------
467 GDCM_NAME_SPACE::DirListType::iterator it;
469 for (it = fileNames.begin();
470 it != fileNames.end();
473 if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(*it) )
475 std::cout << "--- --- [" << *it << "] is a file" << std::endl;
480 for (it = fileNames.begin();
481 it != fileNames.end();
484 if ( GDCM_NAME_SPACE::DirList::IsDirectory(*it) )
486 std::cout << "--- --- [" << *it << "] is a directory" << std::endl;
487 DealWithNiveau3(*it);
493 void DealWithNiveau3(std::string level3Directory){
495 GDCM_NAME_SPACE::DirList dirList(level3Directory, false, true); // DON'T get recursively the list of files
497 GDCM_NAME_SPACE::DirListType fileNames;
498 fileNames = dirList.GetFilenames();
500 // -----------------------------------------------------
501 // Iterate fo ALL the directories found in the input directory
502 // -----------------------------------------------------
504 for (GDCM_NAME_SPACE::DirListType::iterator it = fileNames.begin();
505 it != fileNames.end();
509 if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(*it) )
511 std::cout << "--- --- --- [" << *it << "] is a file" << std::endl;
515 std::cout << "--- --- --- [" << *it << "] is a directory" << std::endl;