]> Creatis software - gdcm.git/blob - Example/SingleFrames2Multiframe.cxx
Small exe, for unaware users
[gdcm.git] / Example / SingleFrames2Multiframe.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: SingleFrames2Multiframe.cxx,v $
5   Language:  C++
6   Date:      $Date: 2010/09/01 14:40:00 $
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 #include "gdcmFile.h"
19 #include "gdcmDocument.h"
20 #include "gdcmSeqEntry.h"
21 #include "gdcmSQItem.h"
22 #include "gdcmDataEntry.h"
23 #include "gdcmUtil.h"
24
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"
32 #include <iostream>
33
34 #include <algorithm>
35
36 int main(int argc, char *argv[])
37 {
38
39    START_USAGE(usage)
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                    ",
44    
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   ",
51    FINISH_USAGE
52
53    // Initialize Arguments Manager   
54    GDCM_NAME_SPACE::ArgMgr *am= new GDCM_NAME_SPACE::ArgMgr(argc, argv);
55   
56    if (argc == 1 || am->ArgMgrDefined("usage") )
57    {
58       am->ArgMgrUsage(usage); // Display 'usage'
59       delete am;
60       return 1;
61    }
62
63    const char *dirName  = am->ArgMgrGetString("dirin");
64
65    if  (dirName == 0 )
66    {
67       std::cerr << std::endl
68         << "'dirin=' must be present;";
69       am->ArgMgrUsage(usage); // Display 'usage'  
70       delete am;
71       return 1;
72    }   
73
74    const char *outputFileName = am->ArgMgrGetString("fileout");
75    if  (outputFileName == 0 )
76    {
77       std::cerr << std::endl
78         << "'fileout=' must be present;" ;
79       am->ArgMgrUsage(usage); // Display 'usage'  
80       delete am;
81       return 1;
82    }
83    
84    if (am->ArgMgrDefined("debug"))
85       GDCM_NAME_SPACE::Debug::DebugOn();
86
87    if (am->ArgMgrDefined("warning"))
88       GDCM_NAME_SPACE::Debug::WarningOn();
89
90    bool userDefinedStudy = ( 0 != am->ArgMgrDefined("studyUID") );
91    const char *studyUID;
92    if (userDefinedStudy)
93       studyUID  = am->ArgMgrGetString("studyUID");  
94
95    // not described *on purpose* in the Usage !
96    bool userDefinedSerie = ( 0 != am->ArgMgrDefined("serieUID") );       
97    const char *serieUID;
98    if(userDefinedSerie)
99       serieUID = am->ArgMgrGetString("serieUID");
100
101    /* if unused Param we give up */
102    if ( am->ArgMgrPrintUnusedLabels() )
103    {
104       am->ArgMgrUsage(usage);
105       delete am;
106       return 1;
107    } 
108
109    delete am;  // we don't need Argument Manager any longer
110
111    // ----------- End Arguments Manager ---------
112
113
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;
117       
118       bool res;
119
120       if (fileList.size() == 0)
121       {
122          std::cout << "No file found in : [" << dirName << "]" << std::endl;
123          exit(0);
124       }
125
126       // Order on file name (no pertinent info within header for 'secondary capture storage' images
127       //fileList.sort();
128       std::sort( fileList.begin(), fileList.end() );
129
130       f = GDCM_NAME_SPACE::File::New();
131       f->SetFileName( fileList[0].c_str() );
132       res = f->Load();
133
134       // if first file is not gdcm-readable, we give up.
135       // (maybe we should check *all* the files ...)
136
137       if (!res)
138       {
139             std::cout << "Cannot process file [" << fileList[0].c_str() << "]" 
140                       << std::endl;
141             std::cout << "Either it doesn't exist, or it's read protected " 
142                       << std::endl;
143             std::cout << "or it's not a Dicom File, or its 'header' is bugged" 
144                       << std::endl;
145             std::cout << "use 'PrintFile filein=... debug' "
146                       << "to try to guess the pb"
147                       << std::endl;
148             f->Delete();
149             exit(0);
150       } 
151
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();
157       
158       std::string stud= f->GetEntryString(0x0020,0x000d );
159       std::cout << "------------------------------------------------ Study UID " << stud << std::endl;
160       
161       
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;
164      
165       char *imageBuffer; //   = new char[nX*nY*pxSz];
166       char *globalBuffer = new char[nX*nY*nZ*pxSz*sPP];
167       
168       int i = 0;  // image counter           
169       for( GDCM_NAME_SPACE::DirListType::iterator it  = fileList.begin();
170                                  it != fileList.end();
171                                  ++it )
172       {
173          std::cout << std::endl<<" Start processing :[" << it->c_str() << "]"
174                    << std::endl;
175          f = GDCM_NAME_SPACE::File::New();
176          f->SetFileName( it->c_str() );
177          res = f->Load();
178  
179          if ( !res )
180          {
181             std::cout << "Cannot process file [" << it->c_str() << "]" 
182                       << std::endl;
183             std::cout << "Either it doesn't exist, or it's read protected " 
184                       << std::endl;
185             std::cout << "or it's not a Dicom File, or its 'header' is bugged" 
186                       << std::endl;
187             std::cout << "use 'PrintFile filein=... debug' "
188                       << "to try to guess the pb"
189                       << std::endl;
190             f->Delete();
191             continue;
192          }
193  
194          GDCM_NAME_SPACE::FileHelper *fh = GDCM_NAME_SPACE::FileHelper::New(f);
195          imageBuffer = (char *)fh->GetImageData();
196          int lgr     = fh->GetImageDataSize();
197
198       //  we check all the files are consistent with the first one  
199          if ( lgr != nX*nY*pxSz*sPP)
200          {
201             std::cout << "File : [" << it->c_str() << "] inconsistent with first one (lgr " <<  lgr  << " vs " << nX*nY*pxSz*sPP<< "); ignored!" << std::endl;
202             continue;
203          }
204          else
205  
206          {
207             memcpy(globalBuffer+i*nX*nY*pxSz*sPP, imageBuffer, lgr );
208             i++;
209          }
210          fh->Delete();
211       }
212
213       GDCM_NAME_SPACE::FileHelper *fh2 = GDCM_NAME_SPACE::FileHelper::New();
214
215    std::string strStudyUID;
216    std::string strSerieUID;
217
218    if (userDefinedStudy)
219       strSerieUID = studyUID;
220    else
221    {
222       //strStudyUID = GDCM_NAME_SPACE::Util::CreateUniqueUID();
223       
224       strStudyUID = stud;
225    } 
226    
227    if (userDefinedSerie)
228      strSerieUID = serieUID;
229    else
230       strSerieUID = GDCM_NAME_SPACE::Util::CreateUniqueUID();
231                  
232       char temp[64];
233       
234       sprintf(temp, "%d", sPP);
235       fh2->InsertEntryString(temp,0x0028,0x0002, "US"); // Samples per Pixel
236            
237       sprintf(temp, "%d", nY);
238       fh2->InsertEntryString(temp,0x0028,0x0010, "US"); // Number of Rows
239    
240       sprintf(temp, "%d", nX);
241       fh2->InsertEntryString(temp,0x0028,0x0011, "US"); // Number of Columns      
242       
243       sprintf(temp, "%d", nZ);
244       fh2->InsertEntryString(temp,0x0028,0x0008, "IS"); // Number of Frames
245       
246       sprintf(temp, "%d", pxSz*8);
247       fh2->InsertEntryString(temp,0x0028,0x0100, "US"); // Bits Allocated
248
249
250
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
256
257    fh2->InsertEntryString(strStudyUID,0x0020,0x000d,"UI");  //  Study UID   
258
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
264    
265    fh2->InsertEntryString(strSerieUID,0x0020,0x000e,"UI");  //  Serie UID
266    
267       // Set the image Pixel Data
268       fh2->SetUserData((uint8_t *)globalBuffer, nX*nY*pxSz*sPP*nZ);
269       
270       res = fh2->Write(outputFileName);
271       
272       if(!res)
273          std::cout <<"Fail to write [" << outputFileName << "]" <<std::endl;    
274
275       f->Delete();
276       fh2->Delete();
277
278       return 0;
279 }