ITK  5.0.0
Insight Segmentation and Registration Toolkit
itkLinearInterpolateImageFunction.h
Go to the documentation of this file.
1 /*=========================================================================
2  *
3  * Copyright Insight Software Consortium
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *=========================================================================*/
18 #ifndef itkLinearInterpolateImageFunction_h
19 #define itkLinearInterpolateImageFunction_h
20 
23 
24 namespace itk
25 {
48 template< typename TInputImage, typename TCoordRep = double >
49 class ITK_TEMPLATE_EXPORT LinearInterpolateImageFunction:
50  public InterpolateImageFunction< TInputImage, TCoordRep >
51 {
52 public:
53  ITK_DISALLOW_COPY_AND_ASSIGN(LinearInterpolateImageFunction);
54 
60 
63 
65  itkNewMacro(Self);
66 
68  using OutputType = typename Superclass::OutputType;
69 
71  using InputImageType = typename Superclass::InputImageType;
72 
74  using InputPixelType = typename Superclass::InputPixelType;
75 
77  using RealType = typename Superclass::RealType;
78 
80  static constexpr unsigned int ImageDimension = Superclass::ImageDimension;
81 
83  using IndexType = typename Superclass::IndexType;
84 
86  using ContinuousIndexType = typename Superclass::ContinuousIndexType;
87  using InternalComputationType = typename ContinuousIndexType::ValueType;
88 
99  index) const override
100  {
101  return this->EvaluateOptimized(Dispatch< ImageDimension >(), index);
102  }
103 
104 protected:
105  LinearInterpolateImageFunction() = default;
106  ~LinearInterpolateImageFunction() override = default;
107  void PrintSelf(std::ostream & os, Indent indent) const override;
108 
109 private:
110  struct DispatchBase {};
111  template< unsigned int >
112  struct Dispatch: public DispatchBase {};
113 
115  const ContinuousIndexType & ) const
116  {
117  return 0;
118  }
119 
121  const ContinuousIndexType & index) const
122  {
123  IndexType basei;
124  basei[0] = Math::Floor< IndexValueType >(index[0]);
125  if ( basei[0] < this->m_StartIndex[0] )
126  {
127  basei[0] = this->m_StartIndex[0];
128  }
129 
130  const InternalComputationType & distance = index[0] - static_cast< InternalComputationType >( basei[0] );
131 
132  const TInputImage * const inputImagePtr = this->GetInputImage();
133  const RealType & val0 = inputImagePtr->GetPixel(basei);
134  if ( distance <= 0. )
135  {
136  return ( static_cast< OutputType >( val0 ) );
137  }
138 
139  ++basei[0];
140  if ( basei[0] > this->m_EndIndex[0] )
141  {
142  return ( static_cast< OutputType >( val0 ) );
143  }
144  const RealType & val1 = inputImagePtr->GetPixel(basei);
145 
146  return ( static_cast< OutputType >( val0 + ( val1 - val0 ) * distance ) );
147  }
148 
150  const ContinuousIndexType & index) const
151  {
152  IndexType basei;
153 
154  basei[0] = Math::Floor< IndexValueType >(index[0]);
155  if ( basei[0] < this->m_StartIndex[0] )
156  {
157  basei[0] = this->m_StartIndex[0];
158  }
159  const InternalComputationType & distance0 = index[0] - static_cast< InternalComputationType >( basei[0] );
160 
161  basei[1] = Math::Floor< IndexValueType >(index[1]);
162  if ( basei[1] < this->m_StartIndex[1] )
163  {
164  basei[1] = this->m_StartIndex[1];
165  }
166  const InternalComputationType & distance1 = index[1] - static_cast< InternalComputationType >( basei[1] );
167 
168  const TInputImage * const inputImagePtr = this->GetInputImage();
169  const RealType & val00 = inputImagePtr->GetPixel(basei);
170  if ( distance0 <= 0. && distance1 <= 0. )
171  {
172  return ( static_cast< OutputType >( val00 ) );
173  }
174  else if ( distance1 <= 0. ) // if they have the same "y"
175  {
176  ++basei[0]; // then interpolate across "x"
177  if ( basei[0] > this->m_EndIndex[0] )
178  {
179  return ( static_cast< OutputType >( val00 ) );
180  }
181  const RealType & val10 = inputImagePtr->GetPixel(basei);
182  return ( static_cast< OutputType >( val00 + ( val10 - val00 ) * distance0 ) );
183  }
184  else if ( distance0 <= 0. ) // if they have the same "x"
185  {
186  ++basei[1]; // then interpolate across "y"
187  if ( basei[1] > this->m_EndIndex[1] )
188  {
189  return ( static_cast< OutputType >( val00 ) );
190  }
191  const RealType & val01 = inputImagePtr->GetPixel(basei);
192  return ( static_cast< OutputType >( val00 + ( val01 - val00 ) * distance1 ) );
193  }
194  // fall-through case:
195  // interpolate across "xy"
196  ++basei[0];
197  if ( basei[0] > this->m_EndIndex[0] ) // interpolate across "y"
198  {
199  --basei[0];
200  ++basei[1];
201  if ( basei[1] > this->m_EndIndex[1] )
202  {
203  return ( static_cast< OutputType >( val00 ) );
204  }
205  const RealType & val01 = inputImagePtr->GetPixel(basei);
206  return ( static_cast< OutputType >( val00 + ( val01 - val00 ) * distance1 ) );
207  }
208  const RealType & val10 = inputImagePtr->GetPixel(basei);
209 
210  const RealType & valx0 = val00 + ( val10 - val00 ) * distance0;
211 
212  ++basei[1];
213  if ( basei[1] > this->m_EndIndex[1] ) // interpolate across "x"
214  {
215  return ( static_cast< OutputType >( valx0 ) );
216  }
217  const RealType & val11 = inputImagePtr->GetPixel(basei);
218  --basei[0];
219  const RealType & val01 = inputImagePtr->GetPixel(basei);
220 
221  const RealType & valx1 = val01 + ( val11 - val01 ) * distance0;
222 
223  return ( static_cast< OutputType >( valx0 + ( valx1 - valx0 ) * distance1 ) );
224  }
225 
227  const ContinuousIndexType & index) const
228  {
229  IndexType basei;
230  basei[0] = Math::Floor< IndexValueType >(index[0]);
231  if ( basei[0] < this->m_StartIndex[0] )
232  {
233  basei[0] = this->m_StartIndex[0];
234  }
235  const InternalComputationType & distance0 = index[0] - static_cast< InternalComputationType >( basei[0] );
236 
237  basei[1] = Math::Floor< IndexValueType >(index[1]);
238  if ( basei[1] < this->m_StartIndex[1] )
239  {
240  basei[1] = this->m_StartIndex[1];
241  }
242  const InternalComputationType & distance1 = index[1] - static_cast< InternalComputationType >( basei[1] );
243 
244  basei[2] = Math::Floor< IndexValueType >(index[2]);
245  if ( basei[2] < this->m_StartIndex[2] )
246  {
247  basei[2] = this->m_StartIndex[2];
248  }
249  const InternalComputationType & distance2 = index[2] - static_cast< InternalComputationType >( basei[2] );
250 
251  const TInputImage * const inputImagePtr = this->GetInputImage();
252  const RealType & val000 = inputImagePtr->GetPixel(basei);
253  if ( distance0 <= 0. && distance1 <= 0. && distance2 <= 0. )
254  {
255  return ( static_cast< OutputType >( val000 ) );
256  }
257 
258  if ( distance2 <= 0. )
259  {
260  if ( distance1 <= 0. ) // interpolate across "x"
261  {
262  ++basei[0];
263  if ( basei[0] > this->m_EndIndex[0] )
264  {
265  return ( static_cast< OutputType >( val000 ) );
266  }
267  const RealType & val100 = inputImagePtr->GetPixel(basei);
268 
269  return static_cast< OutputType >( val000 + ( val100 - val000 ) * distance0 );
270  }
271  else if ( distance0 <= 0. ) // interpolate across "y"
272  {
273  ++basei[1];
274  if ( basei[1] > this->m_EndIndex[1] )
275  {
276  return ( static_cast< OutputType >( val000 ) );
277  }
278  const RealType & val010 = inputImagePtr->GetPixel(basei);
279 
280  return static_cast< OutputType >( val000 + ( val010 - val000 ) * distance1 );
281  }
282  else // interpolate across "xy"
283  {
284  ++basei[0];
285  if ( basei[0] > this->m_EndIndex[0] ) // interpolate across "y"
286  {
287  --basei[0];
288  ++basei[1];
289  if ( basei[1] > this->m_EndIndex[1] )
290  {
291  return ( static_cast< OutputType >( val000 ) );
292  }
293  const RealType & val010 = inputImagePtr->GetPixel(basei);
294  return static_cast< OutputType >( val000 + ( val010 - val000 ) * distance1 );
295  }
296  const RealType & val100 = inputImagePtr->GetPixel(basei);
297  const RealType & valx00 = val000 + ( val100 - val000 ) * distance0;
298 
299  ++basei[1];
300  if ( basei[1] > this->m_EndIndex[1] ) // interpolate across "x"
301  {
302  return ( static_cast< OutputType >( valx00 ) );
303  }
304  const RealType & val110 = inputImagePtr->GetPixel(basei);
305 
306  --basei[0];
307  const RealType & val010 = inputImagePtr->GetPixel(basei);
308  const RealType & valx10 = val010 + ( val110 - val010 ) * distance0;
309 
310  return static_cast< OutputType >( valx00 + ( valx10 - valx00 ) * distance1 );
311  }
312  }
313  else
314  {
315  if ( distance1 <= 0. )
316  {
317  if ( distance0 <= 0. ) // interpolate across "z"
318  {
319  ++basei[2];
320  if ( basei[2] > this->m_EndIndex[2] )
321  {
322  return ( static_cast< OutputType >( val000 ) );
323  }
324  const RealType & val001 = inputImagePtr->GetPixel(basei);
325 
326  return static_cast< OutputType >( val000 + ( val001 - val000 ) * distance2 );
327  }
328  else // interpolate across "xz"
329  {
330  ++basei[0];
331  if ( basei[0] > this->m_EndIndex[0] ) // interpolate across "z"
332  {
333  --basei[0];
334  ++basei[2];
335  if ( basei[2] > this->m_EndIndex[2] )
336  {
337  return ( static_cast< OutputType >( val000 ) );
338  }
339  const RealType & val001 = inputImagePtr->GetPixel(basei);
340 
341  return static_cast< OutputType >( val000 + ( val001 - val000 ) * distance2 );
342  }
343  const RealType & val100 = inputImagePtr->GetPixel(basei);
344 
345  const RealType & valx00 = val000 + ( val100 - val000 ) * distance0;
346 
347  ++basei[2];
348  if ( basei[2] > this->m_EndIndex[2] ) // interpolate across "x"
349  {
350  return ( static_cast< OutputType >( valx00 ) );
351  }
352  const RealType & val101 = inputImagePtr->GetPixel(basei);
353 
354  --basei[0];
355  const RealType & val001 = inputImagePtr->GetPixel(basei);
356 
357  const RealType & valx01 = val001 + ( val101 - val001 ) * distance0;
358 
359  return static_cast< OutputType >( valx00 + ( valx01 - valx00 ) * distance2 );
360  }
361  }
362  else if ( distance0 <= 0. ) // interpolate across "yz"
363  {
364  ++basei[1];
365  if ( basei[1] > this->m_EndIndex[1] ) // interpolate across "z"
366  {
367  --basei[1];
368  ++basei[2];
369  if ( basei[2] > this->m_EndIndex[2] )
370  {
371  return ( static_cast< OutputType >( val000 ) );
372  }
373  const RealType & val001 = inputImagePtr->GetPixel(basei);
374 
375  return static_cast< OutputType >( val000 + ( val001 - val000 ) * distance2 );
376  }
377  const RealType & val010 = inputImagePtr->GetPixel(basei);
378 
379  const RealType & val0x0 = val000 + ( val010 - val000 ) * distance1;
380 
381  ++basei[2];
382  if ( basei[2] > this->m_EndIndex[2] ) // interpolate across "y"
383  {
384  return ( static_cast< OutputType >( val0x0 ) );
385  }
386  const RealType & val011 = inputImagePtr->GetPixel(basei);
387 
388  --basei[1];
389  const RealType & val001 = inputImagePtr->GetPixel(basei);
390 
391  const RealType & val0x1 = val001 + ( val011 - val001 ) * distance1;
392 
393  return static_cast< OutputType >( val0x0 + ( val0x1 - val0x0 ) * distance2 );
394  }
395  else // interpolate across "xyz"
396  {
397  ++basei[0];
398  if ( basei[0] > this->m_EndIndex[0] ) // interpolate across "yz"
399  {
400  --basei[0];
401  ++basei[1];
402  if ( basei[1] > this->m_EndIndex[1] ) // interpolate across "z"
403  {
404  --basei[1];
405  ++basei[2];
406  if ( basei[2] > this->m_EndIndex[2] )
407  {
408  return ( static_cast< OutputType >( val000 ) );
409  }
410  const RealType & val001 = inputImagePtr->GetPixel(basei);
411 
412  return static_cast< OutputType >( val000 + ( val001 - val000 ) * distance2 );
413  }
414  const RealType & val010 = inputImagePtr->GetPixel(basei);
415  const RealType & val0x0 = val000 + ( val010 - val000 ) * distance1;
416 
417  ++basei[2];
418  if ( basei[2] > this->m_EndIndex[2] ) // interpolate across "y"
419  {
420  return ( static_cast< OutputType >( val0x0 ) );
421  }
422  const RealType & val011 = inputImagePtr->GetPixel(basei);
423 
424  --basei[1];
425  const RealType & val001 = inputImagePtr->GetPixel(basei);
426 
427  const RealType & val0x1 = val001 + ( val011 - val001 ) * distance1;
428 
429  return static_cast< OutputType >( val0x0 + ( val0x1 - val0x0 ) * distance2 );
430  }
431  const RealType & val100 = inputImagePtr->GetPixel(basei);
432 
433  const RealType & valx00 = val000 + ( val100 - val000 ) * distance0;
434 
435  ++basei[1];
436  if ( basei[1] > this->m_EndIndex[1] ) // interpolate across "xz"
437  {
438  --basei[1];
439  ++basei[2];
440  if ( basei[2] > this->m_EndIndex[2] ) // interpolate across "x"
441  {
442  return ( static_cast< OutputType >( valx00 ) );
443  }
444  const RealType & val101 = inputImagePtr->GetPixel(basei);
445 
446  --basei[0];
447  const RealType & val001 = inputImagePtr->GetPixel(basei);
448 
449  const RealType & valx01 = val001 + ( val101 - val001 ) * distance0;
450 
451  return static_cast< OutputType >( valx00 + ( valx01 - valx00 ) * distance2 );
452  }
453  const RealType & val110 = inputImagePtr->GetPixel(basei);
454 
455  --basei[0];
456  const RealType & val010 = inputImagePtr->GetPixel(basei);
457 
458  const RealType & valx10 = val010 + ( val110 - val010 ) * distance0;
459 
460  const RealType & valxx0 = valx00 + ( valx10 - valx00 ) * distance1;
461 
462  ++basei[2];
463  if ( basei[2] > this->m_EndIndex[2] ) // interpolate across "xy"
464  {
465  return ( static_cast< OutputType >( valxx0 ) );
466  }
467  const RealType & val011 = inputImagePtr->GetPixel(basei);
468 
469  ++basei[0];
470  const RealType & val111 = inputImagePtr->GetPixel(basei);
471 
472  --basei[1];
473  const RealType & val101 = inputImagePtr->GetPixel(basei);
474 
475  --basei[0];
476  const RealType & val001 = inputImagePtr->GetPixel(basei);
477 
478  const RealType & valx01 = val001 + ( val101 - val001 ) * distance0;
479  const RealType & valx11 = val011 + ( val111 - val011 ) * distance0;
480  const RealType & valxx1 = valx01 + ( valx11 - valx01 ) * distance1;
481 
482  return ( static_cast< OutputType >( valxx0 + ( valxx1 - valxx0 ) * distance2 ) );
483  }
484  }
485  }
486 
488  const ContinuousIndexType & index) const
489  {
490  return this->EvaluateUnoptimized(index);
491  }
492 
494  virtual inline OutputType EvaluateUnoptimized(
495  const ContinuousIndexType & index) const;
496 
499  template<typename RealTypeScalarRealType>
500  void
501  MakeZeroInitializer(const TInputImage * const inputImagePtr,
503  {
504  // Variable length vector version to get the size of the pixel correct.
505  typename TInputImage::IndexType idx;
506  idx.Fill(0);
507  const typename TInputImage::PixelType & tempPixel = inputImagePtr->GetPixel(idx);
508  const unsigned int sizeOfVarLengthVector = tempPixel.GetSize();
509  tempZeros.SetSize(sizeOfVarLengthVector);
511  }
512 
513  template<typename RealTypeScalarRealType>
514  void
515  MakeZeroInitializer(const TInputImage * const itkNotUsed( inputImagePtr ),
516  RealTypeScalarRealType & tempZeros) const
517  {
518  // All other cases
520  }
521 
522 };
523 } // end namespace itk
524 
525 #ifndef ITK_MANUAL_INSTANTIATION
526 #include "itkLinearInterpolateImageFunction.hxx"
527 #endif
528 
529 #endif
OutputType EvaluateOptimized(const DispatchBase &, const ContinuousIndexType &index) const
Light weight base class for most itk classes.
typename Superclass::ContinuousIndexType ContinuousIndexType
void MakeZeroInitializer(const TInputImage *const , RealTypeScalarRealType &tempZeros) const
Define numeric traits for std::vector.
typename Superclass::OutputType OutputType
void MakeZeroInitializer(const TInputImage *const inputImagePtr, VariableLengthVector< RealTypeScalarRealType > &tempZeros) const
A method to generically set all components to zero.
OutputType EvaluateAtContinuousIndex(const ContinuousIndexType &index) const override
typename NumericTraits< typename TInputImage::PixelType >::RealType RealType
typename Superclass::IndexType IndexType
Represents an array whose length can be defined at run-time.
Linearly interpolate an image at specified positions.
Base class for all image interpolaters.
typename Superclass::InputPixelType InputPixelType
typename Superclass::InputImageType InputImageType
void Fill(IndexValueType value)
Definition: itkIndex.h:257
Control indentation during Print() invocation.
Definition: itkIndent.h:49
OutputType EvaluateOptimized(const Dispatch< 1 > &, const ContinuousIndexType &index) const
void SetSize(unsigned int sz, TReallocatePolicy reallocatePolicy, TKeepValuesPolicy keepValues)
OutputType EvaluateOptimized(const Dispatch< 0 > &, const ContinuousIndexType &) const
void Fill(TValue const &v)
typename ContinuousIndexType::ValueType InternalComputationType
OutputType EvaluateOptimized(const Dispatch< 3 > &, const ContinuousIndexType &index) const
OutputType EvaluateOptimized(const Dispatch< 2 > &, const ContinuousIndexType &index) const