]> Creatis software - gdcm.git/blobdiff - vtk/vtkGdcmReader.cxx
EMH: *Add PrintAllDocument, dog slow right now
[gdcm.git] / vtk / vtkGdcmReader.cxx
index 89ff5dc0dec821835bfda402993df1448c810520..11d9f68076f835e9ec4a2a770822ae1ffe973d20 100644 (file)
 //  2a/ ExecuteData calls AllocateOutputData that in turn seems to 
 //      (indirectely call) ExecuteInformation which ends up in a second
 //      header parsing
+//      This is fixed by adding a test at the beginning of ExecuteInformation
+//      on the modification of the object instance. If a modification have been
+//      made (method Modified() ), the MTime value is increased. The fileTime
+//      is compared to this new value to find a modification in the class
+//      parameters
 //  2b/ the core of ExecuteData then needs gdcmFile (which in turns
 //      initialises gdcmHeader in the constructor) in order to access
 //      the data-image.
 #include <vtkPointData.h>
 #include <vtkLookupTable.h>
 
+vtkCxxRevisionMacro(vtkGdcmReader, "$Revision: 1.46 $");
+vtkStandardNewMacro(vtkGdcmReader);
+
 //-----------------------------------------------------------------------------
 // Constructor / Destructor
 vtkGdcmReader::vtkGdcmReader()
 {
    this->LookupTable = NULL;
+   this->AllowLookupTable = 0;
 }
 
 vtkGdcmReader::~vtkGdcmReader()
@@ -91,6 +100,7 @@ void vtkGdcmReader::PrintSelf(ostream& os, vtkIndent indent)
 void vtkGdcmReader::RemoveAllFileName(void)
 {
    this->FileNameList.clear();
+   this->Modified();
 }
 
 /*
@@ -103,8 +113,8 @@ void vtkGdcmReader::AddFileName(const char* name)
    char * LocalName = new char[strlen(name) + 1];
    strcpy(LocalName, name);
    this->FileNameList.push_back(LocalName);
-   this->Modified();
    delete[] LocalName;
+   this->Modified();
 }
 
 /*
@@ -116,6 +126,7 @@ void vtkGdcmReader::SetFileName(const char *name)
    // Since we maintain a list of filenames, when building a volume,
    // (see vtkGdcmReader::AddFileName), we additionaly need to purge
    // this list when we manually positionate the filename.
+   vtkDebugMacro("Clearing all files given with AddFileName");
    this->FileNameList.clear();
    this->Modified();
 }
@@ -127,95 +138,100 @@ void vtkGdcmReader::SetFileName(const char *name)
  */
 void vtkGdcmReader::ExecuteInformation()
 {
-   this->TotalNumberOfPlanes = this->CheckFileCoherence();
-   if ( this->TotalNumberOfPlanes == 0)
+   if(this->MTime>this->fileTime)
    {
-      vtkErrorMacro("File set is not coherent. Exiting...");
-      return;
-   }
+      this->TotalNumberOfPlanes = this->CheckFileCoherence();
+      if ( this->TotalNumberOfPlanes == 0)
+      {
+         vtkErrorMacro("File set is not coherent. Exiting...");
+         return;
+      }
       
-   // if the user has not set the extent, but has set the VOI
-   // set the z axis extent to the VOI z axis
-   if (this->DataExtent[4]==0 && this->DataExtent[5] == 0 &&
-   (this->DataVOI[4] || this->DataVOI[5]))
-   {
-      this->DataExtent[4] = this->DataVOI[4];
-      this->DataExtent[5] = this->DataVOI[5];
-   }
-
-   // When the user has set the VOI, check it's coherence with the file content.
-   if (this->DataVOI[0] || this->DataVOI[1] || 
-   this->DataVOI[2] || this->DataVOI[3] ||
-   this->DataVOI[4] || this->DataVOI[5])
-   { 
-      if ((this->DataVOI[0] < 0) ||
-          (this->DataVOI[1] >= this->NumColumns) ||
-          (this->DataVOI[2] < 0) ||
-          (this->DataVOI[3] >= this->NumLines) ||
-          (this->DataVOI[4] < 0) ||
-          (this->DataVOI[5] >= this->TotalNumberOfPlanes ))
+      // if the user has not set the extent, but has set the VOI
+      // set the z axis extent to the VOI z axis
+      if (this->DataExtent[4]==0 && this->DataExtent[5] == 0 &&
+      (this->DataVOI[4] || this->DataVOI[5]))
       {
-         vtkWarningMacro("The requested VOI is larger than expected extent.");
-         this->DataVOI[0] = 0;
-         this->DataVOI[1] = this->NumColumns - 1;
-         this->DataVOI[2] = 0;
-         this->DataVOI[3] = this->NumLines - 1;
-         this->DataVOI[4] = 0;
-         this->DataVOI[5] = this->TotalNumberOfPlanes - 1;
+         this->DataExtent[4] = this->DataVOI[4];
+         this->DataExtent[5] = this->DataVOI[5];
+      }
+
+      // When the user has set the VOI, check it's coherence with the file content.
+      if (this->DataVOI[0] || this->DataVOI[1] || 
+      this->DataVOI[2] || this->DataVOI[3] ||
+      this->DataVOI[4] || this->DataVOI[5])
+      { 
+         if ((this->DataVOI[0] < 0) ||
+             (this->DataVOI[1] >= this->NumColumns) ||
+             (this->DataVOI[2] < 0) ||
+             (this->DataVOI[3] >= this->NumLines) ||
+             (this->DataVOI[4] < 0) ||
+             (this->DataVOI[5] >= this->TotalNumberOfPlanes ))
+         {
+            vtkWarningMacro("The requested VOI is larger than expected extent.");
+            this->DataVOI[0] = 0;
+            this->DataVOI[1] = this->NumColumns - 1;
+            this->DataVOI[2] = 0;
+            this->DataVOI[3] = this->NumLines - 1;
+            this->DataVOI[4] = 0;
+            this->DataVOI[5] = this->TotalNumberOfPlanes - 1;
+         }
       }
-   }
 
-   // Positionate the Extent.
-   this->DataExtent[0] = 0;
-   this->DataExtent[1] = this->NumColumns - 1;
-   this->DataExtent[2] = 0;
-   this->DataExtent[3] = this->NumLines - 1;
-   this->DataExtent[4] = 0;
-   this->DataExtent[5] = this->TotalNumberOfPlanes - 1;
+      // Positionate the Extent.
+      this->DataExtent[0] = 0;
+      this->DataExtent[1] = this->NumColumns - 1;
+      this->DataExtent[2] = 0;
+      this->DataExtent[3] = this->NumLines - 1;
+      this->DataExtent[4] = 0;
+      this->DataExtent[5] = this->TotalNumberOfPlanes - 1;
   
-   // 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 do need to set up the data type for downstream filters:
-   if      ( ImageType == "8U" )
-   {
-      vtkDebugMacro("8 bits unsigned image");
-      this->SetDataScalarTypeToUnsignedChar(); 
-   }
-   else if ( ImageType == "8S" )
-   {
-      vtkErrorMacro("Cannot handle 8 bit signed files");
-      return;
-   }
-   else if ( ImageType == "16U" )
-   {
-      vtkDebugMacro("16 bits unsigned image");
-      this->SetDataScalarTypeToUnsignedShort();
-   }
-   else if ( ImageType == "16S" )
-   {
-      vtkDebugMacro("16 bits signed image");
-      this->SetDataScalarTypeToShort();
-      //vtkErrorMacro("Cannot handle 16 bit signed files");
-   }
-   else if ( ImageType == "32U" )
-   {
-      vtkDebugMacro("32 bits unsigned image");
-      vtkDebugMacro("WARNING: forced to signed int !");
-      this->SetDataScalarTypeToInt();
-   }
-   else if ( ImageType == "32S" )
-   {
-      vtkDebugMacro("32 bits signed image");
-      this->SetDataScalarTypeToInt();
-   }
-   else if ( ImageType == "FD" )
-   {
-      vtkDebugMacro("64 bits Double image");
-      this->SetDataScalarTypeToDouble();
+      // 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 do need to set up the data type for downstream filters:
+      if      ( ImageType == "8U" )
+      {
+         vtkDebugMacro("8 bits unsigned image");
+         this->SetDataScalarTypeToUnsignedChar(); 
+      }
+      else if ( ImageType == "8S" )
+      {
+         vtkErrorMacro("Cannot handle 8 bit signed files");
+         return;
+      }
+      else if ( ImageType == "16U" )
+      {
+         vtkDebugMacro("16 bits unsigned image");
+         this->SetDataScalarTypeToUnsignedShort();
+      }
+      else if ( ImageType == "16S" )
+      {
+         vtkDebugMacro("16 bits signed image");
+         this->SetDataScalarTypeToShort();
+         //vtkErrorMacro("Cannot handle 16 bit signed files");
+      }
+      else if ( ImageType == "32U" )
+      {
+         vtkDebugMacro("32 bits unsigned image");
+         vtkDebugMacro("WARNING: forced to signed int !");
+         this->SetDataScalarTypeToInt();
+      }
+      else if ( ImageType == "32S" )
+      {
+         vtkDebugMacro("32 bits signed image");
+         this->SetDataScalarTypeToInt();
+      }
+      else if ( ImageType == "FD" )
+      {
+         vtkDebugMacro("64 bits Double image");
+         this->SetDataScalarTypeToDouble();
+      }
+      //Set number of scalar components:
+      this->SetNumberOfScalarComponents(this->NumComponents);
+
+      this->fileTime=this->MTime;
    }
-   //Set number of scalar components:
-   this->SetNumberOfScalarComponents(this->NumComponents);
 
    this->Superclass::ExecuteInformation();
 }
@@ -248,9 +264,9 @@ void vtkGdcmReader::ExecuteData(vtkDataObject *output)
    {
       // The memory size for a full stack of images of course depends
       // on the number of planes and the size of each image:
-      size_t StackNumPixels = this->NumColumns * this->NumLines
-                            * this->TotalNumberOfPlanes * this->NumComponents;
-      size_t stack_size = StackNumPixels * this->PixelSize;
+      //size_t StackNumPixels = this->NumColumns * this->NumLines
+      //                      * this->TotalNumberOfPlanes * this->NumComponents;
+      //size_t stack_size = StackNumPixels * this->PixelSize; //not used
       // Allocate pixel data space itself.
 
       // Variables for the UpdateProgress. We shall use 50 steps to signify
@@ -308,10 +324,26 @@ void vtkGdcmReader::ExecuteData(vtkDataObject *output)
  */
 void vtkGdcmReader::BuildFileListFromPattern()
 {
+   this->RemoveAllInternalFileName();
+
    if ((! this->FileNameList.empty()) && this->FileName )
    {
-      vtkErrorMacro("Both file patterns and AddFileName schemes were used");
-      vtkErrorMacro("Only the files specified with AddFileName shall be used");
+      vtkErrorMacro("Both AddFileName and SetFileName schemes were used");
+      vtkErrorMacro("No images loaded ! ");
+      return;
+   }
+
+   if ((! this->FileNameList.empty()) && this->FilePrefix )
+   {
+      vtkErrorMacro("Both AddFileName and SetFilePrefix schemes were used");
+      vtkErrorMacro("No images loaded ! ");
+      return;
+   }
+
+   if (this->FileName && this->FilePrefix)
+   {
+      vtkErrorMacro("Both SetFileName and SetFilePrefix schemes were used");
+      vtkErrorMacro("No images loaded ! ");
       return;
    }
 
@@ -322,24 +354,24 @@ void vtkGdcmReader::BuildFileListFromPattern()
       return;
    }
 
-   if (!this->FileName && !this->FilePattern)
+   if (!this->FileName && !this->FilePrefix)
    {
       vtkErrorMacro("FileNames are not set. Either use AddFileName() or");
-      vtkErrorMacro("specify a FileName or FilePattern.");
+      vtkErrorMacro("specify a FileName or FilePrefix.");
       return;
    }
 
-   this->RemoveAllInternalFileName();
-   if( this->FileNameList.empty() )
+   if( this->FileName )
    {
-      //Multiframe case:
+      // Single file loading (as given with ::SetFileName()):
+      // Case of multi-frame file considered here
       this->ComputeInternalFileName(this->DataExtent[4]);
       vtkDebugMacro("Adding file " << this->InternalFileName);
       this->AddInternalFileName(this->InternalFileName);
    }
    else
    {
-      //stack of 2D dicom case:
+      // Multi file loading (as given with ::SetFilePattern()):
       for (int idx = this->DataExtent[4]; idx <= this->DataExtent[5]; ++idx)
       {
          this->ComputeInternalFileName(idx);
@@ -410,9 +442,10 @@ int vtkGdcmReader::CheckFileCoherence()
          continue;
       }
       fclose(fp);
-   
+
       // Stage 1.2: check for Gdcm parsability
-      gdcmHeaderHelper GdcmHeader(FileName->c_str());
+      gdcmHeader GdcmHeader(FileName->c_str(), false, true);
+      //                             true : for enableSequences
       if (!GdcmHeader.IsReadable())
       {
          vtkErrorMacro("Gdcm cannot parse file " << FileName->c_str());
@@ -500,8 +533,9 @@ int vtkGdcmReader::CheckFileCoherence()
          this->ImageType = type;
          this->PixelSize = GdcmHeader.GetPixelSize();
 
-         if( GdcmHeader.HasLUT() )
+         if( GdcmHeader.HasLUT() && this->AllowLookupTable )
          {
+            // I could raise an error is AllowLookupTable is on and HasLUT() off
             this->NumComponents = GdcmHeader.GetNumberOfScalarComponentsRaw();
          }
          else
@@ -576,12 +610,13 @@ size_t vtkGdcmReader::LoadImageInMemory(
              const unsigned long UpdateProgressTarget,
              unsigned long & UpdateProgressCount)
 {
-   vtkDebugMacro("Copying to memory image" << FileName.c_str());
-   gdcmFile GdcmFile(FileName.c_str());
+   vtkDebugMacro("Copying to memory image [" << FileName.c_str() << "]");
+   gdcmFile GdcmFile(FileName.c_str(),false,true);
+   // true : to enable SeQuences
    size_t size;
 
    // If the data structure of vtk for image/volume representation
-   // were straigthforwards the following would suffice:
+   // were straigthforwards the following would be enough:
    //    GdcmFile.GetImageDataIntoVector((void*)Dest, size);
    // But vtk chooses to invert the lines of an image, that is the last
    // line comes first (for some axis related reasons?). Hence we need
@@ -594,7 +629,7 @@ size_t vtkGdcmReader::LoadImageInMemory(
 
    unsigned char * Source;
    
-   if( GdcmFile.GetHeader()->HasLUT() )
+   if( GdcmFile.GetHeader()->HasLUT() && this->AllowLookupTable )
    {
       size               = GdcmFile.GetImageDataSizeRaw();
       Source             = (unsigned char*) GdcmFile.GetImageDataRaw();
@@ -621,7 +656,8 @@ size_t vtkGdcmReader::LoadImageInMemory(
    {
       size        = GdcmFile.GetImageDataSize();
       Source      = (unsigned char*)GdcmFile.GetImageData();
-   }
+   } 
+   
    unsigned char * pSource     = Source; //pointer for later deletion
    unsigned char * Destination = Dest + size - LineSize;
 
@@ -641,8 +677,18 @@ size_t vtkGdcmReader::LoadImageInMemory(
          UpdateProgressCount++;
       }
    }
+   
+// DO NOT remove this commented out code .
+// Nobody knows what's expecting you ...
+// Just to 'see' what was actually read on disk :-(
+
+//   FILE * f2;
+//   f2 = fopen("SpuriousFile.RAW","wb");
+//   fwrite(Dest,size,1,f2);
+//   fclose(f2); 
+   
    //GetImageData allocate a (void*)malloc, remove it:
-   free(pSource);
+   delete[] pSource;
    return size;
 }