]> Creatis software - gdcm.git/blob - vtk/vtkGdcmReader.cxx
* src/*.[h] all occurences of stl classes are now prefixed with
[gdcm.git] / vtk / vtkGdcmReader.cxx
1 // $Header: /cvs/public/gdcm/vtk/vtkGdcmReader.cxx,v 1.4 2003/05/21 16:26:29 regrain Exp $
2 //CLEANME#include <vtkByteSwap.h>
3 #include <stdio.h>
4 #include <vtkObjectFactory.h>
5 #include <vtkImageData.h>
6 #include <vtkPointData.h>
7 #include "vtkGdcmReader.h"
8 #include "gdcm.h"
9
10 vtkGdcmReader::vtkGdcmReader()
11 {
12   // Constructor
13 }
14
15 //----------------------------------------------------------------------------
16 vtkGdcmReader::~vtkGdcmReader()
17
18   // FIXME free memory
19 }
20
21 // Configure the output e.g. WholeExtent, spacing, origin, scalar type...
22 void vtkGdcmReader::ExecuteInformation()
23 {
24   //FIXME free any old memory
25       
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]))
30     {
31     this->DataExtent[4] = this->DataVOI[4];
32     this->DataExtent[5] = this->DataVOI[5];
33     }
34
35   this->ComputeInternalFileName(this->DataExtent[4]);
36   
37   // Check for file existence.
38   FILE *fp;
39   fp = fopen(this->InternalFileName,"rb");
40   if (!fp)
41     {
42     vtkErrorMacro("Unable to open file " << this->InternalFileName);
43     return;
44     }
45   fclose(fp);
46
47   // Check for Gdcm parsability
48   gdcmHeader GdcmHeader(this->InternalFileName);
49   if (!GdcmHeader.IsReadable())
50     {
51     vtkErrorMacro("Gdcm cannot parse file " << this->InternalFileName);
52     return;
53     }
54
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);
60
61   if(NZ>1) this->SetFileDimensionality(3);
62
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])
67     { 
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))
74       {
75       vtkWarningMacro("The requested VOI is larger than the file's ("
76                       << this->InternalFileName << ") extent ");
77       this->DataVOI[0] = 0;
78       this->DataVOI[1] = NX - 1;
79       this->DataVOI[2] = 0;
80       this->DataVOI[3] = NY - 1;
81       this->DataVOI[4] = 0;
82       this->DataVOI[5] = NZ - 1;
83       }
84     }
85
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)
92     {
93       this->DataExtent[4] = 0;
94       this->DataExtent[5] = NZ - 1;
95     }
96   
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
100
101   // But we need to set up the data type for downstream filters:
102   std::string type = GdcmHeader.GetPixelType();
103   if      ( type == "8U" )
104     {
105     vtkDebugMacro("8 bits unsigned image");
106     this->SetDataScalarTypeToUnsignedChar(); 
107     }
108   else if ( type == "8S" )
109     {
110     vtkErrorMacro("Cannot handle 8 bit signed files");
111     return;
112     }
113   else if ( type == "16U" )
114     {
115     vtkDebugMacro("16 bits unsigned image");
116     this->SetDataScalarTypeToUnsignedShort();
117     }
118   else if ( type == "16S" )
119     {
120     vtkDebugMacro("16 bits signed image");
121     this->SetDataScalarTypeToShort();
122     //vtkErrorMacro("Cannot handle 16 bit signed files");
123     }
124   else if ( type == "32U" )
125     {
126     vtkDebugMacro("32 bits unsigned image");
127     vtkDebugMacro("WARNING: forced to signed int !");
128     this->SetDataScalarTypeToInt();
129     }
130   else if ( type == "32S" )
131     {
132     vtkDebugMacro("32 bits signed image");
133     this->SetDataScalarTypeToInt();
134     }
135   else
136     {
137     vtkErrorMacro("Bad File Type " << this->InternalFileName
138                                    << "Type " << type.c_str());
139     return;
140     }
141
142   vtkImageReader::ExecuteInformation();
143 }
144
145 // Update -> UpdateData -> Execute -> ExecuteData (see vtkSource.cxx for
146 // last step.
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)
152 {
153   if (!this->FileName)
154     {
155     vtkErrorMacro("A valid FileName must be specified.");
156     return;
157     }
158
159   vtkImageData *data = this->AllocateOutputData(output);
160   data->SetExtent(this->DataExtent);
161   data->GetPointData()->GetScalars()->SetName("ImageFile");
162
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   int size = NumColumns * NumLines * NumPlanes * GdcmFile.GetPixelSize();
170   if ( size != GdcmFile.GetImageDataSize() )
171     {
172     vtkDebugMacro("Inconsistency with GetImageDataSize");
173     vtkDebugMacro("Number of scalar components"
174                   << this->NumberOfScalarComponents);
175     }
176   // Allocate pixel data space itself.
177   unsigned char *mem = new unsigned char [size];
178
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++)
189     {
190     memcpy((void*)Destination, (void*)Source, LineSize);
191     Source      += LineSize;
192     Destination -= LineSize;
193     }
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);
198   this->Modified();
199
200 }
201
202 void vtkGdcmReader::PrintSelf(ostream& os, vtkIndent indent)
203 {
204   vtkImageReader::PrintSelf(os,indent);
205   //CLEANME os << indent << "TypeSize: " << this->TypeSize << "\n";
206 }