+//-----------------------------------------------------------------------------
+// Protected
+/*
+ * Configure the output e.g. WholeExtent, spacing, origin, scalar type...
+ */
+void vtkGdcmReader::ExecuteInformation()
+{
+ if(this->MTime>this->fileTime)
+ {
+ 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 ))
+ {
+ 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;
+
+ // 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;
+ }
+
+ this->Superclass::ExecuteInformation();
+}
+
+/*
+ * Update => ouput->Update => UpdateData => Execute => ExecuteData
+ * (see vtkSource.cxx for last step).
+ * This function (redefinition of vtkImageReader::ExecuteData, see
+ * VTK/IO/vtkImageReader.cxx) reads a data from a file. The datas
+ * extent/axes are assumed to be the same as the file extent/order.
+ */
+void vtkGdcmReader::ExecuteData(vtkDataObject *output)
+{
+ if (this->InternalFileNameList.empty())
+ {
+ vtkErrorMacro("A least a valid FileName must be specified.");
+ return;
+ }
+
+ // FIXME : extraneous parsing of header is made when allocating OuputData
+ vtkImageData *data = this->AllocateOutputData(output);
+ data->SetExtent(this->DataExtent);
+ data->GetPointData()->GetScalars()->SetName("DicomImage-Volume");
+
+ // Test if output has valid extent
+ // Prevent memory errors
+ if((this->DataExtent[1]-this->DataExtent[0]>=0) &&
+ (this->DataExtent[3]-this->DataExtent[2]>=0) &&
+ (this->DataExtent[5]-this->DataExtent[4]>=0))
+ {
+ // 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; //not used
+ // Allocate pixel data space itself.
+
+ // Variables for the UpdateProgress. We shall use 50 steps to signify
+ // the advance of the process:
+ unsigned long UpdateProgressTarget = (unsigned long) ceil (this->NumLines
+ * this->TotalNumberOfPlanes
+ / 50.0);
+ // The actual advance measure:
+ unsigned long UpdateProgressCount = 0;
+
+ // Feeling the allocated memory space with each image/volume:
+ unsigned char *Dest = (unsigned char *)data->GetPointData()->GetScalars()->GetVoidPointer(0);
+ for (std::list<std::string>::iterator filename = InternalFileNameList.begin();
+ filename != InternalFileNameList.end();
+ ++filename)
+ {
+ // Images that were tagged as unreadable in CheckFileCoherence()
+ // are substituted with a black image to let the caller visually
+ // notice something wrong is going on:
+ if (*filename != "GDCM_UNREADABLE")
+ {
+ // Update progress related for good files is made in LoadImageInMemory
+ Dest += this->LoadImageInMemory(*filename, Dest,
+ UpdateProgressTarget,
+ UpdateProgressCount);
+ }
+ else
+ {
+ // We insert a black image in the stack for the user to be aware that
+ // this image/volume couldn't be loaded. We simply skip one image
+ // size:
+ Dest += this->NumColumns * this->NumLines * this->PixelSize;
+
+ // Update progress related for bad files:
+ UpdateProgressCount += this->NumLines;
+ if (UpdateProgressTarget > 0)
+ {
+ if (!(UpdateProgressCount%UpdateProgressTarget))
+ {
+ this->UpdateProgress(UpdateProgressCount/(50.0*UpdateProgressTarget));
+ }
+ }
+ } // Else, file not loadable
+ } // Loop on files
+ }
+}
+
+/*
+ * 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::AddFileName()
+ * When the first method was used by caller we need to update the local
+ * filename list
+ */