]> Creatis software - clitk.git/blob - itk/clitkResampleImageWithOptionsFilter.txx
Reformatted using new coding style
[clitk.git] / itk / clitkResampleImageWithOptionsFilter.txx
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://oncora1.lyon.fnclcc.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
19 // clitk
20 #include "clitkCommon.h"
21
22 // itk include
23 #include "itkImage.h"
24 #include "itkImageFileReader.h"
25 #include "itkImageSeriesReader.h"
26 #include "itkImageFileWriter.h"
27 #include "itkRecursiveGaussianImageFilter.h"
28 #include "itkResampleImageFilter.h"
29 #include "itkAffineTransform.h"
30 #include "itkNearestNeighborInterpolateImageFunction.h"
31 #include "itkLinearInterpolateImageFunction.h"
32 #include "itkBSplineInterpolateImageFunction.h"
33 #include "itkBSplineInterpolateImageFunctionWithLUT.h"
34 #include "itkCommand.h"
35
36 namespace clitk
37 {
38
39 //--------------------------------------------------------------------
40 template <class TInputImage, class TOutputImage>
41 ResampleImageWithOptionsFilter<TInputImage, TOutputImage>::
42 ResampleImageWithOptionsFilter():itk::ImageToImageFilter<TInputImage, TOutputImage>()
43 {
44   static const unsigned int dim = InputImageType::ImageDimension;
45   this->SetNumberOfRequiredInputs(1);
46   m_OutputIsoSpacing = -1;
47   m_InterpolationType = NearestNeighbor;
48   m_GaussianFilteringEnabled = true;
49   m_BSplineOrder = 3;
50   m_BLUTSamplingFactor = 20;
51   m_LastDimensionIsTime = false;
52   m_Transform =  TransformType::New();
53   if (dim == 4) m_LastDimensionIsTime = true; // by default 4D is 3D+t
54   for(unsigned int i=0; i<dim; i++) {
55     m_OutputSize[i] = 0;
56     m_OutputSpacing[i] = -1;
57     m_GaussianSigma[i] = -1;
58   }
59   m_VerboseOptions = false;
60 }
61 //--------------------------------------------------------------------
62
63
64 //--------------------------------------------------------------------
65 template <class TInputImage, class TOutputImage>
66 void
67 ResampleImageWithOptionsFilter<TInputImage, TOutputImage>::
68 SetInput(const InputImageType * image)
69 {
70   // Process object is not const-correct so the const casting is required.
71   this->SetNthInput(0, const_cast<InputImageType *>(image));
72 }
73 //--------------------------------------------------------------------
74
75
76 //--------------------------------------------------------------------
77 template <class TInputImage, class TOutputImage>
78 void
79 ResampleImageWithOptionsFilter<TInputImage, TOutputImage>::
80 GenerateInputRequestedRegion()
81 {
82   // call the superclass's implementation of this method
83   Superclass::GenerateInputRequestedRegion();
84
85   // get pointers to the input and output
86   InputImagePointer  inputPtr  =
87     const_cast< TInputImage *>( this->GetInput() );
88
89   // Request the entire input image
90   InputImageRegionType inputRegion;
91   inputRegion = inputPtr->GetLargestPossibleRegion();
92   inputPtr->SetRequestedRegion(inputRegion);
93 }
94 //--------------------------------------------------------------------
95
96
97 //--------------------------------------------------------------------
98 template <class TInputImage, class TOutputImage>
99 void
100 ResampleImageWithOptionsFilter<TInputImage, TOutputImage>::
101 GenerateOutputInformation()
102 {
103   static const unsigned int dim = InputImageType::ImageDimension;
104
105   // Warning
106   if (!std::numeric_limits<InputImagePixelType>::is_signed) {
107     if ((m_InterpolationType == BSpline) ||
108         (m_InterpolationType == B_LUT)) {
109       std::cerr << "Warning : input pixel type is not signed, use bspline interpolation at your own risk ..." << std::endl;
110     }
111   }
112
113   // Get input pointer
114   InputImagePointer input = dynamic_cast<InputImageType*>(itk::ProcessObject::GetInput(0));
115
116   // Perform default implementation
117   Superclass::GenerateOutputInformation();
118
119   // Compute sizes
120   InputImageSpacingType inputSpacing = input->GetSpacing();
121   InputImageSizeType inputSize = input->GetLargestPossibleRegion().GetSize();
122
123   if (m_OutputIsoSpacing != -1) { // apply isoSpacing
124     for(unsigned int i=0; i<dim; i++) {
125       m_OutputSpacing[i] = m_OutputIsoSpacing;
126       m_OutputSize[i] = (int)lrint(inputSize[i]*inputSpacing[i]/m_OutputSpacing[i]);
127     }
128   } else {
129     if (m_OutputSpacing[0] != -1) { // apply spacing, compute size
130       for(unsigned int i=0; i<dim; i++) {
131         m_OutputSize[i] = (int)lrint(inputSize[i]*inputSpacing[i]/m_OutputSpacing[i]);
132       }
133     } else {
134       if (m_OutputSize[0] != 0) { // apply size, compute spacing
135         for(unsigned int i=0; i<dim; i++) {
136           m_OutputSpacing[i] = (double)inputSize[i]*inputSpacing[i]/(double)m_OutputSize[i];
137         }
138       } else { // copy input size/spacing ... (no resampling)
139         m_OutputSize = inputSize;
140         m_OutputSpacing = inputSpacing;
141       }
142     }
143   }
144
145   // Special case for temporal image 2D+t or 3D+t
146   if (m_LastDimensionIsTime) {
147     int l = dim-1;
148     m_OutputSize[l] = inputSize[l];
149     m_OutputSpacing[l] = inputSpacing[l];
150   }
151
152   // Set Size/Spacing
153   OutputImagePointer outputImage = this->GetOutput(0);
154   OutputImageRegionType region;
155   region.SetSize(m_OutputSize);
156   region.SetIndex(input->GetLargestPossibleRegion().GetIndex());
157   DD(input->GetLargestPossibleRegion().GetIndex());
158   outputImage->SetLargestPossibleRegion(region);
159   outputImage->SetSpacing(m_OutputSpacing);
160
161   // Init Gaussian sigma
162   if (m_GaussianSigma[0] != -1) { // Gaussian filter set by user
163     m_GaussianFilteringEnabled = true;
164   } else {
165     if (m_GaussianFilteringEnabled) { // Automated sigma when downsample
166       for(unsigned int i=0; i<dim; i++) {
167         if (m_OutputSpacing[i] > inputSpacing[i]) { // downsample
168           m_GaussianSigma[i] = 0.5*m_OutputSpacing[i];// / inputSpacing[i]);
169         } else m_GaussianSigma[i] = 0; // will be ignore after
170       }
171     }
172   }
173   if (m_GaussianFilteringEnabled && m_LastDimensionIsTime) {
174     m_GaussianSigma[dim-1] = 0;
175   }
176 }
177 //--------------------------------------------------------------------
178
179
180 //--------------------------------------------------------------------
181 template <class TInputImage, class TOutputImage>
182 void
183 ResampleImageWithOptionsFilter<TInputImage, TOutputImage>::
184 GenerateData()
185 {
186
187   // Get input pointer
188   InputImagePointer input = dynamic_cast<InputImageType*>(itk::ProcessObject::GetInput(0));
189   static const unsigned int dim = InputImageType::ImageDimension;
190
191   // Create main Resample Image Filter
192   typedef itk::ResampleImageFilter<InputImageType,OutputImageType> FilterType;
193   typename FilterType::Pointer filter = FilterType::New();
194   filter->GraftOutput(this->GetOutput());
195 //     this->GetOutput()->Print(std::cout);
196 //     this->GetOutput()->SetBufferedRegion(this->GetOutput()->GetLargestPossibleRegion());
197 //     this->GetOutput()->Print(std::cout);
198
199   // Print options if needed
200   if (m_VerboseOptions) {
201     std::cout << "Output Spacing = " << m_OutputSpacing << std::endl
202               << "Output Size    = " << m_OutputSize << std::endl
203               << "Gaussian       = " << m_GaussianFilteringEnabled << std::endl;
204     if (m_GaussianFilteringEnabled)
205       std::cout << "Sigma          = " << m_GaussianSigma << std::endl;
206     std::cout << "Interpol       = ";
207     switch (m_InterpolationType) {
208     case NearestNeighbor:
209       std::cout << "NearestNeighbor" << std::endl;
210       break;
211     case Linear:
212       std::cout << "Linear" << std::endl;
213       break;
214     case BSpline:
215       std::cout << "BSpline " << m_BSplineOrder << std::endl;
216       break;
217     case B_LUT:
218       std::cout << "B-LUT " << m_BSplineOrder << " " << m_BLUTSamplingFactor << std::endl;
219       break;
220     }
221     std::cout << "Threads        = " << this->GetNumberOfThreads() << std::endl;
222     std::cout << "LastDimIsTime  = " << m_LastDimensionIsTime << std::endl;
223   }
224
225   // Instance of the transform object to be passed to the resample
226   // filter. By default, identity transform is applied
227   filter->SetTransform(m_Transform);
228   filter->SetSize(m_OutputSize);
229   filter->SetOutputSpacing(m_OutputSpacing);
230   filter->SetOutputOrigin(input->GetOrigin());
231   filter->SetDefaultPixelValue(m_DefaultPixelValue);
232   filter->SetNumberOfThreads(this->GetNumberOfThreads());
233
234   // Select interpolator
235   switch (m_InterpolationType) {
236   case NearestNeighbor: {
237     typedef itk::NearestNeighborInterpolateImageFunction<InputImageType, double> InterpolatorType;
238     typename InterpolatorType::Pointer interpolator = InterpolatorType::New();
239     filter->SetInterpolator(interpolator);
240     break;
241   }
242   case Linear: {
243     typedef itk::LinearInterpolateImageFunction<InputImageType, double> InterpolatorType;
244     typename InterpolatorType::Pointer interpolator =  InterpolatorType::New();
245     filter->SetInterpolator(interpolator);
246     break;
247   }
248   case BSpline: {
249     typedef itk::BSplineInterpolateImageFunction<InputImageType, double> InterpolatorType;
250     typename InterpolatorType::Pointer interpolator = InterpolatorType::New();
251     interpolator->SetSplineOrder(m_BSplineOrder);
252     filter->SetInterpolator(interpolator);
253     break;
254   }
255   case B_LUT: {
256     typedef itk::BSplineInterpolateImageFunctionWithLUT<InputImageType, double> InterpolatorType;
257     typename InterpolatorType::Pointer interpolator = InterpolatorType::New();
258     interpolator->SetSplineOrder(m_BSplineOrder);
259     interpolator->SetLUTSamplingFactor(m_BLUTSamplingFactor);
260     filter->SetInterpolator(interpolator);
261     break;
262   }
263   }
264
265   // Initial Gaussian blurring if needed
266   typedef itk::RecursiveGaussianImageFilter<InputImageType, InputImageType> GaussianFilterType;
267   std::vector<typename GaussianFilterType::Pointer> gaussianFilters;
268   if (m_GaussianFilteringEnabled) {
269     for(unsigned int i=0; i<dim; i++) {
270       if (m_GaussianSigma[i] != 0) {
271         gaussianFilters.push_back(GaussianFilterType::New());
272         gaussianFilters[i]->SetDirection(i);
273         gaussianFilters[i]->SetOrder(GaussianFilterType::ZeroOrder);
274         gaussianFilters[i]->SetNormalizeAcrossScale(false);
275         gaussianFilters[i]->SetSigma(m_GaussianSigma[i]); // in millimeter !
276         if (gaussianFilters.size() == 1) { // first
277           gaussianFilters[0]->SetInput(input);
278         } else {
279           gaussianFilters[i]->SetInput(gaussianFilters[i-1]->GetOutput());
280         }
281       }
282     }
283     if (gaussianFilters.size() > 0) {
284       filter->SetInput(gaussianFilters[gaussianFilters.size()-1]->GetOutput());
285     } else filter->SetInput(input);
286   } else filter->SetInput(input);
287
288   // Go !
289   filter->Update();
290
291   // Set output
292   // DD("before Graft");
293   this->GraftOutput(filter->GetOutput());
294   // DD("after Graft");
295 }
296 //--------------------------------------------------------------------
297
298 }//end clitk
299