1 /*
2 * Medical Image Registration ToolKit (MIRTK)
3 *
4 * Copyright 2013-2015 Imperial College London
5 * Copyright 2013-2015 Andreas Schuh
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 #ifndef MIRTK_ExtrapolateImageFunction_H
21 #define MIRTK_ExtrapolateImageFunction_H
22
23 #include "mirtk/ExtrapolationMode.h"
24 #include "mirtk/Vector.h"
25 #include "mirtk/VoxelCast.h"
26 #include "mirtk/BaseImage.h"
27 #include "mirtk/ImageFunction.h"
28
29
30 namespace mirtk {
31
32
33 /**
34 * Abstract base class for discrete image extrapolation
35 *
36 * This abstract base class defines a common interface for image functions
37 * which provide a value at each discrete image location, especially also
38 * those which are outside the finite domain on which the image is defined.
39 * At these outside voxels, the image function extrapolates the image values,
40 * thus extending an image function to an infinite discrete lattice. An image
41 * extrapolate image function is mainly used indirectly through an instance of
42 * InterpolateImageFunction. Image values at continuous voxel positions
43 * are interpolated by the interpolate image function using the extrapolated
44 * image values at discrete lattice points.
45 */
46 class ExtrapolateImageFunction : public ImageFunction
47 {
48 mirtkAbstractMacro(ExtrapolateImageFunction);
49
50 // ---------------------------------------------------------------------------
51 // Construction/Destruction
52
53 protected:
54
55 /// Default constructor
56 ExtrapolateImageFunction();
57
58 public:
59
60 /// Destructor
61 virtual ~ExtrapolateImageFunction();
62
63 /// Construct extrapolator or return NULL if \p mode is \c Extrapolation_None
64 static ExtrapolateImageFunction *New(ExtrapolationMode mode,
65 const BaseImage * = NULL);
66
67 // ---------------------------------------------------------------------------
68 // Initialization
69
70 /// Get extrapolation mode corresponding to this extrapolator
71 virtual enum ExtrapolationMode ExtrapolationMode() const = 0;
72
73 // ---------------------------------------------------------------------------
74 // Emulation of selected BaseImage functions
75
76 // The following wrapper functions enable the subclasses of
77 // InterpolateImageFunction to use a template function for the
78 // implementation of EvaluateInside and EvaluateOutside where the only
79 // difference is the image type used to access the image values.
80
81 const ImageAttributes &Attributes() const; ///< Attributes of input image
82
83 int X() const; ///< Size of input image in x dimension
84 int Y() const; ///< Size of input image in y dimension
85 int Z() const; ///< Size of input image in z dimension
86 int T() const; ///< Size of input image in t dimension
87 int N() const; ///< Number of vector components per image voxel
88
89 double XSize() const; ///< Voxel size of input image in x dimension
90 double YSize() const; ///< Voxel size of input image in y dimension
91 double ZSize() const; ///< Voxel size of input image in z dimension
92 double TSize() const; ///< Voxel size of input image in t dimension
93
94 /// Whether the extrapolated value is identical to the background
95 /// value of the input image. If the input uses a background mask
96 /// instead, only subclasses of IndexExtrapolateImageFunction
97 /// can determine whether the voxel at the transformed location
98 /// is in the foreground region.
99 virtual bool IsForeground(int, int, int = 0, int = 0) const;
100
101 // ---------------------------------------------------------------------------
102 // Image function interface
103
104 /// Get scalar image value at the nearest discrete image location
105 double Evaluate(double, double, double = 0, double = 0) const;
106
107 /// Get scalar image value at the nearest discrete image location
108 virtual double Evaluate(double, double, double = 0, double = 0);
109
110 // ---------------------------------------------------------------------------
111 // Extrapolation of discrete image function
112
113 /// Get scalar image value at an arbitrary discrete image location
114 double GetAsDouble(int) const;
115
116 /// Get scalar image value at an arbitrary discrete image location
117 virtual double GetAsDouble(int, int, int = 0, int = 0) const = 0;
118
119 /// Get vector image value at an arbitrary discrete image location
120 Vector GetAsVector(int) const;
121
122 /// Get vector image value at an arbitrary discrete image location
123 Vector GetAsVector(int, int, int = 0, int = 0) const;
124
125 /// Get vector image value at an arbitrary discrete image location
126 void GetAsVector(Vector &, int) const;
127
128 /// Get vector image value at an arbitrary discrete image location
129 virtual void GetAsVector(Vector &, int, int, int = 0, int = 0) const = 0;
130
131 };
132
133 ////////////////////////////////////////////////////////////////////////////////
134 // Generic extrapolation interface
135 ////////////////////////////////////////////////////////////////////////////////
136
137 /**
138 * Generic base class for image extrapolation functions
139 *
140 * This base class is templated over the type of the input image to be extrapolated
141 * and thus subclasses can make use of image voxel type specific (non-virtual)
142 * getters to access the image data. No conversion of the voxel type to a uniform
143 * voxel type such as double scalar or vector type is required when the type of
144 * the image to be extrapolated is known. Otherwise, if the image type is unknown,
145 * use the abstract ExtrapolateImageFunction interface instead.
146 *
147 * \sa ExtrapolateImageFunction
148 */
149 template <class TImage>
150 class GenericExtrapolateImageFunction : public ExtrapolateImageFunction
151 {
152 mirtkAbstractMacro(GenericExtrapolateImageFunction);
153
154 // ---------------------------------------------------------------------------
155 // Types
156
157 public:
158
159 typedef TImage ImageType; ///< Input image type
160 typedef typename ImageType::VoxelType VoxelType; ///< Input voxel type
161 typedef typename ImageType::RealType RealType; ///< Compatible floating-point type
162
163 // ---------------------------------------------------------------------------
164 // Construction/Destruction
165
166 protected:
167
168 /// Default constructor
169 GenericExtrapolateImageFunction();
170
171 public:
172
173 /// Destructor
174 virtual ~GenericExtrapolateImageFunction();
175
176 /// Construct extrapolator or return NULL if \p mode is \c Extrapolation_None
177 static GenericExtrapolateImageFunction *New(enum ExtrapolationMode,
178 const TImage * = NULL);
179
180 // ---------------------------------------------------------------------------
181 // Initialization
182
183 /// Set input image
184 virtual void Input(const BaseImage *);
185
186 /// Get input image
187 const ImageType *Input() const;
188
189 /// Initialize image function
190 virtual void Initialize();
191
192 // ---------------------------------------------------------------------------
193 // Extrapolation of discrete image function
194
195 /// Get image value at an arbitrary discrete image location
196 VoxelType Get(int) const;
197
198 /// Get image value at an arbitrary discrete image location
199 virtual VoxelType Get(int, int, int = 0, int = 0) const = 0;
200
201 /// Get image value at an arbitrary discrete image location
202 VoxelType operator ()(int) const;
203
204 /// Get image value at an arbitrary discrete image location
205 VoxelType operator ()(int, int, int = 0, int = 0) const;
206
207 // Import overloaded non-virtual member functions from base class
208 using ExtrapolateImageFunction::GetAsDouble;
209 using ExtrapolateImageFunction::GetAsVector;
210
211 /// Get scalar image value at an arbitrary discrete image location
212 double GetAsDouble(int, int, int = 0, int = 0) const;
213
214 /// Get vector image value at an arbitrary discrete image location
215 void GetAsVector(Vector &, int, int, int = 0, int = 0) const;
216
217 };
218
219 ////////////////////////////////////////////////////////////////////////////////
220 // Index extrapolation interface
221 ////////////////////////////////////////////////////////////////////////////////
222
223 /**
224 * Base class for generic voxel index extrapolation functions
225 *
226 * This abstract class is the base for extrapolate image functions which map
227 * any given discrete voxel coordinate to one, which is inside the finite image
228 * domain. The extrapolation function assigns the image value at the resulting
229 * voxel coordinate to the initially mapped discrete voxel.
230 *
231 * This base class is templated over the type of the input image to be extrapolated
232 * and thus subclasses can make use of image voxel type specific (non-virtual)
233 * getters to access the image data. No conversion of the voxel type to a uniform
234 * voxel type such as double scalar or vector type is required when the type of
235 * the image to be extrapolated is known. Otherwise, if the image type is unknown,
236 * use the abstract ExtrapolateImageFunction interface instead.
237 *
238 * \sa ExtrapolateImageFunction
239 */
240 template <class TImage>
241 class IndexExtrapolateImageFunction
242 : public GenericExtrapolateImageFunction<TImage>
243 {
244 mirtkAbstractMacro(IndexExtrapolateImageFunction);
245
246 // ---------------------------------------------------------------------------
247 // Types
248
249 public:
250
251 typedef TImage ImageType; ///< Input image type
252 typedef typename ImageType::VoxelType VoxelType; ///< Input voxel type
253 typedef typename ImageType::RealType RealType; ///< Compatible floating-point type
254
255 // ---------------------------------------------------------------------------
256 // Attributes
257
258 protected:
259
260 int _xmax; ///< Maximum index in x dimension
261 int _ymax; ///< Maximum index in y dimension
262 int _zmax; ///< Maximum index in z dimension
263 int _tmax; ///< Maximum index in t dimension
264
265 // ---------------------------------------------------------------------------
266 // Construction/Destruction
267
268 protected:
269
270 /// Default constructor
271 IndexExtrapolateImageFunction();
272
273 public:
274
275 /// Destructor
276 virtual ~IndexExtrapolateImageFunction();
277
278 // ---------------------------------------------------------------------------
279 // Initialization
280
281 /// Initialize image function
282 virtual void Initialize();
283
284 // ---------------------------------------------------------------------------
285 // Voxel index transformation
286
287 /// Transform voxel index such that it is inside the range [0, max]
288 ///
289 /// \param[in,out] idx Voxel index.
290 /// \param[in] max Maximum voxel index.
291 virtual void TransformIndex(int &idx, int max) const = 0;
292
293 /// Transform voxel index in x dimension
294 void TransformX(int &) const;
295
296 /// Transform voxel index in y dimension
297 void TransformY(int &) const;
298
299 /// Transform voxel index in z dimension
300 void TransformZ(int &) const;
301
302 /// Transform voxel index in t dimension
303 virtual void TransformT(int &l) const;
304
305 /// Transform voxel index in x dimension
306 void TransformX(int &, int) const;
307
308 /// Transform voxel index in y dimension
309 void TransformY(int &, int) const;
310
311 /// Transform voxel index in z dimension
312 void TransformZ(int &, int) const;
313
314 /// Transform voxel index in t dimension
315 virtual void TransformT(int &l, int c) const;
316
317 /// Transform 2D voxel index
318 void Transform(int &, int &) const;
319
320 /// Transform 3D voxel index
321 void Transform(int &, int &, int &) const;
322
323 /// Transform 4D voxel index
324 void Transform(int &, int &, int &, int &) const;
325
326 // ---------------------------------------------------------------------------
327 // Extrapolation of discrete image function
328
329 /// Whether voxel whose value is used is inside the foreground
330 virtual bool IsForeground(int, int, int = 0, int = 0) const;
331
332 // Import overloaded non-virtual member functions from base class
333 using GenericExtrapolateImageFunction<TImage>::Get;
334
335 /// Get image value at an arbitrary discrete image location
336 virtual VoxelType Get(int, int, int = 0, int = 0) const;
337
338 };
339
340 ////////////////////////////////////////////////////////////////////////////////
341 // Auxiliary macro for subclass implementation
342 ////////////////////////////////////////////////////////////////////////////////
343
344 // -----------------------------------------------------------------------------
345 #define mirtkExtrapolatorMacro(clsname, mode) \
346 mirtkObjectMacro(clsname); \
347 public: \
348 /** Get extrapolation mode implemented by this extrapolator */ \
349 inline virtual enum ExtrapolationMode ExtrapolationMode() const \
350 { return mode; } \
351 /** Get extrapolation mode implemented by this class */ \
352 inline static enum ExtrapolationMode ExtrapolationType() \
353 { return mode; } \
354 private:
355
356 // -----------------------------------------------------------------------------
357 #define mirtkGenericExtrapolatorMacro(clsname, mode) \
358 mirtkExtrapolatorMacro(clsname, mode); \
359 public: \
360 /** Input image type */ \
361 typedef TImage ImageType; \
362 /** Input voxel type */ \
363 typedef typename ImageType::VoxelType VoxelType; \
364 /** Compatible floating-point type */ \
365 typedef typename ImageType::RealType RealType; \
366 /* Import overloaded non-virtual member functions from base class */ \
367 using GenericExtrapolateImageFunction<TImage>::Get; \
368 private:
369
370 ////////////////////////////////////////////////////////////////////////////////
371 // Inline definitions -- ExtrapolateImageFunction
372 ////////////////////////////////////////////////////////////////////////////////
373
374 // -----------------------------------------------------------------------------
Attributes()375 inline const ImageAttributes &ExtrapolateImageFunction::Attributes() const
376 {
377 return Input()->Attributes();
378 }
379
380 // -----------------------------------------------------------------------------
X()381 inline int ExtrapolateImageFunction::X() const
382 {
383 return Input()->X();
384 }
385
386 // -----------------------------------------------------------------------------
Y()387 inline int ExtrapolateImageFunction::Y() const
388 {
389 return Input()->Y();
390 }
391
392 // -----------------------------------------------------------------------------
Z()393 inline int ExtrapolateImageFunction::Z() const
394 {
395 return Input()->Z();
396 }
397
398 // -----------------------------------------------------------------------------
T()399 inline int ExtrapolateImageFunction::T() const
400 {
401 return Input()->T();
402 }
403
404 // -----------------------------------------------------------------------------
N()405 inline int ExtrapolateImageFunction::N() const
406 {
407 return Input()->N();
408 }
409
410 // -----------------------------------------------------------------------------
XSize()411 inline double ExtrapolateImageFunction::XSize() const
412 {
413 return Input()->XSize();
414 }
415
416 // -----------------------------------------------------------------------------
YSize()417 inline double ExtrapolateImageFunction::YSize() const
418 {
419 return Input()->YSize();
420 }
421
422 // -----------------------------------------------------------------------------
ZSize()423 inline double ExtrapolateImageFunction::ZSize() const
424 {
425 return Input()->ZSize();
426 }
427
428 // -----------------------------------------------------------------------------
TSize()429 inline double ExtrapolateImageFunction::TSize() const
430 {
431 return Input()->TSize();
432 }
433
434 // -----------------------------------------------------------------------------
435 inline double ExtrapolateImageFunction
Evaluate(double x,double y,double z,double t)436 ::Evaluate(double x, double y, double z, double t) const
437 {
438 return this->GetAsDouble(static_cast<int>(round(x)),
439 static_cast<int>(round(y)),
440 static_cast<int>(round(z)),
441 static_cast<int>(round(t)));
442 }
443
444 // -----------------------------------------------------------------------------
445 inline double ExtrapolateImageFunction
Evaluate(double x,double y,double z,double t)446 ::Evaluate(double x, double y, double z, double t)
447 {
448 return const_cast<const ExtrapolateImageFunction *>(this)->Evaluate(x, y, z, t);
449 }
450
451 // -----------------------------------------------------------------------------
GetAsDouble(int i,int j,int k,int l)452 inline double ExtrapolateImageFunction::GetAsDouble(int i, int j, int k, int l) const
453 {
454 // Must be implemented by subclass
455 return this->_DefaultValue;
456 }
457
458 // -----------------------------------------------------------------------------
GetAsDouble(int idx)459 inline double ExtrapolateImageFunction::GetAsDouble(int idx) const
460 {
461 int i, j, k, l;
462 Input()->IndexToVoxel(idx, i, j, k, l);
463 return this->GetAsDouble(i, j, k, l);
464 }
465
466 // -----------------------------------------------------------------------------
467 inline void ExtrapolateImageFunction
GetAsVector(Vector & v,int i,int j,int k,int l)468 ::GetAsVector(Vector &v, int i, int j, int k, int l) const
469 {
470 // Must be implemented by subclass
471 v = Vector(N(), this->_DefaultValue);
472 }
473
474 // -----------------------------------------------------------------------------
GetAsVector(int i,int j,int k,int l)475 inline Vector ExtrapolateImageFunction::GetAsVector(int i, int j, int k, int l) const
476 {
477 Vector v;
478 this->GetAsVector(v, i, j, k, l);
479 return v;
480 }
481
482 // -----------------------------------------------------------------------------
GetAsVector(Vector & v,int idx)483 inline void ExtrapolateImageFunction::GetAsVector(Vector &v, int idx) const
484 {
485 int i, j, k, l;
486 Input()->IndexToVoxel(idx, i, j, k, l);
487 this->GetAsVector(v, i, j, k, l);
488 }
489
490 // -----------------------------------------------------------------------------
GetAsVector(int idx)491 inline Vector ExtrapolateImageFunction::GetAsVector(int idx) const
492 {
493 Vector v;
494 this->GetAsVector(v, idx);
495 return v;
496 }
497
498 // -----------------------------------------------------------------------------
IsForeground(int i,int j,int k,int l)499 inline bool ExtrapolateImageFunction::IsForeground(int i, int j, int k, int l) const
500 {
501 if (!this->Input()->HasBackgroundValue()) return true;
502 const double value = this->GetAsDouble(i, j, k, l);
503 const double bg = this->Input()->GetBackgroundValueAsDouble();
504 return (value != bg && (!IsNaN(value) || !IsNaN(bg)));
505 }
506
507 ////////////////////////////////////////////////////////////////////////////////
508 // Inline definitions -- GenericExtrapolateImageFunction
509 ////////////////////////////////////////////////////////////////////////////////
510
511 // -----------------------------------------------------------------------------
512 template <class TImage>
513 inline GenericExtrapolateImageFunction<TImage>
GenericExtrapolateImageFunction()514 ::GenericExtrapolateImageFunction()
515 {
516 }
517
518 // -----------------------------------------------------------------------------
519 template <class TImage>
520 inline GenericExtrapolateImageFunction<TImage>
~GenericExtrapolateImageFunction()521 ::~GenericExtrapolateImageFunction()
522 {
523 }
524
525 // -----------------------------------------------------------------------------
526 template <class TImage>
527 inline void GenericExtrapolateImageFunction<TImage>
Input(const BaseImage * input)528 ::Input(const BaseImage *input)
529 {
530 ExtrapolateImageFunction::Input(dynamic_cast<const ImageType *>(input));
531 if (input && !this->_Input) {
532 cerr << this->NameOfClass() << "::Input: Invalid input image type" << endl;
533 exit(1);
534 }
535 }
536
537 // -----------------------------------------------------------------------------
538 template <class TImage>
Input()539 inline const TImage *GenericExtrapolateImageFunction<TImage>::Input() const
540 {
541 return reinterpret_cast<const TImage *>(this->_Input);
542 }
543
544 // -----------------------------------------------------------------------------
545 template <class TImage>
Initialize()546 inline void GenericExtrapolateImageFunction<TImage>::Initialize()
547 {
548 // Initialize base class
549 ExtrapolateImageFunction::Initialize();
550 // Check type of input image -- also done by Input(const BaseImage *),
551 // but just in case SetInput() has been used.
552 if (!dynamic_cast<const ImageType *>(this->_Input)) {
553 cerr << this->NameOfClass() << "::Initialize: Invalid input image type" << endl;
554 exit(1);
555 }
556 }
557
558 // -----------------------------------------------------------------------------
559 template <class TImage>
560 inline typename GenericExtrapolateImageFunction<TImage>::VoxelType
Get(int i,int j,int k,int l)561 GenericExtrapolateImageFunction<TImage>::Get(int i, int j, int k, int l) const
562 {
563 // Must be implemented by subclass
564 return voxel_cast<VoxelType>(this->_DefaultValue);
565 }
566
567 // -----------------------------------------------------------------------------
568 template <class TImage>
569 inline typename GenericExtrapolateImageFunction<TImage>::VoxelType
Get(int idx)570 GenericExtrapolateImageFunction<TImage>::Get(int idx) const
571 {
572 int i, j, k, l;
573 Input()->IndexToVoxel(idx, i, j, k, l);
574 return this->Get(i, j, k, l);
575 }
576
577 // -----------------------------------------------------------------------------
578 template <class TImage>
579 inline typename GenericExtrapolateImageFunction<TImage>::VoxelType
operator()580 GenericExtrapolateImageFunction<TImage>::operator ()(int idx) const
581 {
582 return this->Get(idx);
583 }
584
585 // -----------------------------------------------------------------------------
586 template <class TImage>
587 inline typename GenericExtrapolateImageFunction<TImage>::VoxelType
588 GenericExtrapolateImageFunction<TImage>
operator()589 ::operator ()(int i, int j, int k, int l) const
590 {
591 return this->Get(i, j, k, l);
592 }
593
594 // -----------------------------------------------------------------------------
595 template <class TImage>
596 inline double GenericExtrapolateImageFunction<TImage>
GetAsDouble(int i,int j,int k,int l)597 ::GetAsDouble(int i, int j, int k, int l) const
598 {
599 return voxel_cast<double>(this->Get(i, j, k, l));
600 }
601
602 // -----------------------------------------------------------------------------
603 template <class TImage>
604 inline void GenericExtrapolateImageFunction<TImage>
GetAsVector(Vector & v,int i,int j,int k,int l)605 ::GetAsVector(Vector &v, int i, int j, int k, int l) const
606 {
607 v = voxel_cast<Vector>(this->Get(i, j, k, l));
608 }
609
610 ////////////////////////////////////////////////////////////////////////////////
611 // Inline definitions -- IndexExtrapolateImageFunction
612 ////////////////////////////////////////////////////////////////////////////////
613
614 // -----------------------------------------------------------------------------
615 template <class TImage>
IndexExtrapolateImageFunction()616 IndexExtrapolateImageFunction<TImage>::IndexExtrapolateImageFunction()
617 :
618 _xmax(0), _ymax(0), _zmax(0), _tmax(0)
619 {
620 }
621
622 // -----------------------------------------------------------------------------
623 template <class TImage>
~IndexExtrapolateImageFunction()624 IndexExtrapolateImageFunction<TImage>::~IndexExtrapolateImageFunction()
625 {
626 }
627
628 // -----------------------------------------------------------------------------
629 template <class TImage>
Initialize()630 void IndexExtrapolateImageFunction<TImage>::Initialize()
631 {
632 // Initialize base class
633 GenericExtrapolateImageFunction<TImage>::Initialize();
634 // Get range of indices
635 _xmax = this->X() - 1;
636 _ymax = this->Y() - 1;
637 _zmax = this->Z() - 1;
638 _tmax = this->T() - 1;
639 }
640
641 // -----------------------------------------------------------------------------
642 template <class TImage>
TransformX(int & i)643 void IndexExtrapolateImageFunction<TImage>::TransformX(int &i) const
644 {
645 this->TransformIndex(i, _xmax);
646 }
647
648 // -----------------------------------------------------------------------------
649 template <class TImage>
TransformY(int & j)650 void IndexExtrapolateImageFunction<TImage>::TransformY(int &j) const
651 {
652 this->TransformIndex(j, _ymax);
653 }
654
655 // -----------------------------------------------------------------------------
656 template <class TImage>
TransformZ(int & k)657 void IndexExtrapolateImageFunction<TImage>::TransformZ(int &k) const
658 {
659 this->TransformIndex(k, _zmax);
660 }
661
662 // -----------------------------------------------------------------------------
663 template <class TImage>
TransformT(int & l)664 void IndexExtrapolateImageFunction<TImage>::TransformT(int &l) const
665 {
666 this->TransformIndex(l, _tmax);
667 }
668
669 // -----------------------------------------------------------------------------
670 template <class TImage>
TransformX(int & i,int c)671 void IndexExtrapolateImageFunction<TImage>::TransformX(int &i, int c) const
672 {
673 i = c;
674 this->TransformIndex(i, _xmax);
675 }
676
677 // -----------------------------------------------------------------------------
678 template <class TImage>
TransformY(int & j,int c)679 void IndexExtrapolateImageFunction<TImage>::TransformY(int &j, int c) const
680 {
681 j = c;
682 this->TransformIndex(j, _ymax);
683 }
684
685 // -----------------------------------------------------------------------------
686 template <class TImage>
TransformZ(int & k,int c)687 void IndexExtrapolateImageFunction<TImage>::TransformZ(int &k, int c) const
688 {
689 k = c;
690 this->TransformIndex(k, _zmax);
691 }
692
693 // -----------------------------------------------------------------------------
694 template <class TImage>
TransformT(int & l,int c)695 void IndexExtrapolateImageFunction<TImage>::TransformT(int &l, int c) const
696 {
697 l = c;
698 this->TransformIndex(l, _tmax);
699 }
700
701 // -----------------------------------------------------------------------------
702 template <class TImage>
Transform(int & i,int & j)703 void IndexExtrapolateImageFunction<TImage>::Transform(int &i, int &j) const
704 {
705 TransformX(i);
706 TransformY(j);
707 }
708
709 // -----------------------------------------------------------------------------
710 template <class TImage>
Transform(int & i,int & j,int & k)711 void IndexExtrapolateImageFunction<TImage>::Transform(int &i, int &j, int &k) const
712 {
713 TransformX(i);
714 TransformY(j);
715 TransformZ(k);
716 }
717
718 // -----------------------------------------------------------------------------
719 template <class TImage>
Transform(int & i,int & j,int & k,int & l)720 void IndexExtrapolateImageFunction<TImage>::Transform(int &i, int &j, int &k, int &l) const
721 {
722 TransformX(i);
723 TransformY(j);
724 TransformZ(k);
725 TransformT(l);
726 }
727
728 // -----------------------------------------------------------------------------
729 template <class TImage>
730 inline bool IndexExtrapolateImageFunction<TImage>
IsForeground(int i,int j,int k,int l)731 ::IsForeground(int i, int j, int k, int l) const
732 {
733 Transform(i, j, k, l);
734 return this->Input()->IsForeground(i, j, k, l);
735 }
736
737 // -----------------------------------------------------------------------------
738 template <class TImage>
739 inline typename IndexExtrapolateImageFunction<TImage>::VoxelType
Get(int i,int j,int k,int l)740 IndexExtrapolateImageFunction<TImage>::Get(int i, int j, int k, int l) const
741 {
742 Transform(i, j, k, l);
743 return this->Input()->Get(i, j, k, l);
744 }
745
746
747 } // namespace mirtk
748
749 ////////////////////////////////////////////////////////////////////////////////
750 // Extrapolation functions
751 ////////////////////////////////////////////////////////////////////////////////
752
753 #include "mirtk/ConstExtrapolateImageFunction.h"
754 #include "mirtk/ConstExtrapolateImageFunctionWithPeriodicTime.h"
755 #include "mirtk/NearestNeighborExtrapolateImageFunction.h"
756 #include "mirtk/RepeatExtrapolateImageFunction.h"
757 #include "mirtk/MirrorExtrapolateImageFunction.h"
758
759 ////////////////////////////////////////////////////////////////////////////////
760 // Instantiation
761 ////////////////////////////////////////////////////////////////////////////////
762
763 namespace mirtk {
764
765
766 // -----------------------------------------------------------------------------
767 template <class TImage>
768 GenericExtrapolateImageFunction<TImage> *
769 GenericExtrapolateImageFunction<TImage>
New(enum ExtrapolationMode mode,const TImage * image)770 ::New(enum ExtrapolationMode mode, const TImage *image)
771 {
772 GenericExtrapolateImageFunction<TImage> *p = NULL;
773 switch (mode) {
774 case Extrapolation_None: { p = NULL; break; }
775 case Extrapolation_Const: { p = new GenericConstExtrapolateImageFunction <TImage>(); break; }
776 case Extrapolation_NN: { p = new GenericNearestNeighborExtrapolateImageFunction<TImage>(); break; }
777 case Extrapolation_Repeat: { p = new GenericRepeatExtrapolateImageFunction <TImage>(); break; }
778 case Extrapolation_Mirror: { p = new GenericMirrorExtrapolateImageFunction <TImage>(); break; }
779 case Extrapolation_ConstWithPeriodicTime:
780 p = new GenericConstExtrapolateImageFunctionWithPeriodicTime<TImage>();
781 break;
782 default:
783 cerr << "GenericExtrapolateImageFunction::New: Unknown extrapolation mode: " << mode << endl;
784 exit(1);
785 }
786 if (p) p->Input(image);
787 return p;
788 }
789
790
791 } // namespace mirtk
792
793 #endif // MIRTK_ExtrapolateImageFunction_H
794