]> Creatis software - gdcm.git/blobdiff - Example/SingleFrames2Multiframe.cxx
Small exe, for unaware users
[gdcm.git] / Example / SingleFrames2Multiframe.cxx
diff --git a/Example/SingleFrames2Multiframe.cxx b/Example/SingleFrames2Multiframe.cxx
new file mode 100644 (file)
index 0000000..b0e1535
--- /dev/null
@@ -0,0 +1,279 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: SingleFrames2Multiframe.cxx,v $
+  Language:  C++
+  Date:      $Date: 2010/09/01 14:40:00 $
+  Version:   $Revision: 1.1 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+#include "gdcmFile.h"
+#include "gdcmDocument.h"
+#include "gdcmSeqEntry.h"
+#include "gdcmSQItem.h"
+#include "gdcmDataEntry.h"
+#include "gdcmUtil.h"
+
+#include "gdcmFileHelper.h"
+#include "gdcmDebug.h"
+#include "gdcmDirList.h"
+#include "gdcmGlobal.h"
+#include "gdcmDictSet.h"
+#include "gdcmArgMgr.h"
+#include "gdcmOrientation.h"
+#include <iostream>
+
+#include <algorithm>
+
+int main(int argc, char *argv[])
+{
+
+   START_USAGE(usage)
+   " \n SingleFrames2Multiframe : \n                                          ",
+   "   Converts a directory holding a set of SingleFrames to a Multiframe file",
+   " usage: SingleFrames2Multiframe {dirin=inputDirectoryName}                ",
+   "                        fileout=nomDuFichierMultiframe                    ",
+   
+   "                       [debug] [warning]                                  ",
+   "  studyUID   : *aware* user wants to add the serie                        ",
+   "                                             to an already existing study ",
+   "  serieUID   : *aware* user wants to give his own serie UID               ",
+   "      debug      : user wants to run the program in 'debug mode'          ",
+   "      warning    : user wants to be warned about any oddity in the File   ",
+   FINISH_USAGE
+
+   // Initialize Arguments Manager   
+   GDCM_NAME_SPACE::ArgMgr *am= new GDCM_NAME_SPACE::ArgMgr(argc, argv);
+  
+   if (argc == 1 || am->ArgMgrDefined("usage") )
+   {
+      am->ArgMgrUsage(usage); // Display 'usage'
+      delete am;
+      return 1;
+   }
+
+   const char *dirName  = am->ArgMgrGetString("dirin");
+
+   if  (dirName == 0 )
+   {
+      std::cerr << std::endl
+        << "'dirin=' must be present;";
+      am->ArgMgrUsage(usage); // Display 'usage'  
+      delete am;
+      return 1;
+   }   
+
+   const char *outputFileName = am->ArgMgrGetString("fileout");
+   if  (outputFileName == 0 )
+   {
+      std::cerr << std::endl
+        << "'fileout=' must be present;" ;
+      am->ArgMgrUsage(usage); // Display 'usage'  
+      delete am;
+      return 1;
+   }
+   
+   if (am->ArgMgrDefined("debug"))
+      GDCM_NAME_SPACE::Debug::DebugOn();
+
+   if (am->ArgMgrDefined("warning"))
+      GDCM_NAME_SPACE::Debug::WarningOn();
+
+   bool userDefinedStudy = ( 0 != am->ArgMgrDefined("studyUID") );
+   const char *studyUID;
+   if (userDefinedStudy)
+      studyUID  = am->ArgMgrGetString("studyUID");  
+
+   // not described *on purpose* in the Usage !
+   bool userDefinedSerie = ( 0 != am->ArgMgrDefined("serieUID") );       
+   const char *serieUID;
+   if(userDefinedSerie)
+      serieUID = am->ArgMgrGetString("serieUID");
+
+   /* if unused Param we give up */
+   if ( am->ArgMgrPrintUnusedLabels() )
+   {
+      am->ArgMgrUsage(usage);
+      delete am;
+      return 1;
+   } 
+
+   delete am;  // we don't need Argument Manager any longer
+
+   // ----------- End Arguments Manager ---------
+
+
+      GDCM_NAME_SPACE::DirList dirList(dirName,false); // gets recursively (or not) the file list
+      GDCM_NAME_SPACE::DirListType fileList = dirList.GetFilenames();
+      GDCM_NAME_SPACE::File *f;
+      
+      bool res;
+
+      if (fileList.size() == 0)
+      {
+         std::cout << "No file found in : [" << dirName << "]" << std::endl;
+         exit(0);
+      }
+
+      // Order on file name (no pertinent info within header for 'secondary capture storage' images
+      //fileList.sort();
+      std::sort( fileList.begin(), fileList.end() );
+
+      f = GDCM_NAME_SPACE::File::New();
+      f->SetFileName( fileList[0].c_str() );
+      res = f->Load();
+
+      // if first file is not gdcm-readable, we give up.
+      // (maybe we should check *all* the files ...)
+
+      if (!res)
+      {
+            std::cout << "Cannot process file [" << fileList[0].c_str() << "]" 
+                      << std::endl;
+            std::cout << "Either it doesn't exist, or it's read protected " 
+                      << std::endl;
+            std::cout << "or it's not a Dicom File, or its 'header' is bugged" 
+                      << std::endl;
+            std::cout << "use 'PrintFile filein=... debug' "
+                      << "to try to guess the pb"
+                      << std::endl;
+            f->Delete();
+            exit(0);
+      } 
+
+      int nX   = f->GetXSize();
+      int nY   = f->GetYSize();
+      int nZ   = fileList.size();
+      int pxSz = f->GetPixelSize();
+      int sPP  = f->GetSamplesPerPixel();
+      
+      std::string stud= f->GetEntryString(0x0020,0x000d );
+      std::cout << "------------------------------------------------ Study UID " << stud << std::endl;
+      
+      
+     std::cout << "First file nX " << nX << " nY " << nY << " nZ " << nZ << " pxSz " << pxSz << " sPP " << sPP << std::endl;
+     std::cout << "Image size " << nX*nY*pxSz*sPP << std::endl;
+     
+      char *imageBuffer; //   = new char[nX*nY*pxSz];
+      char *globalBuffer = new char[nX*nY*nZ*pxSz*sPP];
+      
+      int i = 0;  // image counter           
+      for( GDCM_NAME_SPACE::DirListType::iterator it  = fileList.begin();
+                                 it != fileList.end();
+                                 ++it )
+      {
+         std::cout << std::endl<<" Start processing :[" << it->c_str() << "]"
+                   << std::endl;
+         f = GDCM_NAME_SPACE::File::New();
+         f->SetFileName( it->c_str() );
+         res = f->Load();
+         if ( !res )
+         {
+            std::cout << "Cannot process file [" << it->c_str() << "]" 
+                      << std::endl;
+            std::cout << "Either it doesn't exist, or it's read protected " 
+                      << std::endl;
+            std::cout << "or it's not a Dicom File, or its 'header' is bugged" 
+                      << std::endl;
+            std::cout << "use 'PrintFile filein=... debug' "
+                      << "to try to guess the pb"
+                      << std::endl;
+            f->Delete();
+            continue;
+         }
+         GDCM_NAME_SPACE::FileHelper *fh = GDCM_NAME_SPACE::FileHelper::New(f);
+         imageBuffer = (char *)fh->GetImageData();
+         int lgr     = fh->GetImageDataSize();
+
+      //  we check all the files are consistent with the first one  
+         if ( lgr != nX*nY*pxSz*sPP)
+         {
+            std::cout << "File : [" << it->c_str() << "] inconsistent with first one (lgr " <<  lgr  << " vs " << nX*nY*pxSz*sPP<< "); ignored!" << std::endl;
+            continue;
+         }
+         else
+         {
+            memcpy(globalBuffer+i*nX*nY*pxSz*sPP, imageBuffer, lgr );
+            i++;
+         }
+         fh->Delete();
+      }
+
+      GDCM_NAME_SPACE::FileHelper *fh2 = GDCM_NAME_SPACE::FileHelper::New();
+
+   std::string strStudyUID;
+   std::string strSerieUID;
+
+   if (userDefinedStudy)
+      strSerieUID = studyUID;
+   else
+   {
+      //strStudyUID = GDCM_NAME_SPACE::Util::CreateUniqueUID();
+      
+      strStudyUID = stud;
+   } 
+   
+   if (userDefinedSerie)
+     strSerieUID = serieUID;
+   else
+      strSerieUID = GDCM_NAME_SPACE::Util::CreateUniqueUID();
+                 
+      char temp[64];
+      
+      sprintf(temp, "%d", sPP);
+      fh2->InsertEntryString(temp,0x0028,0x0002, "US"); // Samples per Pixel
+           
+      sprintf(temp, "%d", nY);
+      fh2->InsertEntryString(temp,0x0028,0x0010, "US"); // Number of Rows
+   
+      sprintf(temp, "%d", nX);
+      fh2->InsertEntryString(temp,0x0028,0x0011, "US"); // Number of Columns      
+      
+      sprintf(temp, "%d", nZ);
+      fh2->InsertEntryString(temp,0x0028,0x0008, "IS"); // Number of Frames
+      
+      sprintf(temp, "%d", pxSz*8);
+      fh2->InsertEntryString(temp,0x0028,0x0100, "US"); // Bits Allocated
+
+
+
+   // 'Study Instance UID'
+   // The user is allowed to create his own Study, 
+   //          keeping the same 'Study Instance UID' for various images
+   // The user may add images to a 'Manufacturer Study',
+   //          adding new Series to an already existing Study
+
+   fh2->InsertEntryString(strStudyUID,0x0020,0x000d,"UI");  //  Study UID   
+
+   // 'Serie Instance UID'
+   // The user is allowed to create his own Series, 
+   // keeping the same 'Serie Instance UID' for various images
+   // The user shouldn't add any image to a 'Manufacturer Serie'
+   // but there is no way no to prevent him for doing that
+   
+   fh2->InsertEntryString(strSerieUID,0x0020,0x000e,"UI");  //  Serie UID
+   
+      // Set the image Pixel Data
+      fh2->SetUserData((uint8_t *)globalBuffer, nX*nY*pxSz*sPP*nZ);
+      
+      res = fh2->Write(outputFileName);
+      
+      if(!res)
+         std::cout <<"Fail to write [" << outputFileName << "]" <<std::endl;    
+
+      f->Delete();
+      fh2->Delete();
+
+      return 0;
+}