1 // $Header: /cvs/public/gdcm/vtk/vtkGdcmReader.cxx,v 1.5 2003/05/28 19:36:21 frog Exp $
2 //CLEANME#include <vtkByteSwap.h>
4 #include <vtkObjectFactory.h>
5 #include <vtkImageData.h>
6 #include <vtkPointData.h>
7 #include "vtkGdcmReader.h"
10 vtkGdcmReader::vtkGdcmReader()
15 //----------------------------------------------------------------------------
16 vtkGdcmReader::~vtkGdcmReader()
21 // Configure the output e.g. WholeExtent, spacing, origin, scalar type...
22 void vtkGdcmReader::ExecuteInformation()
24 //FIXME free any old memory
26 // if the user has not set the extent, but has set the VOI
27 // set the zaxis extent to the VOI z axis
28 if (this->DataExtent[4]==0 && this->DataExtent[5] == 0 &&
29 (this->DataVOI[4] || this->DataVOI[5]))
31 this->DataExtent[4] = this->DataVOI[4];
32 this->DataExtent[5] = this->DataVOI[5];
35 this->ComputeInternalFileName(this->DataExtent[4]);
37 // Check for file existence.
39 fp = fopen(this->InternalFileName,"rb");
42 vtkErrorMacro("Unable to open file " << this->InternalFileName);
47 // Check for Gdcm parsability
48 gdcmHeader GdcmHeader(this->InternalFileName);
49 if (!GdcmHeader.IsReadable())
51 vtkErrorMacro("Gdcm cannot parse file " << this->InternalFileName);
55 int NX = GdcmHeader.GetXSize();
56 int NY = GdcmHeader.GetYSize();
57 int NZ = GdcmHeader.GetZSize();
58 vtkDebugMacro("Image dimension as read from Gdcm:" <<
59 NX << " " << NY << " " << NZ);
61 if(NZ>1) this->SetFileDimensionality(3);
63 // When the user has set the VOI, check it's coherence with the file content.
64 if (this->DataVOI[0] || this->DataVOI[1] ||
65 this->DataVOI[2] || this->DataVOI[3] ||
66 this->DataVOI[4] || this->DataVOI[5])
68 if ((this->DataVOI[0] < 0) ||
69 (this->DataVOI[1] >= NX) ||
70 (this->DataVOI[2] < 0) ||
71 (this->DataVOI[3] >= NY) ||
72 (this->DataVOI[4] < 0) ||
73 (this->DataVOI[5] >= NZ))
75 vtkWarningMacro("The requested VOI is larger than the file's ("
76 << this->InternalFileName << ") extent ");
78 this->DataVOI[1] = NX - 1;
80 this->DataVOI[3] = NY - 1;
82 this->DataVOI[5] = NZ - 1;
86 // Positionate the Extent.
87 this->DataExtent[0] = 0;
88 this->DataExtent[1] = NX - 1;
89 this->DataExtent[2] = 0;
90 this->DataExtent[3] = NY - 1;
91 if(this->GetFileDimensionality()==3)
93 this->DataExtent[4] = 0;
94 this->DataExtent[5] = NZ - 1;
97 // We don't need to positionate the Endian related stuff (by using
98 // this->SetDataByteOrderToBigEndian() or SetDataByteOrderToLittleEndian()
99 // since the // reading of the file is done by gdcm
101 // But we need to set up the data type for downstream filters:
102 std::string type = GdcmHeader.GetPixelType();
105 vtkDebugMacro("8 bits unsigned image");
106 this->SetDataScalarTypeToUnsignedChar();
108 else if ( type == "8S" )
110 vtkErrorMacro("Cannot handle 8 bit signed files");
113 else if ( type == "16U" )
115 vtkDebugMacro("16 bits unsigned image");
116 this->SetDataScalarTypeToUnsignedShort();
118 else if ( type == "16S" )
120 vtkDebugMacro("16 bits signed image");
121 this->SetDataScalarTypeToShort();
122 //vtkErrorMacro("Cannot handle 16 bit signed files");
124 else if ( type == "32U" )
126 vtkDebugMacro("32 bits unsigned image");
127 vtkDebugMacro("WARNING: forced to signed int !");
128 this->SetDataScalarTypeToInt();
130 else if ( type == "32S" )
132 vtkDebugMacro("32 bits signed image");
133 this->SetDataScalarTypeToInt();
137 vtkErrorMacro("Bad File Type " << this->InternalFileName
138 << "Type " << type.c_str());
142 vtkImageReader::ExecuteInformation();
145 // Update -> UpdateData -> Execute -> ExecuteData (see vtkSource.cxx for
147 // This function (redefinition of vtkImageReader::ExecuteData, see
148 // VTK/IO/vtkImageReader.cxx) reads a data from a file. The datas
149 // extent/axes are assumed to be the
150 // same as the file extent/order.
151 void vtkGdcmReader::ExecuteData(vtkDataObject *output)
155 vtkErrorMacro("A valid FileName must be specified.");
159 vtkImageData *data = this->AllocateOutputData(output);
160 data->SetExtent(this->DataExtent);
161 data->GetPointData()->GetScalars()->SetName("ImageFile");
163 // First check the coherence between the DataExtent and the
164 // size of the pixel data as annouced by gdcm (looks a bit paranoid).
165 gdcmFile GdcmFile(this->InternalFileName);
166 int NumColumns = this->DataExtent[1] - this->DataExtent[0] + 1;
167 int NumLines = this->DataExtent[3] - this->DataExtent[2] + 1;
168 int NumPlanes = this->DataExtent[5] - this->DataExtent[4] + 1;
169 size_t size = NumColumns * NumLines * NumPlanes * GdcmFile.GetPixelSize();
170 if ( size != GdcmFile.GetImageDataSize() )
172 vtkDebugMacro("Inconsistency with GetImageDataSize");
173 vtkDebugMacro("Number of scalar components"
174 << this->NumberOfScalarComponents);
176 // Allocate pixel data space itself.
177 unsigned char *mem = new unsigned char [size];
179 // If the data structure of vtk for image/volume representation
180 // were straigthforwards the following would suffice:
181 // GdcmFile.GetImageDataIntoVector((void*)mem, size);
182 // But vtk chose to invert the lines of an image, that is the last
183 // line comes first (for some axis related reasons?). Hence we need
184 // to load the image line by line, starting from the end:
185 int LineSize = NumColumns * GdcmFile.GetPixelSize();
186 unsigned char * Source = (unsigned char*)GdcmFile.GetImageData();
187 unsigned char * Destination = mem + size - LineSize;
188 for (int i = 0; i < NumLines; i++)
190 memcpy((void*)Destination, (void*)Source, LineSize);
192 Destination -= LineSize;
194 // The "size" of the vtkScalars data is expressed in number of points,
195 // and is not the memory size representing those points:
196 size = size / GdcmFile.GetPixelSize();
197 data->GetPointData()->GetScalars()->SetVoidArray(mem, size, 0);
202 void vtkGdcmReader::PrintSelf(ostream& os, vtkIndent indent)
204 vtkImageReader::PrintSelf(os,indent);
205 //CLEANME os << indent << "TypeSize: " << this->TypeSize << "\n";