// 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.
vtkGdcmReader::vtkGdcmReader()
{
this->LookupTable = NULL;
+ this->AllowLookupTable = 0;
}
vtkGdcmReader::~vtkGdcmReader()
-{
+{
this->RemoveAllFileName();
this->InternalFileNameList.clear();
if(this->LookupTable)
// Print
void vtkGdcmReader::PrintSelf(ostream& os, vtkIndent indent)
{
- vtkImageReader::PrintSelf(os,indent);
- os << indent << "Filenames : " << endl;
- vtkIndent nextIndent = indent.GetNextIndent();
- for (std::list<std::string>::iterator FileName = FileNameList.begin();
- FileName != FileNameList.end();
- ++FileName)
- {
- os << nextIndent << FileName->c_str() << endl ;
- }
+ vtkImageReader::PrintSelf(os,indent);
+ os << indent << "Filenames : " << endl;
+ vtkIndent nextIndent = indent.GetNextIndent();
+ for (std::list<std::string>::iterator FileName = FileNameList.begin();
+ FileName != FileNameList.end();
+ ++FileName)
+ {
+ os << nextIndent << FileName->c_str() << endl ;
+ }
}
//-----------------------------------------------------------------------------
void vtkGdcmReader::RemoveAllFileName(void)
{
this->FileNameList.clear();
+ this->Modified();
}
/*
char * LocalName = new char[strlen(name) + 1];
strcpy(LocalName, name);
this->FileNameList.push_back(LocalName);
- this->Modified();
delete[] LocalName;
+ this->Modified();
}
/*
// 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();
}
*/
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();
- }
+ // 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);
- //Set number of scalar components:
- this->SetNumberOfScalarComponents(this->NumComponents);
+ this->fileTime=this->MTime;
+ }
- vtkImageReader::ExecuteInformation();
+ this->Superclass::ExecuteInformation();
}
/*
* this->TotalNumberOfPlanes * this->NumComponents;
size_t stack_size = StackNumPixels * this->PixelSize;
// Allocate pixel data space itself.
- unsigned char *mem = new unsigned char [stack_size];
// Variables for the UpdateProgress. We shall use 50 steps to signify
// the advance of the process:
unsigned long UpdateProgressCount = 0;
// Feeling the allocated memory space with each image/volume:
- unsigned char * Dest = mem;
+ unsigned char *Dest = (unsigned char *)data->GetPointData()->GetScalars()->GetVoidPointer(0);
for (std::list<std::string>::iterator FileName = InternalFileNameList.begin();
FileName != InternalFileNameList.end();
++FileName)
}
} // Else, file not loadable
} // Loop on files
-
- // The "size" of the vtkScalars data is expressed in number of points,
- // and is not the memory size representing those points:
- data->GetPointData()->GetScalars()->SetVoidArray(mem, StackNumPixels, 0);
- //don't know why it's here, it's calling one more time ExecuteInformation:
- //this->Modified();
}
}
*/
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;
}
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);
continue;
}
fclose(fp);
-
+
// Stage 1.2: check for Gdcm parsability
- gdcmHeaderHelper GdcmHeader(FileName->c_str());
+ gdcmHeaderHelper GdcmHeader(FileName->c_str(), false, true);
+ // true : for enableSequences
if (!GdcmHeader.IsReadable())
{
vtkErrorMacro("Gdcm cannot parse file " << FileName->c_str());
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
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
int LineSize = NumComponents * NumColumns * GdcmFile.GetHeader()->GetPixelSize();
unsigned char * Source;
- if( GdcmFile.GetHeader()->HasLUT() )
+
+ if( GdcmFile.GetHeader()->HasLUT() && this->AllowLookupTable )
{
size = GdcmFile.GetImageDataSizeRaw();
Source = (unsigned char*) GdcmFile.GetImageDataRaw();
{
size = GdcmFile.GetImageDataSize();
Source = (unsigned char*)GdcmFile.GetImageData();
- }
+ }
+
unsigned char * pSource = Source; //pointer for later deletion
unsigned char * Destination = Dest + size - LineSize;
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);
-
return size;
}