]> Creatis software - clitk.git/blob - common/vvImageReader.cxx
Open NVector Pixel Image as 4D Image
[clitk.git] / common / vvImageReader.cxx
1 /*=========================================================================
2   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
3
4   Authors belong to:
5   - University of LYON              http://www.universite-lyon.fr/
6   - Léon Bérard cancer center       http://www.centreleonberard.fr
7   - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
8
9   This software is distributed WITHOUT ANY WARRANTY; without even
10   the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11   PURPOSE.  See the copyright notices for more information.
12
13   It is distributed under dual licence
14
15   - BSD        See included LICENSE.txt file
16   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17   ===========================================================================**/
18 #ifndef VVIMAGEREADER_CXX
19 #define VVIMAGEREADER_CXX
20
21 #include <itkImageFileReader.h>
22 #include "vvImageReader.h"
23 #include "vvImageReader.txx"
24 #include "clitkTransformUtilities.h"
25 #include "clitkElastix.h"
26
27 //------------------------------------------------------------------------------
28 vvImageReader::vvImageReader()
29 {
30   mImage = NULL;
31   mInputFilenames.resize(0);
32   mLastError = "";
33   mType = UNDEFINEDIMAGETYPE;
34   mSlice = 0;
35 }
36 //------------------------------------------------------------------------------
37
38
39 //------------------------------------------------------------------------------
40 vvImageReader::~vvImageReader() { }
41 //------------------------------------------------------------------------------
42
43
44 //------------------------------------------------------------------------------
45 void vvImageReader::Update()
46 {
47   Update(mType);
48 }
49 //------------------------------------------------------------------------------
50
51
52 //------------------------------------------------------------------------------
53 void vvImageReader::Update(LoadedImageType type)
54 {
55   itk::ImageIOBase::Pointer reader = itk::ImageIOFactory::CreateImageIO(mInputFilenames[0].c_str(), itk::ImageIOFactory::ReadMode);
56   if (!reader) {
57     mLastError="Unable to read file.";
58   } else {
59     reader->SetFileName(mInputFilenames[0]);
60     reader->ReadImageInformation();
61     if (mInputFilenames.size() > 1)
62       Update(reader->GetNumberOfDimensions()+1,reader->GetComponentTypeAsString(reader->GetComponentType()),type);
63     else if (reader->GetComponentSize() > 1 && type != VECTORFIELD && type != VECTORFIELDWITHTIME)
64       Update(reader->GetNumberOfDimensions()+1,reader->GetComponentTypeAsString(reader->GetComponentType()),VECTORPIXELIMAGE);
65     else
66       Update(reader->GetNumberOfDimensions(),reader->GetComponentTypeAsString(reader->GetComponentType()),type);
67   }
68 }
69 //------------------------------------------------------------------------------
70
71
72 //------------------------------------------------------------------------------
73 void vvImageReader::Update(int dim,std::string inputPixelType, LoadedImageType type)
74 {
75   //CALL_FOR_ALL_DIMS(dim,UpdateWithDim,inputPixelType);
76   mType = type;
77   mDim = dim;
78   mInputPixelType=inputPixelType;
79
80   switch(mDim)     {
81   case 2:
82     UpdateWithDim<2>(mInputPixelType);
83     break;
84   case 3:
85     UpdateWithDim<3>(mInputPixelType);
86     break;
87   case 4:
88     UpdateWithDim<4>(mInputPixelType);
89     break;
90   default:
91     std::cerr << "dimension unknown in Update ! " << std::endl;
92   }
93 }
94 //------------------------------------------------------------------------------
95
96
97 //------------------------------------------------------------------------------
98 void vvImageReader::SetInputFilename(const std::string & filename)
99 {
100   mInputFilenames.resize(0);
101   mInputFilenames.push_back(filename);
102 }
103 //------------------------------------------------------------------------------
104
105
106 //------------------------------------------------------------------------------
107 void vvImageReader::SetInputFilenames(const std::vector<std::string> & filenames)
108 {
109   mInputFilenames = filenames;
110 }
111 //------------------------------------------------------------------------------
112
113
114 //------------------------------------------------------------------------------
115 //Read transformation in NKI format (Xdr, transposed, cm)
116 //void vvImageReader::ReadNkiImageTransform()
117 //{
118 //  bool bRead=false;
119 //  std::string filename = mInputFilenames[0]+".MACHINEORIENTATION";
120 //  if(itksys::SystemTools::FileExists(filename.c_str())){
121 //    typedef itk::ImageFileReader< itk::Image< double, 2 > > MatrixReaderType;
122 //    MatrixReaderType::Pointer readerTransfo = MatrixReaderType::New();
123 //    readerTransfo->SetFileName(filename);
124 //    try {
125 //      bRead = true;
126 //      readerTransfo->Update();
127 //    } catch( itk::ExceptionObject & err ) {
128 //      bRead=false;
129 //      std::cerr << "Cannot read " << filename << std::endl
130 //                << "The error is: " << err << std::endl;
131 //    }
132
133 //    if (bRead) {
134 //      //Transpose matrix (NKI format)
135 //      for(int j=0; j<4; j++)
136 //        for(int i=0; i<4; i++)
137 //          mImage->GetTransform()->GetMatrix()->SetElement(j,i,readerTransfo->GetOutput()->GetBufferPointer()[4*i+j]);
138
139 //      //From cm to mm
140 //      for(int i=0; i<3; i++)
141 //        mImage->GetTransform()->GetMatrix()->SetElement(i,3,10*mImage->GetTransform()->GetMatrix()->GetElement(i,3));
142
143 //      mImage->GetTransform()->Inverse();
144 //    }
145 //  }
146 //}
147 //------------------------------------------------------------------------------
148
149
150 //------------------------------------------------------------------------------
151 //Read transformation in ASCII format
152 void vvImageReader::ReadMatImageTransform()
153 {
154   std::string filename(mInputFilenames[0]);
155   std::string ext(itksys::SystemTools::GetFilenameLastExtension(filename));
156
157   // Try a ".mat" extension
158   if (ext.length() > 0) {
159     size_t pos = filename.rfind(ext);
160     filename.replace(pos, ext.length(), ".mat");
161   }
162   else
163     filename += ".mat";
164   std::ifstream f(filename.c_str());
165   itk::Matrix<double, 4, 4> itkMat;
166   bool itkMatRead = false;
167   if(f.is_open()) {
168     itkMatRead = true;
169
170     itkMat.SetIdentity();
171     try {
172       itkMat = clitk::ReadMatrix3D(filename);
173     }
174     catch (itk::ExceptionObject & err) {
175       itkWarningMacro(<< "Found " << filename
176                       << " but this is not a 4x4 matrix so it is ignored.");
177       itkMatRead = false;
178     }
179   }
180   f.close();
181
182   // Try a ".elx" extension
183   filename = mInputFilenames[0];
184   if (ext.length() > 0) {
185     size_t pos = filename.rfind(ext);
186     filename.replace(pos, ext.length(), ".elx");
187   }
188   else
189     filename += ".elx";
190   f.open(filename.c_str());
191   if(!itkMatRead && f.is_open()) {
192     itkMatRead = true;
193     itkMat = clitk::createMatrixFromElastixFile<3>(filename, true);
194   }
195   f.close();
196
197   if(itkMatRead) {
198     vtkSmartPointer<vtkMatrix4x4> matrix = vtkSmartPointer<vtkMatrix4x4>::New();
199     matrix->Identity();
200     for(int j=0; j<4; j++)
201       for(int i=0; i<4; i++)
202         matrix->SetElement(j,i,itkMat[j][i]);
203
204     // RP: 14/03/2011
205     //  For some reason, the transformation matrix given in the MHD
206     // file is inverted wrt the transformation given in the MAT file.
207     // We don't really know where the inversion takes place inside
208     // VTK or ITK. For what we could see in VV, the transformation
209     // given in the MHD file seems "more correct" than that given in
210     // the MAT file. For this reason, we invert the matrix read from
211     // the MAT file before concatenating it to the current transformation.
212     // Still, it would be nice to find out what happens exactly between
213     // VTK and ITK...
214     //
215     // SR: 23/06/2011
216     // We actually use vtkImageReslice which takes the inverse transform
217     // as input. So it seems more correct to inverse the matrix given by
218     // itk::ImageBase< VImageDimension >::GetDirection() than the matrix
219     // in .mat which is indeed the inverse optimized by a typical
220     // affine registration algorithm.
221     // Validated using clitkAffineTransform --transform_grid
222     if (matrix->Determinant() == 0)
223     {
224       vtkGenericWarningMacro("Matrix in " << filename.c_str() << " cannot be inverted (determinant = 0)");
225     }
226
227     // TODO SR and BP: check on the list of transforms and not the first only
228     mImage->GetTransform()[0]->PreMultiply();
229     mImage->GetTransform()[0]->Concatenate(matrix);
230     mImage->GetTransform()[0]->Update();
231
232     //for image sequences, apply the transform to each images of the sequence
233     if (mImage->IsTimeSequence())
234     {
235       for (unsigned i = 1 ; i<mImage->GetTransform().size() ; i++)
236       {
237         mImage->GetTransform()[i]->PreMultiply();
238         mImage->GetTransform()[i]->Concatenate(matrix);
239         mImage->GetTransform()[i]->Update();
240       }
241     }
242
243   }
244 }
245 //------------------------------------------------------------------------------
246 #endif
247