ITK  5.2.0
Insight Toolkit
itkLinearInterpolateImageFunction.h
Go to the documentation of this file.
1 /*=========================================================================
2  *
3  * Copyright NumFOCUS
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 {
49 template <typename TInputImage, typename TCoordRep = double>
50 class ITK_TEMPLATE_EXPORT LinearInterpolateImageFunction : public InterpolateImageFunction<TInputImage, TCoordRep>
51 {
52 public:
53  ITK_DISALLOW_COPY_AND_MOVE(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 SizeType = typename Superclass::SizeType;
87 
89  using ContinuousIndexType = typename Superclass::ContinuousIndexType;
90  using InternalComputationType = typename ContinuousIndexType::ValueType;
91 
100  OutputType
101  EvaluateAtContinuousIndex(const ContinuousIndexType & index) const override
102  {
103  return this->EvaluateOptimized(Dispatch<ImageDimension>(), index);
104  }
105 
106  SizeType
107  GetRadius() const override
108  {
109  return SizeType::Filled(1);
110  }
111 
112 protected:
113  LinearInterpolateImageFunction() = default;
114  ~LinearInterpolateImageFunction() override = default;
115  void
116  PrintSelf(std::ostream & os, Indent indent) const override;
117 
118 private:
120  {};
121  template <unsigned int>
122  struct Dispatch : public DispatchBase
123  {};
124 
125  inline OutputType
127  {
128  return 0;
129  }
130 
131  inline OutputType
132  EvaluateOptimized(const Dispatch<1> &, const ContinuousIndexType & index) const
133  {
134  IndexType basei;
135  basei[0] = Math::Floor<IndexValueType>(index[0]);
136  if (basei[0] < this->m_StartIndex[0])
137  {
138  basei[0] = this->m_StartIndex[0];
139  }
140 
141  const InternalComputationType & distance = index[0] - static_cast<InternalComputationType>(basei[0]);
142 
143  const TInputImage * const inputImagePtr = this->GetInputImage();
144  const RealType & val0 = inputImagePtr->GetPixel(basei);
145  if (distance <= 0.)
146  {
147  return (static_cast<OutputType>(val0));
148  }
149 
150  ++basei[0];
151  if (basei[0] > this->m_EndIndex[0])
152  {
153  return (static_cast<OutputType>(val0));
154  }
155  const RealType & val1 = inputImagePtr->GetPixel(basei);
156 
157  return (static_cast<OutputType>(val0 + (val1 - val0) * distance));
158  }
159 
160  inline OutputType
161  EvaluateOptimized(const Dispatch<2> &, const ContinuousIndexType & index) const
162  {
163  IndexType basei;
164 
165  basei[0] = Math::Floor<IndexValueType>(index[0]);
166  if (basei[0] < this->m_StartIndex[0])
167  {
168  basei[0] = this->m_StartIndex[0];
169  }
170  const InternalComputationType & distance0 = index[0] - static_cast<InternalComputationType>(basei[0]);
171 
172  basei[1] = Math::Floor<IndexValueType>(index[1]);
173  if (basei[1] < this->m_StartIndex[1])
174  {
175  basei[1] = this->m_StartIndex[1];
176  }
177  const InternalComputationType & distance1 = index[1] - static_cast<InternalComputationType>(basei[1]);
178 
179  const TInputImage * const inputImagePtr = this->GetInputImage();
180  const RealType & val00 = inputImagePtr->GetPixel(basei);
181  if (distance0 <= 0. && distance1 <= 0.)
182  {
183  return (static_cast<OutputType>(val00));
184  }
185  else if (distance1 <= 0.) // if they have the same "y"
186  {
187  ++basei[0]; // then interpolate across "x"
188  if (basei[0] > this->m_EndIndex[0])
189  {
190  return (static_cast<OutputType>(val00));
191  }
192  const RealType & val10 = inputImagePtr->GetPixel(basei);
193  return (static_cast<OutputType>(val00 + (val10 - val00) * distance0));
194  }
195  else if (distance0 <= 0.) // if they have the same "x"
196  {
197  ++basei[1]; // then interpolate across "y"
198  if (basei[1] > this->m_EndIndex[1])
199  {
200  return (static_cast<OutputType>(val00));
201  }
202  const RealType & val01 = inputImagePtr->GetPixel(basei);
203  return (static_cast<OutputType>(val00 + (val01 - val00) * distance1));
204  }
205  // fall-through case:
206  // interpolate across "xy"
207  ++basei[0];
208  if (basei[0] > this->m_EndIndex[0]) // interpolate across "y"
209  {
210  --basei[0];
211  ++basei[1];
212  if (basei[1] > this->m_EndIndex[1])
213  {
214  return (static_cast<OutputType>(val00));
215  }
216  const RealType & val01 = inputImagePtr->GetPixel(basei);
217  return (static_cast<OutputType>(val00 + (val01 - val00) * distance1));
218  }
219  const RealType & val10 = inputImagePtr->GetPixel(basei);
220 
221  const RealType & valx0 = val00 + (val10 - val00) * distance0;
222 
223  ++basei[1];
224  if (basei[1] > this->m_EndIndex[1]) // interpolate across "x"
225  {
226  return (static_cast<OutputType>(valx0));
227  }
228  const RealType & val11 = inputImagePtr->GetPixel(basei);
229  --basei[0];
230  const RealType & val01 = inputImagePtr->GetPixel(basei);
231 
232  const RealType & valx1 = val01 + (val11 - val01) * distance0;
233 
234  return (static_cast<OutputType>(valx0 + (valx1 - valx0) * distance1));
235  }
236 
237  inline OutputType
238  EvaluateOptimized(const Dispatch<3> &, const ContinuousIndexType & index) const
239  {
240  IndexType basei;
241  basei[0] = Math::Floor<IndexValueType>(index[0]);
242  if (basei[0] < this->m_StartIndex[0])
243  {
244  basei[0] = this->m_StartIndex[0];
245  }
246  const InternalComputationType & distance0 = index[0] - static_cast<InternalComputationType>(basei[0]);
247 
248  basei[1] = Math::Floor<IndexValueType>(index[1]);
249  if (basei[1] < this->m_StartIndex[1])
250  {
251  basei[1] = this->m_StartIndex[1];
252  }
253  const InternalComputationType & distance1 = index[1] - static_cast<InternalComputationType>(basei[1]);
254 
255  basei[2] = Math::Floor<IndexValueType>(index[2]);
256  if (basei[2] < this->m_StartIndex[2])
257  {
258  basei[2] = this->m_StartIndex[2];
259  }
260  const InternalComputationType & distance2 = index[2] - static_cast<InternalComputationType>(basei[2]);
261 
262  const TInputImage * const inputImagePtr = this->GetInputImage();
263  const RealType & val000 = inputImagePtr->GetPixel(basei);
264  if (distance0 <= 0. && distance1 <= 0. && distance2 <= 0.)
265  {
266  return (static_cast<OutputType>(val000));
267  }
268 
269  if (distance2 <= 0.)
270  {
271  if (distance1 <= 0.) // interpolate across "x"
272  {
273  ++basei[0];
274  if (basei[0] > this->m_EndIndex[0])
275  {
276  return (static_cast<OutputType>(val000));
277  }
278  const RealType & val100 = inputImagePtr->GetPixel(basei);
279 
280  return static_cast<OutputType>(val000 + (val100 - val000) * distance0);
281  }
282  else if (distance0 <= 0.) // interpolate across "y"
283  {
284  ++basei[1];
285  if (basei[1] > this->m_EndIndex[1])
286  {
287  return (static_cast<OutputType>(val000));
288  }
289  const RealType & val010 = inputImagePtr->GetPixel(basei);
290 
291  return static_cast<OutputType>(val000 + (val010 - val000) * distance1);
292  }
293  else // interpolate across "xy"
294  {
295  ++basei[0];
296  if (basei[0] > this->m_EndIndex[0]) // interpolate across "y"
297  {
298  --basei[0];
299  ++basei[1];
300  if (basei[1] > this->m_EndIndex[1])
301  {
302  return (static_cast<OutputType>(val000));
303  }
304  const RealType & val010 = inputImagePtr->GetPixel(basei);
305  return static_cast<OutputType>(val000 + (val010 - val000) * distance1);
306  }
307  const RealType & val100 = inputImagePtr->GetPixel(basei);
308  const RealType & valx00 = val000 + (val100 - val000) * distance0;
309 
310  ++basei[1];
311  if (basei[1] > this->m_EndIndex[1]) // interpolate across "x"
312  {
313  return (static_cast<OutputType>(valx00));
314  }
315  const RealType & val110 = inputImagePtr->GetPixel(basei);
316 
317  --basei[0];
318  const RealType & val010 = inputImagePtr->GetPixel(basei);
319  const RealType & valx10 = val010 + (val110 - val010) * distance0;
320 
321  return static_cast<OutputType>(valx00 + (valx10 - valx00) * distance1);
322  }
323  }
324  else
325  {
326  if (distance1 <= 0.)
327  {
328  if (distance0 <= 0.) // interpolate across "z"
329  {
330  ++basei[2];
331  if (basei[2] > this->m_EndIndex[2])
332  {
333  return (static_cast<OutputType>(val000));
334  }
335  const RealType & val001 = inputImagePtr->GetPixel(basei);
336 
337  return static_cast<OutputType>(val000 + (val001 - val000) * distance2);
338  }
339  else // interpolate across "xz"
340  {
341  ++basei[0];
342  if (basei[0] > this->m_EndIndex[0]) // interpolate across "z"
343  {
344  --basei[0];
345  ++basei[2];
346  if (basei[2] > this->m_EndIndex[2])
347  {
348  return (static_cast<OutputType>(val000));
349  }
350  const RealType & val001 = inputImagePtr->GetPixel(basei);
351 
352  return static_cast<OutputType>(val000 + (val001 - val000) * distance2);
353  }
354  const RealType & val100 = inputImagePtr->GetPixel(basei);
355 
356  const RealType & valx00 = val000 + (val100 - val000) * distance0;
357 
358  ++basei[2];
359  if (basei[2] > this->m_EndIndex[2]) // interpolate across "x"
360  {
361  return (static_cast<OutputType>(valx00));
362  }
363  const RealType & val101 = inputImagePtr->GetPixel(basei);
364 
365  --basei[0];
366  const RealType & val001 = inputImagePtr->GetPixel(basei);
367 
368  const RealType & valx01 = val001 + (val101 - val001) * distance0;
369 
370  return static_cast<OutputType>(valx00 + (valx01 - valx00) * distance2);
371  }
372  }
373  else if (distance0 <= 0.) // interpolate across "yz"
374  {
375  ++basei[1];
376  if (basei[1] > this->m_EndIndex[1]) // interpolate across "z"
377  {
378  --basei[1];
379  ++basei[2];
380  if (basei[2] > this->m_EndIndex[2])
381  {
382  return (static_cast<OutputType>(val000));
383  }
384  const RealType & val001 = inputImagePtr->GetPixel(basei);
385 
386  return static_cast<OutputType>(val000 + (val001 - val000) * distance2);
387  }
388  const RealType & val010 = inputImagePtr->GetPixel(basei);
389 
390  const RealType & val0x0 = val000 + (val010 - val000) * distance1;
391 
392  ++basei[2];
393  if (basei[2] > this->m_EndIndex[2]) // interpolate across "y"
394  {
395  return (static_cast<OutputType>(val0x0));
396  }
397  const RealType & val011 = inputImagePtr->GetPixel(basei);
398 
399  --basei[1];
400  const RealType & val001 = inputImagePtr->GetPixel(basei);
401 
402  const RealType & val0x1 = val001 + (val011 - val001) * distance1;
403 
404  return static_cast<OutputType>(val0x0 + (val0x1 - val0x0) * distance2);
405  }
406  else // interpolate across "xyz"
407  {
408  ++basei[0];
409  if (basei[0] > this->m_EndIndex[0]) // interpolate across "yz"
410  {
411  --basei[0];
412  ++basei[1];
413  if (basei[1] > this->m_EndIndex[1]) // interpolate across "z"
414  {
415  --basei[1];
416  ++basei[2];
417  if (basei[2] > this->m_EndIndex[2])
418  {
419  return (static_cast<OutputType>(val000));
420  }
421  const RealType & val001 = inputImagePtr->GetPixel(basei);
422 
423  return static_cast<OutputType>(val000 + (val001 - val000) * distance2);
424  }
425  const RealType & val010 = inputImagePtr->GetPixel(basei);
426  const RealType & val0x0 = val000 + (val010 - val000) * distance1;
427 
428  ++basei[2];
429  if (basei[2] > this->m_EndIndex[2]) // interpolate across "y"
430  {
431  return (static_cast<OutputType>(val0x0));
432  }
433  const RealType & val011 = inputImagePtr->GetPixel(basei);
434 
435  --basei[1];
436  const RealType & val001 = inputImagePtr->GetPixel(basei);
437 
438  const RealType & val0x1 = val001 + (val011 - val001) * distance1;
439 
440  return static_cast<OutputType>(val0x0 + (val0x1 - val0x0) * distance2);
441  }
442  const RealType & val100 = inputImagePtr->GetPixel(basei);
443 
444  const RealType & valx00 = val000 + (val100 - val000) * distance0;
445 
446  ++basei[1];
447  if (basei[1] > this->m_EndIndex[1]) // interpolate across "xz"
448  {
449  --basei[1];
450  ++basei[2];
451  if (basei[2] > this->m_EndIndex[2]) // interpolate across "x"
452  {
453  return (static_cast<OutputType>(valx00));
454  }
455  const RealType & val101 = inputImagePtr->GetPixel(basei);
456 
457  --basei[0];
458  const RealType & val001 = inputImagePtr->GetPixel(basei);
459 
460  const RealType & valx01 = val001 + (val101 - val001) * distance0;
461 
462  return static_cast<OutputType>(valx00 + (valx01 - valx00) * distance2);
463  }
464  const RealType & val110 = inputImagePtr->GetPixel(basei);
465 
466  --basei[0];
467  const RealType & val010 = inputImagePtr->GetPixel(basei);
468 
469  const RealType & valx10 = val010 + (val110 - val010) * distance0;
470 
471  const RealType & valxx0 = valx00 + (valx10 - valx00) * distance1;
472 
473  ++basei[2];
474  if (basei[2] > this->m_EndIndex[2]) // interpolate across "xy"
475  {
476  return (static_cast<OutputType>(valxx0));
477  }
478  const RealType & val011 = inputImagePtr->GetPixel(basei);
479 
480  ++basei[0];
481  const RealType & val111 = inputImagePtr->GetPixel(basei);
482 
483  --basei[1];
484  const RealType & val101 = inputImagePtr->GetPixel(basei);
485 
486  --basei[0];
487  const RealType & val001 = inputImagePtr->GetPixel(basei);
488 
489  const RealType & valx01 = val001 + (val101 - val001) * distance0;
490  const RealType & valx11 = val011 + (val111 - val011) * distance0;
491  const RealType & valxx1 = valx01 + (valx11 - valx01) * distance1;
492 
493  return (static_cast<OutputType>(valxx0 + (valxx1 - valxx0) * distance2));
494  }
495  }
496  }
497 
498  inline OutputType
499  EvaluateOptimized(const DispatchBase &, const ContinuousIndexType & index) const
500  {
501  return this->EvaluateUnoptimized(index);
502  }
503 
505  virtual inline OutputType
506  EvaluateUnoptimized(const ContinuousIndexType & index) const;
507 
510  template <typename RealTypeScalarRealType>
511  void
512  MakeZeroInitializer(const TInputImage * const inputImagePtr,
514  {
515  // Variable length vector version to get the size of the pixel correct.
516  typename TInputImage::IndexType idx;
517  idx.Fill(0);
518  const typename TInputImage::PixelType & tempPixel = inputImagePtr->GetPixel(idx);
519  const unsigned int sizeOfVarLengthVector = tempPixel.GetSize();
520  tempZeros.SetSize(sizeOfVarLengthVector);
522  }
523 
524  template <typename RealTypeScalarRealType>
525  void
526  MakeZeroInitializer(const TInputImage * const itkNotUsed(inputImagePtr), RealTypeScalarRealType & tempZeros) const
527  {
528  // All other cases
530  }
531 };
532 } // end namespace itk
533 
534 #ifndef ITK_MANUAL_INSTANTIATION
535 # include "itkLinearInterpolateImageFunction.hxx"
536 #endif
537 
538 #endif
itk::VariableLengthVector::Fill
void Fill(TValue const &v)
itk::InterpolateImageFunction::SizeType
typename InputImageType::SizeType SizeType
Definition: itkInterpolateImageFunction.h:79
itk::LinearInterpolateImageFunction::EvaluateOptimized
OutputType EvaluateOptimized(const DispatchBase &, const ContinuousIndexType &index) const
Definition: itkLinearInterpolateImageFunction.h:499
itkVariableLengthVector.h
itk::LinearInterpolateImageFunction::EvaluateOptimized
OutputType EvaluateOptimized(const Dispatch< 3 > &, const ContinuousIndexType &index) const
Definition: itkLinearInterpolateImageFunction.h:238
itk::VariableLengthVector::SetSize
void SetSize(unsigned int sz, TReallocatePolicy reallocatePolicy, TKeepValuesPolicy keepValues)
itk::GTest::TypedefsAndConstructors::Dimension2::SizeType
ImageBaseType::SizeType SizeType
Definition: itkGTestTypedefsAndConstructors.h:49
itk::LinearInterpolateImageFunction::EvaluateOptimized
OutputType EvaluateOptimized(const Dispatch< 2 > &, const ContinuousIndexType &index) const
Definition: itkLinearInterpolateImageFunction.h:161
itk::SmartPointer< Self >
itk::Indent
Control indentation during Print() invocation.
Definition: itkIndent.h:49
itk::LinearInterpolateImageFunction::MakeZeroInitializer
void MakeZeroInitializer(const TInputImage *const, RealTypeScalarRealType &tempZeros) const
Definition: itkLinearInterpolateImageFunction.h:526
itk::Index::Fill
void Fill(IndexValueType value)
Definition: itkIndex.h:270
itk::GTest::TypedefsAndConstructors::Dimension2::IndexType
ImageBaseType::IndexType IndexType
Definition: itkGTestTypedefsAndConstructors.h:50
itk::LinearInterpolateImageFunction
Linearly interpolate an image at specified positions.
Definition: itkLinearInterpolateImageFunction.h:50
itk::LightObject
Light weight base class for most itk classes.
Definition: itkLightObject.h:59
itk::LinearInterpolateImageFunction::InternalComputationType
typename ContinuousIndexType::ValueType InternalComputationType
Definition: itkLinearInterpolateImageFunction.h:90
itk::LinearInterpolateImageFunction::MakeZeroInitializer
void MakeZeroInitializer(const TInputImage *const inputImagePtr, VariableLengthVector< RealTypeScalarRealType > &tempZeros) const
A method to generically set all components to zero.
Definition: itkLinearInterpolateImageFunction.h:512
itk::InterpolateImageFunction::ContinuousIndexType
typename Superclass::ContinuousIndexType ContinuousIndexType
Definition: itkInterpolateImageFunction.h:82
itk::LinearInterpolateImageFunction::DispatchBase
Definition: itkLinearInterpolateImageFunction.h:119
itk::InterpolateImageFunction::InputImageType
typename Superclass::InputImageType InputImageType
Definition: itkInterpolateImageFunction.h:66
itk::VariableLengthVector
Represents an array whose length can be defined at run-time.
Definition: itkConstantBoundaryCondition.h:28
itk::NumericTraits
Define additional traits for native types such as int or float.
Definition: itkNumericTraits.h:58
itk::LinearInterpolateImageFunction::InputPixelType
typename Superclass::InputPixelType InputPixelType
Definition: itkLinearInterpolateImageFunction.h:74
itk::NumericTraits::ZeroValue
static T ZeroValue()
Definition: itkNumericTraits.h:148
itk::LinearInterpolateImageFunction::Dispatch
Definition: itkLinearInterpolateImageFunction.h:122
itk::InterpolateImageFunction::OutputType
typename Superclass::OutputType OutputType
Definition: itkInterpolateImageFunction.h:63
itk
The "itk" namespace contains all Insight Segmentation and Registration Toolkit (ITK) classes....
Definition: itkAnnulusOperator.h:24
itk::LinearInterpolateImageFunction::GetRadius
SizeType GetRadius() const override
Definition: itkLinearInterpolateImageFunction.h:107
itkInterpolateImageFunction.h
itk::LinearInterpolateImageFunction::EvaluateAtContinuousIndex
OutputType EvaluateAtContinuousIndex(const ContinuousIndexType &index) const override
Definition: itkLinearInterpolateImageFunction.h:101
itk::LinearInterpolateImageFunction::EvaluateOptimized
OutputType EvaluateOptimized(const Dispatch< 0 > &, const ContinuousIndexType &) const
Definition: itkLinearInterpolateImageFunction.h:126
itk::InterpolateImageFunction
Base class for all image interpolators.
Definition: itkInterpolateImageFunction.h:45
itk::LinearInterpolateImageFunction::EvaluateOptimized
OutputType EvaluateOptimized(const Dispatch< 1 > &, const ContinuousIndexType &index) const
Definition: itkLinearInterpolateImageFunction.h:132
itk::InterpolateImageFunction::IndexType
typename Superclass::IndexType IndexType
Definition: itkInterpolateImageFunction.h:75
itk::InterpolateImageFunction::RealType
typename NumericTraits< typename TInputImage::PixelType >::RealType RealType
Definition: itkInterpolateImageFunction.h:85