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