]> Creatis software - gdcm.git/commitdiff
Small exe, for unaware users
authorjpr <jpr>
Wed, 1 Sep 2010 14:40:00 +0000 (14:40 +0000)
committerjpr <jpr>
Wed, 1 Sep 2010 14:40:00 +0000 (14:40 +0000)
Example/BrukerToMhd.cxx [new file with mode: 0644]
Example/SingleFrames2Multiframe.cxx [new file with mode: 0644]
Example/exExplorePresentationState.cxx [new file with mode: 0644]

diff --git a/Example/BrukerToMhd.cxx b/Example/BrukerToMhd.cxx
new file mode 100644 (file)
index 0000000..a4be43e
--- /dev/null
@@ -0,0 +1,519 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: BrukerToMhd.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.
+                                      
+=========================================================================*/
+
+/**
+ * Writes an old style Bruker Dicom file, InTag compliant, from a Raw File
+ * User has to supply parameters. 
+ * 
+ */
+#include "gdcmFile.h"
+#include "gdcmFileHelper.h"
+#include "gdcmDebug.h"
+#include "gdcmUtil.h"
+#include "gdcmDirList.h"
+
+#include "gdcmArgMgr.h"
+
+#include <iostream>
+#include <sstream>
+
+void DealWithNiveau1(std::string level1Directory);
+void DealWithNiveau2(std::string level2Directory);
+void DealWithNiveau3(std::string level3Directory);
+/**
+  * \brief   
+  *          - explores  the given root directory e.g. :
+  *            B67d1.Bp1
+  *              subject
+  *              AdjStatePerStudy
+  *              1
+  *                 acqp
+  *                 fid
+  *                 imnd
+  *                 pulseprogram
+  *                 spnam0
+  *                 spnam1
+  *                 pdata
+  *                    1
+  *                       2dseq
+  *                       d3proc
+  *                       isa
+  *                       meta
+  *                       procs
+  *                       roi
+  *                    2
+  *                       ...                   
+  * 
+  *              2
+  *                 acqp
+  *                 fid
+  *                 ...
+  *                 pdata
+  *              3         
+  *                ...
+  *          - fills a single level Directory with *all* the files,
+  *            converted into a Brucker-like Dicom, Intags compliant
+  */  
+  
+
+
+
+int main(int argc, char *argv[])
+{
+   START_USAGE(usage)
+   " \n BrukerToMhd : \n                                                      ",
+   " - explores the given directory, at the 3 levels,                         ",
+   " - fills an equivalent Directory with the MHD files,                      ",
+   "           converted into a Brucker-like Dicom, InTags compliant          ",
+   " usage: BrukerToMhd dirin=rootDirectoryName                               ",
+   "                   dirout=outputDirectoryName                             ",
+   "                   [{b|l}] b:BigEndian,l:LittleEndian default : l         ",
+   "                   [debug] [verbose] [listonly]                           ",
+   "                                                                          ",
+   "  debug      : developper wants to run the program in 'debug mode'        ",
+   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 *dirNamein;   
+   dirNamein  = am->ArgMgrGetString("dirin",".");
+
+   const char *dirNameout;   
+   dirNameout  = am->ArgMgrGetString("dirout",".");
+   
+   int b = am->ArgMgrDefined("b");
+   int l = am->ArgMgrDefined("l");
+   
+   if (am->ArgMgrDefined("debug"))
+      GDCM_NAME_SPACE::Debug::DebugOn();
+
+   int verbose  = am->ArgMgrDefined("verbose");      
+   int listonly = am->ArgMgrDefined("listonly");
+   
+   /* 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 ---------
+   
+
+   // ----- Begin Processing -----
+
+
+   bool bigEndian = GDCM_NAME_SPACE::Util::IsCurrentProcessorBigEndian();
+
+   if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirNamein) )
+   {
+      std::cout << "KO : [" << dirNamein << "] is not a Directory." << std::endl;
+      return 0;
+
+   }
+   else
+   {
+      std::cout << "OK : [" << dirNamein << "] is a Directory." << std::endl;
+   }
+   std::string systemCommand;
+   
+   std::cout << "Check for output directory :[" << dirNameout << "]."
+             <<std::endl;
+   if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirNameout) )    // dirout not found
+   {
+      std::string strDirNameout(dirNameout);          // to please gcc 4
+      systemCommand = "mkdir " +strDirNameout;        // create it!
+      if (verbose)
+         std::cout << systemCommand << std::endl;
+      system (systemCommand.c_str());
+      if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirNameout) ) // be sure it worked
+      {
+          std::cout << "KO : not a dir : [" << dirNameout << "] (creation failure ?)" << std::endl;
+      return 0;
+
+      }
+      else
+      {
+        std::cout << "Directory [" << dirNameout << "] created." << std::endl;
+      }
+   }
+   else
+   {
+       std::cout << "Output Directory [" << dirNameout << "] already exists; Used as is." << std::endl;
+   }
+
+   std::string strDirNamein(dirNamein);
+   GDCM_NAME_SPACE::DirList dirList(strDirNamein, false, true); // DON'T get recursively the list of files
+   std::string strDirNameout(dirNameout);   
+   
+   if (listonly)
+   {
+      std::cout << "------------List of found files ------------" << std::endl;
+      dirList.Print();
+      std::cout << std::endl;
+      return 1;
+   }
+
+
+   GDCM_NAME_SPACE::DirListType fileNames;
+   fileNames = dirList.GetFilenames();
+
+  // GDCM_NAME_SPACE::File *f;
+  // GDCM_NAME_SPACE::FileHelper *fh;
+
+   std::string outputFileName;
+
+   // -----------------------------------------------------
+   // Iterate to ALL the objets(files/directories) found in the input directory
+   // -----------------------------------------------------
+   GDCM_NAME_SPACE::DirListType::iterator it;
+   
+   for (it = fileNames.begin();
+        it != fileNames.end();
+      ++it)
+   {
+      if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(*it) )
+      { 
+         std::cout << "[" << *it << "] is a file" << std::endl;
+      }
+      
+   }
+   
+    for (it = fileNames.begin();
+         it != fileNames.end();
+       ++it)
+   {
+      if ( GDCM_NAME_SPACE::DirList::IsDirectory(*it) )
+      { 
+         std::cout << "[" << *it << "] is a directory" << std::endl;
+         DealWithNiveau1(*it);
+      }
+   }
+   
+   /*
+   
+ // Open the Raw file
+   std::ifstream *Fp = new std::ifstream((*it).c_str(), std::ios::in | std::ios::binary);
+   if ( ! *Fp )
+   {
+      std::cout << "Cannot open file: [" << *it << "]" << std::endl;
+      delete Fp;
+      Fp = 0;
+      return 0;
+   }
+   if (verbose)
+      std::cout << "Success to open file: [" << *it << "]" << std::endl;
+
+   // Read the pixels
+
+   int singlePlaneDataSize =  nX*nY*samplesPerPixel*pixelSizeOut;
+   int dataSizeIn          =  nX*nY*samplesPerPixel*pixelSize*nZ;
+
+   uint8_t *pixels         = new uint8_t[dataSizeIn];
+   uint8_t *planePixelsOut = new uint8_t[singlePlaneDataSize];
+
+   Fp->read((char*)pixels, (size_t)dataSizeIn);
+
+   if ( pixelSize !=1 && ( (l && bigEndian) || (b && ! bigEndian) ) )
+   {  
+      ConvertSwapZone(pixelSize, pixels, dataSizeIn);
+   }
+
+if (verbose)
+   std::cout << "After ConvertSwapZone" << std::endl;
+
+// Copy (and convert) pixels of a single plane
+
+     switch ( pixelTypeCode )
+     {
+       case 8    : CFR(PU8);  break;
+       case -8   : CFR(PS8);  break;
+       case -16  : CFR(PU16); break;
+       case 16   : CFR(PS16); break;
+       case -32  : CFR(PS32); break;
+       case 32   : CFR(PU32); break;
+       case 33   : CFR(PF32); break;
+       case 64   : CFR(PD64); break;
+     }
+
+if (verbose)
+   std::cout << "After CFR" << std::endl;
+   
+// Create an empty FileHelper
+
+   GDCM_NAME_SPACE::FileHelper *fileH = GDCM_NAME_SPACE::FileHelper::New();
+ // Get the (empty) image header.
+   GDCM_NAME_SPACE::File *fileToBuild = fileH->GetFile();
+
+   // '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
+
+   fileToBuild->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
+   
+   fileToBuild->InsertEntryString(strSerieUID,0x0020,0x000e,"UI");  //  Serie UID
+   
+   std::ostringstream str;
+
+   // Set the image size
+   str.str("");
+   str << nX;
+   fileToBuild->InsertEntryString(str.str(),0x0028,0x0011, "US"); // Columns
+   str.str("");
+   str << nY;
+   fileToBuild->InsertEntryString(str.str(),0x0028,0x0010, "US"); // Rows
+   
+       if (verbose)
+         std::cout << "before  debut des choses serieuses2"<< std::endl;      
+  
+//   str.str("");
+//   str << nZ;
+//   fileToBuild->InsertEntryString(str.str(),0x0028,0x0008, "IS"); // Number of Frames
+
+   // Set the pixel type
+   
+   str.str("");
+   str << pixelSizeOut*8;
+   fileToBuild->InsertEntryString(str.str(),0x0028,0x0100, "US"); // Bits Allocated
+
+   str.str("");
+   str << pixelSizeOut*8;
+   fileToBuild->InsertEntryString(str.str(),0x0028,0x0101, "US"); // Bits Stored
+
+   str.str("");
+   str << ( pixelSizeOut*8 - 1 );
+   fileToBuild->InsertEntryString(str.str(),0x0028,0x0102, "US"); // High Bit
+
+   str.str("");
+   str << pixelSign;
+   fileToBuild->InsertEntryString(str.str(),0x0028,0x0103, "US"); // Pixel Representation
+
+// If you deal with a Serie of images, as slices of a volume,
+// it's up to you to tell gdcm, for each image, what are the values of :
+// 
+// 0020 0032 DS 3 Image Position (Patient)
+// 0020 0037 DS 6 Image Orientation (Patient)
+
+   str.str("");
+   str << "0.0\\0.0\\0.0";
+
+// take Frame Index as position (we don't know anything else) NO!
+
+   fileToBuild->InsertEntryString(str.str(),0x0020,0x0032, "DS");
+
+   fileToBuild->InsertEntryString("1.0\\0.0\\0.0\\0.0\\1.0\\0.0",0x0020,0x0037, "DS"); //[1\0\0\0\1\0] : Axial
+   
+   
+   
+   
+   str.str("");
+   str << samplesPerPixel;
+   fileToBuild->InsertEntryString(str.str(),0x0028,0x0002, "US"); // Samples per Pixel
+
+   if (strlen(patientName) != 0)
+      fileToBuild->InsertEntryString(patientName,0x0010,0x0010, "PN"); // Patient's Name
+    
+   //  0=white  
+   if(monochrome1)
+      fileH->SetPhotometricInterpretationToMonochrome1();
+
+// Special InTag, now.
+
+      fileH->InsertEntryString(chSessionIndex, 0x0020, 0x0012, "IS");
+
+      // Deal with  0x0021, 0x1020 : 'SLICE INDEX'
+      // will stay to 0, since the stuff deals with single slice directories
+      char chSliceIndex[5];
+      sprintf(chSliceIndex, "%04d", sliceIndex);
+      std::string strChSliceIndex(chSliceIndex);
+
+      // Deal with  0x0021, 0x1040 : 'FRAME INDEX'
+
+      str.str("");
+      str << frameIndex;
+      frameIndex++;  // be ready for next one 
+
+      fileH->InsertEntryString(strChSliceIndex, 0x0021, 0x1020, "IS");
+      fileH->InsertEntryString(str.str(),    0x0021, 0x1040, "IS");
+
+      // Pixel Size
+      /// \TODO Ask user to supply 'Pixel Size' value
+      float pxSzX = 1.0;
+      float pxSzY = 1.0;
+
+      // Field of view
+      char fov[64];
+      sprintf(fov, "%f\\%f",nX*pxSzX, nY*pxSzY);
+      fileH->InsertEntryString(fov, 0x0019, 0x1000, "DS");
+
+
+// Set the image Pixel Data
+   fileH->SetImageData(planePixelsOut,singlePlaneDataSize);
+
+// Set the writting mode and write the image
+   fileH->SetWriteModeToRaw();
+   
+   
+
+ // Write a DICOM Explicit VR file
+   fileH->SetWriteTypeToDcmExplVR();
+
+
+   outputFileName = strDirNameout +  GDCM_NAME_SPACE::GDCM_FILESEPARATOR + *it + "_ForInTag.dcm";
+   if( !fileH->Write(outputFileName ) )
+   {
+      std::cout << "Failed for [" << outputFileName << "]\n"
+                << "           File is unwrittable\n";
+   }
+
+// End of :    for (GDCM_NAME_SPACE::DirListType::iterator it = fileNames.begin() ... 
+
+
+  
+   fileH->Delete();
+
+   delete[] pixels;
+   delete[] planePixelsOut;
+  }
+*/
+  // return 1;
+ } // end of : for (GDCM_NAME_SPACE::DirListType::iterator it
+
+
+
+void DealWithNiveau1(std::string level1Directory){
+
+   GDCM_NAME_SPACE::DirList dirList(level1Directory, false, true); // DON'T get recursively the list of files
+
+   GDCM_NAME_SPACE::DirListType fileNames;
+   fileNames = dirList.GetFilenames();
+   // -----------------------------------------------------
+   // Iterate to ALL the objets(files/directories) found in the input directory
+   // -----------------------------------------------------
+   GDCM_NAME_SPACE::DirListType::iterator it;
+   
+   for (it = fileNames.begin();
+        it != fileNames.end();
+      ++it)
+   {
+      if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(*it) )
+      { 
+         std::cout << "--- [" << *it << "] is a file" << std::endl;
+      }
+      
+   }
+   
+    for (it = fileNames.begin();
+         it != fileNames.end();
+       ++it)
+   {
+      if ( GDCM_NAME_SPACE::DirList::IsDirectory(*it) )
+      { 
+         std::cout << "--- [" << *it << "] is a directory" << std::endl;
+         DealWithNiveau2(*it);
+      }
+   }
+}
+
+
+void DealWithNiveau2(std::string level2Directory){
+
+   GDCM_NAME_SPACE::DirList dirList(level2Directory, false, true); // DON'T get recursively the list of files
+
+   GDCM_NAME_SPACE::DirListType fileNames;
+   fileNames = dirList.GetFilenames();
+
+   // -----------------------------------------------------
+   // Iterate to ALL the objets(files/directories) found in the input directory
+   // -----------------------------------------------------
+   GDCM_NAME_SPACE::DirListType::iterator it;
+   
+   for (it = fileNames.begin();
+        it != fileNames.end();
+      ++it)
+   {
+      if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(*it) )
+      { 
+         std::cout << "--- --- [" << *it << "] is a file" << std::endl;
+      }
+      
+   }
+   
+   for (it = fileNames.begin();
+         it != fileNames.end();
+       ++it)
+   {
+      if ( GDCM_NAME_SPACE::DirList::IsDirectory(*it) )
+      { 
+         std::cout << "--- --- [" << *it << "] is a directory" << std::endl;
+         DealWithNiveau3(*it);
+      }
+    }
+}
+
+
+void DealWithNiveau3(std::string level3Directory){
+
+   GDCM_NAME_SPACE::DirList dirList(level3Directory, false, true); // DON'T get recursively the list of files
+
+   GDCM_NAME_SPACE::DirListType fileNames;
+   fileNames = dirList.GetFilenames();
+
+   // -----------------------------------------------------
+   // Iterate fo ALL the directories found in the input directory
+   // -----------------------------------------------------
+
+   for (GDCM_NAME_SPACE::DirListType::iterator it = fileNames.begin();
+                                    it != fileNames.end();
+                                  ++it)
+   {
+
+      if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(*it) )
+      {
+         std::cout << "--- --- --- [" << *it << "] is a file" << std::endl;
+      }
+      else
+      {
+         std::cout << "--- --- --- [" << *it << "] is a directory" << std::endl;
+      
+      }
+    }
+}
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;
+}
diff --git a/Example/exExplorePresentationState.cxx b/Example/exExplorePresentationState.cxx
new file mode 100644 (file)
index 0000000..16a2e3d
--- /dev/null
@@ -0,0 +1,570 @@
+ /*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: exExplorePresentationState.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 "gdcmArgMgr.h"
+
+#include "gdcmSeqEntry.h"
+#include "gdcmSQItem.h"
+#include "gdcmDocEntrySet.h"
+//#include "gdcmSerieHelper.h"
+#include "gdcmDirList.h"
+#include "gdcmUtil.h"
+
+typedef struct {
+       // 0020|0013 [IS]  [Instance Number]
+       std::string referencedInstanceNumber;
+       // 0004|1500 [CS] [Referenced File ID]
+       std::string referencedFileName;
+} FILEINFO;
+
+
+  GDCM_NAME_SPACE::SeqEntry *CheckIfSequenceExists(GDCM_NAME_SPACE::File *fPS,  uint16_t gr, uint16_t el);
+  GDCM_NAME_SPACE::SeqEntry *CheckIfSequenceExists(GDCM_NAME_SPACE::SQItem *si, uint16_t gr, uint16_t el); 
+  bool dealWithCurrentFile(const char *PSName);
+  bool dealWithTopLevelItem(GDCM_NAME_SPACE::SQItem* currentItem);
+  bool dealWithEndLevelItem(GDCM_NAME_SPACE::SQItem* currentItem);
+  void displaySeekResult(GDCM_NAME_SPACE::SeqEntry* currentItem, uint16_t g, uint16_t e);
+  bool dealWithSequence(GDCM_NAME_SPACE::SeqEntry* se);
+  std::string dealWithReferencedFile(GDCM_NAME_SPACE::SQItem *si);
+  std::map<std::string, FILEINFO> dealWithDicomDir(const char *dicomdirname);
+    
+bool verbose;
+bool PSNameAlreadyShown;
+std::map<std::string, FILEINFO> m;
+std::string currentPSFileName;
+
+   
+int main(int argc, char *argv[])
+{
+   START_USAGE(usage)
+   "\n exExplorePresentationState :\n    ",
+   FINISH_USAGE
+   
+
+   // ----- Initialize Arguments Manager ------
+  
+   GDCM_NAME_SPACE::ArgMgr *am = new GDCM_NAME_SPACE::ArgMgr(argc, argv);
+  
+   if (am->ArgMgrDefined("usage") || argc == 1) 
+   {
+      am->ArgMgrUsage(usage); // Display 'usage'
+      delete am;
+      return 0;
+   }
+   
+   if (am->ArgMgrDefined("debug"))
+      GDCM_NAME_SPACE::Debug::DebugOn();
+
+   /*bool */verbose = am->ArgMgrDefined("verbose");
+   bool rec  = ( 0 != am->ArgMgrDefined("rec") );
+      
+   const char *dirName  = am->ArgMgrGetString("dirin");
+   const char *dicomdirname = am->ArgMgrGetString("dicomdir");
+      
+   /* if unused Param we give up */
+   if ( am->ArgMgrPrintUnusedLabels() )
+   {
+      am->ArgMgrUsage(usage);
+      delete am;
+      return 0;
+   }  
+   delete am;  // ------ we don't need Arguments Manager any longer ------
+   
+     // ===========================================================================
+     // ========================= Deal with the relevant DICOMDIR =================
+     // ===========================================================================
+   
+   
+      /*std::map<std::string, std::string> */ m = dealWithDicomDir(dicomdirname);   
+
+     // ===========================================================================
+     // ========================= Deal with the Directory holding DICOM images   ==
+     // ===========================================================================
+
+      std::cout << " Image Directory Name [" << dirName << "]\n\n" << std::endl;
+      
+      GDCM_NAME_SPACE::DirList dirList(dirName,rec); // 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;
+      }
+      
+      for( GDCM_NAME_SPACE::DirListType::iterator it  = fileList.begin();
+                                 it != fileList.end();
+                                 ++it )
+      {
+      
+         currentPSFileName = it->c_str();
+         if (verbose)
+            std::cout << std::endl<<" Start processing :[" << it->c_str() << "]"
+                      << std::endl;
+         f = GDCM_NAME_SPACE::File::New();
+         //f->SetLoadMode(loadMode);
+         f->SetFileName( it->c_str() );
+         res = f->GDCM_NAME_SPACE::Document::Load();
+
+         if ( !res )
+         {
+            if (verbose)
+            { 
+               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;
+         }
+         bool resFile = dealWithCurrentFile(it->c_str());
+         if (verbose)
+           std::cout << "\n\n"  <<std::endl;
+         //std::cout << "=====================================================[" <<  it->c_str() << "]==" << resFile << std::endl;
+         //return resFile;
+         continue;
+      }
+}
+
+
+
+//----------------------------------------------------------------------------------------------------
+bool dealWithCurrentFile(const char *PSName)
+{
+
+   GDCM_NAME_SPACE::File *fPS = GDCM_NAME_SPACE::File::New( );
+   fPS->SetFileName( PSName );
+   fPS->SetMaxSizeLoadEntry(0xffff);
+   bool res2 = fPS->Load();
+           
+   if (!res2) {
+      if (verbose)
+          std::cout << "Sorry, " << PSName << " not a gdcm-readable "
+                    << "DICOM / ACR File"
+                    << std::endl;
+      fPS->Delete();
+      return false;
+   }
+   
+   GDCM_NAME_SPACE::SeqEntry *se;
+   
+   se = CheckIfSequenceExists( fPS, 0x0070, 0x0001);
+   //displaySeekResult(se, 0x0070, 0x0001);
+   if (!se)
+   {
+         if (verbose)
+            std::cout << "[" << PSName << "] : Hopeless (" << std::hex <<  0x0070 << "|" << 0x0001 << std::dec << " doesn't exist...)" <<std::endl;
+         return false;      
+   }
+   
+   if (verbose){   
+      std::cout << "\n\n =========================================================================================" <<std::endl;       
+      std::cout << "[" << PSName << "] is a gdcm-readable PresentationState file, "
+                << "that (probabely?) holds one or more 'ROI' within [0070|0001] (Graphic Annotation Sequence)"   <<std::endl; 
+      std::cout << " =========================================================================================\n\n" <<std::endl;
+   }
+   GDCM_NAME_SPACE::SQItem* currentItem = se->GetFirstSQItem(); // Get the first 'ROI'
+   if (currentItem == NULL)
+   {
+      if (verbose)
+         std::cout << "======== Deal With NOTHING! (Sequence 0070|0001 [Graphic Annotation Sequence] has NO item ?!?) within " 
+                 << PSName << "]" << std::endl;
+      return false;
+   }
+   int i =0;
+   bool res3;
+   bool finalRes = false;
+   while (currentItem != NULL)
+   {
+      if (verbose)
+        std::cout << "======== Deal With 'ROI' n." << i << std::endl;
+
+        // do what you want with the current 'ROI'
+         res3 = dealWithTopLevelItem(currentItem);
+       if (res3)
+         finalRes = true;
+        //...
+
+        currentItem = se->GetNextSQItem(); // Get the next 'ROI'
+        i++;
+   }
+
+   if (finalRes)
+      std::cout << "=============================(within PS File :[" <<  PSName << "]\n\n" << std::endl;   
+   fPS->Delete();
+   
+   if(verbose)
+      std::cout << "\n\n"  <<std::endl;
+   return true;
+}
+//----------------------------------------------------------------------------------------------------
+bool dealWithTopLevelItem(GDCM_NAME_SPACE::SQItem* currentItem)
+{
+  // probably this list should be cleaned up.
+  // (I didn't find the exact architecture of Presentation State)
+   int tabElement[] = {         0x0008, 0x0009, 0x005a, 0x0060, 0x0086, 
+                        0x0308, 0x0309, 0x030A, 0x030d, 0x0311, 0x0314, 
+                        0x0318, 0x031c, 0x031e, 0x0402, 0x0404, 0x0000 };
+
+   bool finalRes = false;
+   bool res;
+   GDCM_NAME_SPACE::SeqEntry *se;
+
+   se = CheckIfSequenceExists(currentItem, 0x0008, 0x1140);
+   displaySeekResult(se, 0x0008, 0x1140); 
+   if (se != 0)
+   {
+      res = dealWithSequence(se);
+      if (!res)
+         return false;
+   }
+   
+   for(int i=0; tabElement[i]!=0x0000; i++)
+   {
+      se = CheckIfSequenceExists(currentItem, 0x0070, tabElement[i]);
+      //displaySeekResult(se, 0x0070, tabElement[i]);       
+      if (se != 0)
+      {
+         res = dealWithSequence(se);
+         if (res)
+            finalRes = true;
+      }
+   } 
+   return (finalRes);
+}
+
+
+//----------------------------------------------------------------------------------------------------
+bool dealWithEndLevelItem(GDCM_NAME_SPACE::SQItem* currentItem)
+{
+  // probably this list should be cleaned up, too.
+  // (I didn't find the exact architecture of Presentation State)
+   int tabElement[] = {         0x0008, 0x0009, 0x005a, 0x0060, 0x0086, 
+                        0x0308, 0x0309, 0x030A, 0x030d, 0x0311, 0x0314, 
+                        0x0318, 0x031c, 0x031e, 0x0402, 0x0404, 0x0000 };
+
+   bool res = false;
+   GDCM_NAME_SPACE::SeqEntry *se;
+
+   se = CheckIfSequenceExists(currentItem, 0x0008, 0x1140);
+   displaySeekResult(se, 0x0008, 0x1140); 
+   if (se != 0)
+   {
+      res = true;
+      dealWithSequence(se);
+   }
+
+   for(int i=0; tabElement[i]!=0x0000; i++)
+   {
+      se = CheckIfSequenceExists(currentItem, 0x0070, tabElement[i]);
+      displaySeekResult(se, 0x0070, tabElement[i]);       
+      if (se != 0)
+      {
+         res = true;
+         dealWithSequence(se);
+      }
+   } 
+   return (res);
+}
+//----------------------------------------------------------------------------------------------------
+
+bool dealWithSequence(GDCM_NAME_SPACE::SeqEntry* se)
+{    
+   uint16_t g = se->GetGroup();
+   uint16_t e = se->GetElement();
+   if (verbose)  
+      std::cout << std::hex << "\n------------------------ deal with " << g <<"|" << e <<  std::dec 
+                << "  " << se->GetName() << std::endl;
+
+   GDCM_NAME_SPACE::SQItem *si = se->GetFirstSQItem();
+   if (!si) {
+      if (verbose)
+         std::cout << "Sequence " << std::hex << g <<"|" << e <<  std::dec <<  "has no Item ?!?" << std::endl;
+      return false;
+   }
+   std::string referencedFileUID;
+   //std::cout << "\n============================== [" << currentPSFileName << "] =================" << std::endl;  
+   if (g == 0x0008) {
+      if (verbose)
+         si->Print(std::cout);
+      referencedFileUID = dealWithReferencedFile(si);
+//      std::cout << "   referencedFile UID[" << referencedFileUID <<"]" << std::endl;
+      
+   } else if (g == 0x0070) {
+      if (verbose)   
+         si->Print(std::cout);   
+   } else {
+        if (verbose)
+           std::cout << "Unexpected Group " << std::hex << g << std::hex << std::endl;
+   }
+   
+   si =  se->GetNextSQItem();
+   if (si)
+   {
+      if (verbose)
+         std::cout << "Sequence " << std::hex << g <<"|" << e <<  std::dec <<  "should have only ONE Item ?!?" << std::endl;
+     // if (verbose)  
+     //    si->Print(std::cout);
+      return false;
+   }
+   return true;
+}
+
+//----------------------------------------------------------------------------------------------------
+
+void displaySeekResult(GDCM_NAME_SPACE::SeqEntry* se, uint16_t g, uint16_t e)
+{  
+      if (se)
+      {
+        // std::cout << std::hex <<  g << "|" << e << std::dec << " [" << se->GetName() << "] exists" <<std::endl;
+      }
+      else
+      {
+         if (verbose)
+            std::cout << " No " << std::hex <<  g << "|" << e << std::dec << " found" <<std::endl;
+      }
+}
+      
+//----------------------------------------------------------------------------------------------------  
+
+bool TestPresentationState(GDCM_NAME_SPACE::File *f, GDCM_NAME_SPACE::File *fPS)
+{
+
+/*------------------------------------------------------
+
+0070 0001 SQ 1 Graphic Annotation Sequence
+0070 0008 SQ 1 Text Object Sequence
+0070 0009 SQ 1 Graphic Object Sequence
+0070 005a SQ 1 Displayed Area Selection Sequence
+0070 0060 SQ 1 Graphic Layer Sequence
+0070 0086 SQ 1 Content Creator's Identification Code Sequence
+0070 0308 SQ 1 Registration Sequence
+0070 0309 SQ 1 Matrix Registration Sequence
+0070 030a SQ 1 Matrix Sequence
+0070 030d SQ 1 Registration Type Code Sequence
+0070 0311 SQ 1 Fiducial Identifier Code Sequence
+0070 0314 SQ 1 Used Fiducials Sequence
+0070 0318 SQ 1 Graphic Coordinates Data Sequence
+0070 031c SQ 1 Fiducial Set Sequence
+0070 031e SQ 1 Fiducial Sequence
+0070 0402 SQ 1 Blending Sequence
+0070 0404 SQ 1 Referenced Spatial Registration Sequence
+------------------------------------------------------- */
+
+/*------------------------------------------------------
+Relevant part of Dicom V3 Dict
+
+0070 0000 UL 1 Group Length
+0070 0001 SQ 1 Graphic Annotation Sequence
+0070 0002 CS 1 Graphic Layer
+0070 0003 CS 1 Bounding Box Annotation Units
+0070 0004 CS 1 Anchor Point Annotation Units
+0070 0005 CS 1 Graphic Annotation Units
+0070 0006 ST 1 Unformatted Text Value
+0070 0008 SQ 1 Text Object Sequence
+0070 0009 SQ 1 Graphic Object Sequence
+0070 0010 FL 2 Bounding Box Top Left Hand Corner
+0070 0011 FL 2 Bounding Box Bottom Right Hand Corner
+0070 0012 CS 1 Bounding Box Text Horizontal Justification
+0070 0014 FL 2 Anchor Point
+0070 0015 CS 1 Anchor Point Visibility
+0070 0020 US 1 Graphic Dimensions
+0070 0021 US 1 Number of Graphic Points
+0070 0022 FL 2-2n Graphic Data
+0070 0023 CS 1 Graphic Type
+0070 0024 CS 1 Graphic Filled
+0070 0041 CS 1 Image Horizontal Flip
+0070 0042 US 1 Image Rotation
+0070 0052 SL 2 Displayed Area Top Left Hand Corner
+0070 0053 SL 2 Displayed Area Bottom Right Hand Corner
+0070 005a SQ 1 Displayed Area Selection Sequence
+0070 0060 SQ 1 Graphic Layer Sequence
+0070 0062 IS 1 Graphic Layer Order
+0070 0066 US 1 Graphic Layer Recommended Display Grayscale Value
+0070 0067 US 3 Graphic Layer Recommended Display RGB Value (RET)
+0070 0068 LO 1 Graphic Layer Description
+0070 0080 CS 1 Content Label
+0070 0081 LO 1 Content Description
+0070 0082 DA 1 Presentation Creation Date
+0070 0083 TM 1 Presentation Creation Time
+0070 0084 PN 1 Content Creator's Name
+0070 0086 SQ 1 Content Creator's Identification Code Sequence
+0070 0100 CS 1 Presentation Size Mode
+0070 0101 DS 2 Presentation Pixel Spacing
+0070 0102 IS 2 Presentation Pixel Aspect Ratio
+0070 0103 FL 1 Presentation Pixel Magnification Ratio
+0070 0306 CS 1 Shape Type
+0070 0308 SQ 1 Registration Sequence
+0070 0309 SQ 1 Matrix Registration Sequence
+0070 030a SQ 1 Matrix Sequence
+0070 030c CS 1 Frame of Reference Transformation Matrix Type
+0070 030d SQ 1 Registration Type Code Sequence
+0070 030f ST 1 Fiducial Description
+0070 0310 SH 1 Fiducial Identifier
+0070 0311 SQ 1 Fiducial Identifier Code Sequence
+0070 0312 FD 1 Contour Uncertainty Radius
+0070 0314 SQ 1 Used Fiducials Sequence
+0070 0318 SQ 1 Graphic Coordinates Data Sequence
+0070 031a UI 1 Fiducial UID
+0070 031c SQ 1 Fiducial Set Sequence
+0070 031e SQ 1 Fiducial Sequence
+0070 0401 US 3 Graphic Layer Recommended Display CIELab Value
+0070 0402 SQ 1 Blending Sequence
+0070 0403 FL 1 Relative Opacity
+0070 0404 SQ 1 Referenced Spatial Registration Sequence
+0070 0405 CS 1 Blending Position
+------------------------------------------------------- */
+
+}
+
+// ----------------------------------------------------------------------------------
+
+
+GDCM_NAME_SPACE::SeqEntry *CheckIfSequenceExists( GDCM_NAME_SPACE::File *fPS, uint16_t gr, uint16_t el)
+{
+   GDCM_NAME_SPACE::SeqEntry *se= fPS->GetSeqEntry(gr, el);
+   return se;     
+}
+
+// ----------------------------------------------------------------------------------
+  
+GDCM_NAME_SPACE::SeqEntry *CheckIfSequenceExists( GDCM_NAME_SPACE::SQItem *si, uint16_t gr, uint16_t el)
+{
+   GDCM_NAME_SPACE::SeqEntry *se= si->GetSeqEntry(gr, el);
+   return se;     
+}
+
+// ----------------------------------------------------------------------------------
+
+std::string dealWithReferencedFile(GDCM_NAME_SPACE::SQItem *si)
+{
+  // GDCM_NAME_SPACE::DocEntry *si = GetDocEntry(0x0008, 0x1155);
+  
+  // Look for : 0004|1511  [UI]  [Referenced SOP Instance UID in File]  
+  std::string referencedFileUID = si->GetEntryString(0x0008, 0x1155);
+  // std::cout << "   referencedFile UID[" << referencedFileUID <<"]" << std::endl;
+      
+  if (verbose)
+     std::cout << "m[" << referencedFileUID << "] = ";
+
+  std::cout << "[" << m[referencedFileUID].referencedInstanceNumber << "] [" << m[referencedFileUID].referencedFileName << "]" << std::endl;
+
+  return referencedFileUID;
+   
+}  
+
+// ----------------------------------------------------------------------------------
+std::map<std::string, FILEINFO> dealWithDicomDir(const char *dicomdirname)
+{
+   FILEINFO fi;
+   GDCM_NAME_SPACE::File *f;
+   bool res;
+   std::map<std::string, FILEINFO> m;
+         
+         std::cout << std::endl<<" Start reading DICOMDIR :[" << dicomdirname << "]"
+                   << std::endl;
+   
+         f = GDCM_NAME_SPACE::File::New();
+         //f->SetLoadMode(loadMode);
+         f->SetFileName( dicomdirname );
+         // Don't load a DicomDir !
+         res = f->GDCM_NAME_SPACE::Document::Load();
+
+         if ( !res )
+         {
+            std::cout << "Cannot process file [" << dicomdirname << "]" 
+                      << 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();
+            /// \TODO : throw an exception
+            return m;;
+         }
+
+   // Get 0004|1220 [SQ]  [Directory Record Sequence]
+   
+   GDCM_NAME_SPACE::SeqEntry *dsr= f->GetSeqEntry(0x0004,0x1220);
+   if (!dsr)
+   {
+         if (verbose)
+            std::cout << "[" << dicomdirname << "] : Hopeless (" << std::hex <<  0x0094 << "|" << 0x01220 
+                    << std::dec << " -Directory Record Sequence- doesn't exist...)" <<std::endl;
+
+         f->Delete();
+       /// \TODO : throw an exception
+         return m;      
+   }
+
+   GDCM_NAME_SPACE::SQItem* currentItem = dsr->GetFirstSQItem(); // Get the first 'ROI'
+   if (currentItem == NULL)
+   {
+      if (verbose)
+         std::cout << "======== Deal With NOTHING! (Sequence 0004|1220 [Directory Record Sequence] has NO item ?!?)" << std::endl;
+       /// \TODO : throw an exception
+         return m;   
+   }
+  
+   int i =0;
+   while (currentItem != NULL)
+   {
+       // Get 0020|0013 [IS]  [Instance Number]
+       fi.referencedInstanceNumber = currentItem->GetEntryString(0x0020, 0x0013);
+  
+       // Get 0004|1500 [CS] [Referenced File ID]
+       fi.referencedFileName = currentItem->GetEntryString(0x0004, 0x1500);
+
+       // Get0004|1511 [UI] [Referenced SOP Instance UID in File] 
+       std::string referencedFileSopInstanceUID = currentItem->GetEntryString(0x0004, 0x1511);
+
+       m[referencedFileSopInstanceUID] = fi;
+       currentItem = dsr->GetNextSQItem(); // Get the next 'ROI'
+       i++;
+   }
+
+   if (verbose)   
+      for(std::map<std::string, FILEINFO>::iterator it = m.begin(); it != m.end(); ++it)
+      {
+         std::cout << "m[" << (*it).first << "] = [" << (*it).second.referencedInstanceNumber << "] ["  << (*it).second.referencedFileName << std::endl;
+      }
+ return m;  
+
+}