1 /*=========================================================================
4 Module: $RCSfile: SingleFrames2Multiframe.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 =========================================================================*/
19 #include "gdcmDocument.h"
20 #include "gdcmSeqEntry.h"
21 #include "gdcmSQItem.h"
22 #include "gdcmDataEntry.h"
25 #include "gdcmFileHelper.h"
26 #include "gdcmDebug.h"
27 #include "gdcmDirList.h"
28 #include "gdcmGlobal.h"
29 #include "gdcmDictSet.h"
30 #include "gdcmArgMgr.h"
31 #include "gdcmOrientation.h"
36 int main(int argc, char *argv[])
40 " \n SingleFrames2Multiframe : \n ",
41 " Converts a directory holding a set of SingleFrames to a Multiframe file",
42 " usage: SingleFrames2Multiframe {dirin=inputDirectoryName} ",
43 " fileout=nomDuFichierMultiframe ",
45 " [debug] [warning] ",
46 " studyUID : *aware* user wants to add the serie ",
47 " to an already existing study ",
48 " serieUID : *aware* user wants to give his own serie UID ",
49 " debug : user wants to run the program in 'debug mode' ",
50 " warning : user wants to be warned about any oddity in the File ",
53 // Initialize Arguments Manager
54 GDCM_NAME_SPACE::ArgMgr *am= new GDCM_NAME_SPACE::ArgMgr(argc, argv);
56 if (argc == 1 || am->ArgMgrDefined("usage") )
58 am->ArgMgrUsage(usage); // Display 'usage'
63 const char *dirName = am->ArgMgrGetString("dirin");
67 std::cerr << std::endl
68 << "'dirin=' must be present;";
69 am->ArgMgrUsage(usage); // Display 'usage'
74 const char *outputFileName = am->ArgMgrGetString("fileout");
75 if (outputFileName == 0 )
77 std::cerr << std::endl
78 << "'fileout=' must be present;" ;
79 am->ArgMgrUsage(usage); // Display 'usage'
84 if (am->ArgMgrDefined("debug"))
85 GDCM_NAME_SPACE::Debug::DebugOn();
87 if (am->ArgMgrDefined("warning"))
88 GDCM_NAME_SPACE::Debug::WarningOn();
90 bool userDefinedStudy = ( 0 != am->ArgMgrDefined("studyUID") );
93 studyUID = am->ArgMgrGetString("studyUID");
95 // not described *on purpose* in the Usage !
96 bool userDefinedSerie = ( 0 != am->ArgMgrDefined("serieUID") );
99 serieUID = am->ArgMgrGetString("serieUID");
101 /* if unused Param we give up */
102 if ( am->ArgMgrPrintUnusedLabels() )
104 am->ArgMgrUsage(usage);
109 delete am; // we don't need Argument Manager any longer
111 // ----------- End Arguments Manager ---------
114 GDCM_NAME_SPACE::DirList dirList(dirName,false); // gets recursively (or not) the file list
115 GDCM_NAME_SPACE::DirListType fileList = dirList.GetFilenames();
116 GDCM_NAME_SPACE::File *f;
120 if (fileList.size() == 0)
122 std::cout << "No file found in : [" << dirName << "]" << std::endl;
126 // Order on file name (no pertinent info within header for 'secondary capture storage' images
128 std::sort( fileList.begin(), fileList.end() );
130 f = GDCM_NAME_SPACE::File::New();
131 f->SetFileName( fileList[0].c_str() );
134 // if first file is not gdcm-readable, we give up.
135 // (maybe we should check *all* the files ...)
139 std::cout << "Cannot process file [" << fileList[0].c_str() << "]"
141 std::cout << "Either it doesn't exist, or it's read protected "
143 std::cout << "or it's not a Dicom File, or its 'header' is bugged"
145 std::cout << "use 'PrintFile filein=... debug' "
146 << "to try to guess the pb"
152 int nX = f->GetXSize();
153 int nY = f->GetYSize();
154 int nZ = fileList.size();
155 int pxSz = f->GetPixelSize();
156 int sPP = f->GetSamplesPerPixel();
158 std::string stud= f->GetEntryString(0x0020,0x000d );
159 std::cout << "------------------------------------------------ Study UID " << stud << std::endl;
162 std::cout << "First file nX " << nX << " nY " << nY << " nZ " << nZ << " pxSz " << pxSz << " sPP " << sPP << std::endl;
163 std::cout << "Image size " << nX*nY*pxSz*sPP << std::endl;
165 char *imageBuffer; // = new char[nX*nY*pxSz];
166 char *globalBuffer = new char[nX*nY*nZ*pxSz*sPP];
168 int i = 0; // image counter
169 for( GDCM_NAME_SPACE::DirListType::iterator it = fileList.begin();
170 it != fileList.end();
173 std::cout << std::endl<<" Start processing :[" << it->c_str() << "]"
175 f = GDCM_NAME_SPACE::File::New();
176 f->SetFileName( it->c_str() );
181 std::cout << "Cannot process file [" << it->c_str() << "]"
183 std::cout << "Either it doesn't exist, or it's read protected "
185 std::cout << "or it's not a Dicom File, or its 'header' is bugged"
187 std::cout << "use 'PrintFile filein=... debug' "
188 << "to try to guess the pb"
194 GDCM_NAME_SPACE::FileHelper *fh = GDCM_NAME_SPACE::FileHelper::New(f);
195 imageBuffer = (char *)fh->GetImageData();
196 int lgr = fh->GetImageDataSize();
198 // we check all the files are consistent with the first one
199 if ( lgr != nX*nY*pxSz*sPP)
201 std::cout << "File : [" << it->c_str() << "] inconsistent with first one (lgr " << lgr << " vs " << nX*nY*pxSz*sPP<< "); ignored!" << std::endl;
207 memcpy(globalBuffer+i*nX*nY*pxSz*sPP, imageBuffer, lgr );
213 GDCM_NAME_SPACE::FileHelper *fh2 = GDCM_NAME_SPACE::FileHelper::New();
215 std::string strStudyUID;
216 std::string strSerieUID;
218 if (userDefinedStudy)
219 strSerieUID = studyUID;
222 //strStudyUID = GDCM_NAME_SPACE::Util::CreateUniqueUID();
227 if (userDefinedSerie)
228 strSerieUID = serieUID;
230 strSerieUID = GDCM_NAME_SPACE::Util::CreateUniqueUID();
234 sprintf(temp, "%d", sPP);
235 fh2->InsertEntryString(temp,0x0028,0x0002, "US"); // Samples per Pixel
237 sprintf(temp, "%d", nY);
238 fh2->InsertEntryString(temp,0x0028,0x0010, "US"); // Number of Rows
240 sprintf(temp, "%d", nX);
241 fh2->InsertEntryString(temp,0x0028,0x0011, "US"); // Number of Columns
243 sprintf(temp, "%d", nZ);
244 fh2->InsertEntryString(temp,0x0028,0x0008, "IS"); // Number of Frames
246 sprintf(temp, "%d", pxSz*8);
247 fh2->InsertEntryString(temp,0x0028,0x0100, "US"); // Bits Allocated
251 // 'Study Instance UID'
252 // The user is allowed to create his own Study,
253 // keeping the same 'Study Instance UID' for various images
254 // The user may add images to a 'Manufacturer Study',
255 // adding new Series to an already existing Study
257 fh2->InsertEntryString(strStudyUID,0x0020,0x000d,"UI"); // Study UID
259 // 'Serie Instance UID'
260 // The user is allowed to create his own Series,
261 // keeping the same 'Serie Instance UID' for various images
262 // The user shouldn't add any image to a 'Manufacturer Serie'
263 // but there is no way no to prevent him for doing that
265 fh2->InsertEntryString(strSerieUID,0x0020,0x000e,"UI"); // Serie UID
267 // Set the image Pixel Data
268 fh2->SetUserData((uint8_t *)globalBuffer, nX*nY*pxSz*sPP*nZ);
270 res = fh2->Write(outputFileName);
273 std::cout <<"Fail to write [" << outputFileName << "]" <<std::endl;