]> Creatis software - gdcm.git/commitdiff
* vtk/vtkGdcmReader[cxx|h] preparation addons for loading volumes.
authorfrog <frog>
Thu, 29 May 2003 16:58:24 +0000 (16:58 +0000)
committerfrog <frog>
Thu, 29 May 2003 16:58:24 +0000 (16:58 +0000)
ChangeLog
vtk/vtkGdcmReader.cxx
vtk/vtkGdcmReader.h

index 1f1948d3ddac06ab58819c2b8a396fa57895105a..8030bc988a8bb999ec3f016320ca55030700fd85 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,6 @@
+2003-05-29  Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * vtk/vtkGdcmReader[cxx|h] preparation addons for loading volumes.
+
 2003-05-28  Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
       * When compiling with distutils (see setup.py) the C++ compiler is
         called with different flags than the default ones (with automake).
index a8672163d4ba108df6f3fa6b833ece59fe5bcaf6..b9324dcbbeea3127e26b85daf9ea9c06233fdb9a 100644 (file)
@@ -1,4 +1,4 @@
-// $Header: /cvs/public/gdcm/vtk/vtkGdcmReader.cxx,v 1.5 2003/05/28 19:36:21 frog Exp $
+// $Header: /cvs/public/gdcm/vtk/vtkGdcmReader.cxx,v 1.6 2003/05/29 16:58:24 frog Exp $
 //CLEANME#include <vtkByteSwap.h>
 #include <stdio.h>
 #include <vtkObjectFactory.h>
@@ -18,6 +18,157 @@ vtkGdcmReader::~vtkGdcmReader()
   // FIXME free memory
 }
 
+//----------------------------------------------------------------------------
+// Adds a file name to the list of images to read.
+void vtkGdcmReader::AddFileName(const char* name)
+{
+   // We need to bypass the const pointer [since list<>.push_bash() only
+   // takes a char* (but not a const char*)] by making a local copy:
+   char * LocalName = new char[strlen(name) + 1];
+   strcpy(LocalName, name);
+   this->FileNameList.push_back(LocalName);
+   // Starting from two files we have a stack of images:
+   if(this->FileNameList.size() >= 2)
+      this->SetFileDimensionality(3);
+}
+
+//----------------------------------------------------------------------------
+// Sets up a filename to be read.
+void vtkGdcmReader::SetFileName(const char *name) {
+   vtkImageReader2::SetFileName(name);
+   // Since we maintain a list of filenames (when building a volume)
+   // we additionaly need to maintain this list. First we clean-up the
+   // list and then positionate the incoming filename:
+   this->FileNameList.empty();
+   this->AddFileName(name);
+}
+
+//----------------------------------------------------------------------------
+// vtkGdcmReader can have the file names specified through two ways:
+// (1) by calling the vtkImageReader2::SetFileName(), SetFilePrefix() and
+//     SetFilePattern()
+// (2) By successive calls to vtkGdcmReader::SetFileName()
+// When the first method was used by caller we need to update the local
+// filename list
+void vtkGdcmReader::BuilFileListFromPattern()
+{
+   if (! this->FileNameList.empty())
+      return;
+   if (!this->FileName && !this->FilePattern)
+     {
+     vtkErrorMacro("FileNames are not set. Either use AddFileName() or");
+     vtkErrorMacro("specify a FileName or FilePattern.");
+     return;
+     }
+   for (int idx = this->DataExtent[4]; idx <= this->DataExtent[5]; ++idx)
+     {
+     this->ComputeInternalFileName(idx);
+     vtkDebugMacro("Adding file " << this->InternalFileName);
+     this->AddFileName(this->InternalFileName);
+     }
+}
+
+//----------------------------------------------------------------------------
+// When more than one filename is specified (i.e. we expect loading
+// a stack or volume) we need to check the corresponding images are
+// coherent:
+//  - they all share the same X dimensions
+//  - they all share the same Y dimensions
+//  - each file a Z dimension of 1
+//  - they all share the same type ( 8 bit signed, or unsigned...)
+bool vtkGdcmReader::CheckFileCoherence()
+{
+   this->BuilFileListFromPattern();
+   if (this->FileNameList.empty())
+     {
+     vtkErrorMacro("FileNames are not set.");
+     return false;
+     }
+   if (this->FileNameList.size() == 1)
+     {
+     vtkDebugMacro("Single file specified.");
+     return true;
+     }
+
+   // Loop on the filenames:
+   // - check for their existence and gdcm "parasability"
+   // - get the coherence check done:
+   bool FoundReferenceFile = false;
+   int ReferenceNX;
+   int ReferenceNY;
+   int ReferenceNZ;
+   std::string ReferenceType;
+   for (std::list<std::string>::iterator FileName  = FileNameList.begin();
+                                        FileName != FileNameList.end();
+                                      ++FileName)
+     {
+     // Check for file existence.
+     FILE *fp;
+     fp = fopen(FileName->c_str(),"rb");
+     if (!fp)
+       {
+       vtkErrorMacro("Unable to open file " << *FileName);
+       vtkErrorMacro("Removing this file from readed files " << *FileName);
+       FileNameList.remove(*FileName);
+       continue;
+       }
+     fclose(fp);
+   
+     // Check for Gdcm parsability
+     gdcmHeader GdcmHeader(FileName->c_str());
+     if (!GdcmHeader.IsReadable())
+       {
+       vtkErrorMacro("Gdcm cannot parse file " << *FileName);
+       vtkErrorMacro("Removing this file from readed files " << *FileName);
+       FileNameList.remove(*FileName);
+       continue;
+       }
+
+     // Coherence stage:
+     int NX = GdcmHeader.GetXSize();
+     int NY = GdcmHeader.GetYSize();
+     int NZ = GdcmHeader.GetZSize();
+     std::string type = GdcmHeader.GetPixelType();
+     if (FoundReferenceFile) 
+       {
+       if (   ( NX != ReferenceNX )
+           || ( NY != ReferenceNY )
+           || ( NZ != ReferenceNZ )
+           || ( type != ReferenceType ) ) 
+         {
+            vtkErrorMacro("This file is not coherent with previous ones"
+                          << *FileName);
+            vtkErrorMacro("Removing this file from readed files " << *FileName);
+            FileNameList.remove(*FileName);
+            continue;
+         } else {
+            vtkDebugMacro("File is coherent with previous ones" << *FileName);
+         }
+       } else {
+         // This file shall be the reference:
+         FoundReferenceFile = true;
+         ReferenceNX = NX;
+         ReferenceNY = NY;
+         ReferenceNZ = NZ;
+         ReferenceType = type;
+         vtkDebugMacro("File is taken a coherence references" << *FileName);
+       }
+     } // End of loop on FileName
+
+   if (this->FileNameList.empty())
+     {
+     vtkDebugMacro("No gdcm parsable file.");
+     return false;
+     }
+   if (this->FileNameList.size() == 1)
+     {
+     vtkDebugMacro("Single parsable file left after coherence test.");
+     return true;
+     }
+   return true;
+}
+
+//----------------------------------------------------------------------------
 // Configure the output e.g. WholeExtent, spacing, origin, scalar type...
 void vtkGdcmReader::ExecuteInformation()
 {
@@ -96,9 +247,8 @@ void vtkGdcmReader::ExecuteInformation()
   
   // We don't need to positionate the Endian related stuff (by using
   // this->SetDataByteOrderToBigEndian() or SetDataByteOrderToLittleEndian()
-  // since the // reading of the file is done by gdcm
-
-  // But we need to set up the data type for downstream filters:
+  // since the reading of the file is done by gdcm.
+  // But we do need to set up the data type for downstream filters:
   std::string type = GdcmHeader.GetPixelType();
   if      ( type == "8U" )
     {
@@ -142,6 +292,7 @@ void vtkGdcmReader::ExecuteInformation()
   vtkImageReader::ExecuteInformation();
 }
 
+//----------------------------------------------------------------------------
 // Update -> UpdateData -> Execute -> ExecuteData (see vtkSource.cxx for
 // last step.
 // This function (redefinition of vtkImageReader::ExecuteData, see 
@@ -199,8 +350,16 @@ void vtkGdcmReader::ExecuteData(vtkDataObject *output)
 
 }
 
+//----------------------------------------------------------------------------
 void vtkGdcmReader::PrintSelf(ostream& os, vtkIndent indent)
 {
   vtkImageReader::PrintSelf(os,indent);
-  //CLEANME os << indent << "TypeSize: " << this->TypeSize << "\n";
+  os << indent << "Filenames  : " << endl;
+  vtkIndent nextIndent = indent.GetNextIndent();
+  for (std::list<std::string>::iterator FileName  = FileNameList.begin();
+                                        FileName != FileNameList.end();
+                                      ++FileName)
+    {
+    os << nextIndent << *FileName << endl ;
+    }
 }
index 20eb484ae39be6a701fe9e69bccf4a140f469eca..dbcd0faeb24314f4551f4908402897f4e98c3bb8 100644 (file)
@@ -1,8 +1,10 @@
-// $Header: /cvs/public/gdcm/vtk/vtkGdcmReader.h,v 1.1 2003/05/05 14:13:59 frog Exp $
+// $Header: /cvs/public/gdcm/vtk/vtkGdcmReader.h,v 1.2 2003/05/29 16:58:24 frog Exp $
 
 #ifndef __vtkGdcmReader_h
 #define __vtkGdcmReader_h
 
+#include <list>
+#include <string>
 #include "vtkImageReader.h"
 
 class VTK_EXPORT vtkGdcmReader : public vtkImageReader
@@ -11,11 +13,20 @@ public:
   static vtkGdcmReader *New() {return new vtkGdcmReader;};
   vtkTypeMacro(vtkGdcmReader, vtkImageReader);
   void PrintSelf(ostream& os, vtkIndent indent);
+  void AddFileName(const char* name);
+  void SetFileName(const char *name);
 protected:
   vtkGdcmReader();
   ~vtkGdcmReader();
-  void ExecuteData(vtkDataObject *output);
   virtual void ExecuteInformation();
+  void ExecuteData(vtkDataObject *output);
+  void BuilFileListFromPattern();
+  bool CheckFileCoherence();
+  // List of filenames to be read in order to build a stack of images
+  // or volume. The order in the list shall be the order of the images.
+  //BTX
+  std::list<std::string> FileNameList;
+  //ETX
 };
 #endif