1 // $Header: /cvs/public/gdcm/vtk/vtkGdcmReader.cxx,v 1.3 2003/05/21 08:21:17 frog Exp $
2 #include "vtkGdcmReader.h"
3 #include "vtkByteSwap.h"
5 #include "vtkObjectFactory.h"
6 #include "vtkImageFlip.h"
9 vtkGdcmReader::vtkGdcmReader()
14 //----------------------------------------------------------------------------
15 vtkGdcmReader::~vtkGdcmReader()
20 // Configure the output e.g. WholeExtent, spacing, origin, scalar type...
21 void vtkGdcmReader::ExecuteInformation()
23 //FIXME free any old memory
25 // if the user has not set the extent, but has set the VOI
26 // set the zaxis extent to the VOI z axis
27 if (this->DataExtent[4]==0 && this->DataExtent[5] == 0 &&
28 (this->DataVOI[4] || this->DataVOI[5]))
30 this->DataExtent[4] = this->DataVOI[4];
31 this->DataExtent[5] = this->DataVOI[5];
34 this->ComputeInternalFileName(this->DataExtent[4]);
36 // Check for file existence.
38 fp = fopen(this->InternalFileName,"rb");
41 vtkErrorMacro("Unable to open file " << this->InternalFileName);
46 // Check for Gdcm parsability
47 gdcmHeader GdcmHeader(this->InternalFileName);
48 if (!GdcmHeader.IsReadable())
50 vtkErrorMacro("Gdcm cannot parse file " << this->InternalFileName);
54 int NX = GdcmHeader.GetXSize();
55 int NY = GdcmHeader.GetYSize();
56 int NZ = GdcmHeader.GetZSize();
57 vtkDebugMacro("Image dimension as read from Gdcm:" <<
58 NX << " " << NY << " " << NZ);
60 if(NZ>1) this->SetFileDimensionality(3);
62 // When the user has set the VOI, check it's coherence with the file content.
63 if (this->DataVOI[0] || this->DataVOI[1] ||
64 this->DataVOI[2] || this->DataVOI[3] ||
65 this->DataVOI[4] || this->DataVOI[5])
67 if ((this->DataVOI[0] < 0) ||
68 (this->DataVOI[1] >= NX) ||
69 (this->DataVOI[2] < 0) ||
70 (this->DataVOI[3] >= NY) ||
71 (this->DataVOI[4] < 0) ||
72 (this->DataVOI[5] >= NZ))
74 vtkWarningMacro("The requested VOI is larger than the file's ("
75 << this->InternalFileName << ") extent ");
77 this->DataVOI[1] = NX - 1;
79 this->DataVOI[3] = NY - 1;
81 this->DataVOI[5] = NZ - 1;
85 // Positionate the Extent.
86 this->DataExtent[0] = 0;
87 this->DataExtent[1] = NX - 1;
88 this->DataExtent[2] = 0;
89 this->DataExtent[3] = NY - 1;
90 if(this->GetFileDimensionality()==3)
92 this->DataExtent[4] = 0;
93 this->DataExtent[5] = NZ - 1;
96 // We don't need to positionate the Endian related stuff (by using
97 // this->SetDataByteOrderToBigEndian() or SetDataByteOrderToLittleEndian()
98 // since the // reading of the file is done by gdcm
100 // But we need to set up the data type for downstream filters:
101 string type = GdcmHeader.GetPixelType();
104 vtkDebugMacro("8 bits unsigned image");
105 this->SetDataScalarTypeToUnsignedChar();
107 else if ( type == "8S" )
109 vtkErrorMacro("Cannot handle 8 bit signed files");
112 else if ( type == "16U" )
114 vtkDebugMacro("16 bits unsigned image");
115 this->SetDataScalarTypeToUnsignedShort();
117 else if ( type == "16S" )
119 vtkDebugMacro("16 bits signed image");
120 this->SetDataScalarTypeToShort();
121 //vtkErrorMacro("Cannot handle 16 bit signed files");
123 else if ( type == "32U" )
125 vtkDebugMacro("32 bits unsigned image");
126 vtkDebugMacro("WARNING: forced to signed int !");
127 this->SetDataScalarTypeToInt();
129 else if ( type == "32S" )
131 vtkDebugMacro("32 bits signed image");
132 this->SetDataScalarTypeToInt();
136 vtkErrorMacro("Bad File Type " << this->InternalFileName
141 vtkImageReader::ExecuteInformation();
144 // Update -> UpdateData -> Execute -> ExecuteData (see vtkSource.cxx for
146 // This function (redefinition of vtkImageReader::ExecuteData, see
147 // VTK/IO/vtkImageReader.cxx) reads a data from a file. The datas
148 // extent/axes are assumed to be the
149 // same as the file extent/order.
150 void vtkGdcmReader::ExecuteData(vtkDataObject *output)
154 vtkErrorMacro("A valid FileName must be specified.");
158 vtkImageData *data = this->AllocateOutputData(output);
159 data->SetExtent(this->DataExtent);
160 data->GetPointData()->GetScalars()->SetName("ImageFile");
162 // First check the coherence between the DataExtent and the
163 // size of the pixel data as annouced by gdcm (looks a bit paranoid).
164 gdcmFile GdcmFile(this->InternalFileName);
165 int NumColumns = this->DataExtent[1] - this->DataExtent[0] + 1;
166 int NumLines = this->DataExtent[3] - this->DataExtent[2] + 1;
167 int NumPlanes = this->DataExtent[5] - this->DataExtent[4] + 1;
168 int size = NumColumns * NumLines * NumPlanes * GdcmFile.GetPixelSize();
169 if ( size != GdcmFile.GetImageDataSize() )
171 vtkDebugMacro("Inconsistency with GetImageDataSize");
172 vtkDebugMacro("Number of scalar components"
173 << this->NumberOfScalarComponents);
175 // Allocate pixel data space itself.
176 unsigned char *mem = new unsigned char [size];
178 // If the data structure of vtk for image/volume representation
179 // were straigthforwards the following would suffice:
180 // GdcmFile.GetImageDataIntoVector((void*)mem, size);
181 // But vtk chose to invert the lines of an image, that is the last
182 // line comes first (for some axis related reasons?). Hence we need
183 // to load the image line by line, starting from the end:
184 int LineSize = NumColumns * GdcmFile.GetPixelSize();
185 unsigned char * Source = (unsigned char*)GdcmFile.GetImageData();
186 unsigned char * Destination = mem + size - LineSize;
187 for (int i = 0; i < NumLines; i++)
189 memcpy((void*)Destination, (void*)Source, LineSize);
191 Destination -= LineSize;
193 // The "size" of the vtkScalars data is expressed in number of points,
194 // and is not the memory size representing those points:
195 size = size / GdcmFile.GetPixelSize();
196 data->GetPointData()->GetScalars()->SetVoidArray(mem, size, 0);
201 void vtkGdcmReader::PrintSelf(ostream& os, vtkIndent indent)
203 vtkImageReader::PrintSelf(os,indent);
204 //CLEANME os << indent << "TypeSize: " << this->TypeSize << "\n";