ImageRegion.h
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_ImageRegion_H
21 #define MIRTK_ImageRegion_H
22 
23 #include "mirtk/Voxel.h"
24 #include "mirtk/Parallel.h"
25 #include "mirtk/Vector4D.h"
26 #include "mirtk/GenericImage.h"
27 #include "mirtk/Stream.h"
28 
29 
30 namespace mirtk {
31 
32 
33 ////////////////////////////////////////////////////////////////////////////////
34 // Local macros (undefined again at end of this file)
35 ////////////////////////////////////////////////////////////////////////////////
36 
37 // -----------------------------------------------------------------------------
38 // All get Next/Prev pointer method overloads
39 #define _NextPrevMethod(name, stride) \
40  template <class T> \
41  inline const T *Next##name(const T *&p) const { return p + stride; } \
42  template <class T> \
43  inline T *Next##name(T *&p) const { return p + stride; } \
44  template <class T> \
45  inline const T *Prev##name(const T *&p) const { return p - stride; } \
46  template <class T> \
47  inline T *Prev##name(T *&p) const { return p - stride; }
48 
49 // -----------------------------------------------------------------------------
50 // ToNext/ToPrev method with one image pointer argument
51 #define _ToMethod1(name, op, stride) \
52  template <class T> \
53  inline void To##name(const T *&p) const { p = p op stride; } \
54  template <class T> \
55  inline void To##name(T *&p) const { p = p op stride; }
56 
57 // -----------------------------------------------------------------------------
58 // ToNext/ToPrev method with two image pointer arguments
59 #define _ToMethod2(name, op, stride) \
60  template <class T1, class T2> \
61  inline void To##name(const T1 *&p1, const T2 *&p2) const \
62  { p1 = p1 op stride; p2 = p2 op stride; } \
63  template <class T1, class T2> \
64  inline void To##name(const T1 *&p1, T2 *&p2) const \
65  { p1 = p1 op stride; p2 = p2 op stride; } \
66  template <class T1, class T2> \
67  inline void To##name(T1 *&p1, const T2 *&p2) const \
68  { p1 = p1 op stride; p2 = p2 op stride; } \
69  template <class T1, class T2> \
70  inline void To##name(T1 *&p1, T2 *&p2) const \
71  { p1 = p1 op stride; p2 = p2 op stride; }
72 
73 // -----------------------------------------------------------------------------
74 // ToNext/ToPrev method with three image pointer arguments
75 #define _ToMethod3(name, op, stride) \
76  template <class T1, class T2, class T3> \
77  inline void To##name(const T1 *&p1, const T2 *&p2, const T3 *&p3) const \
78  { p1 = p1 op stride; p2 = p2 op stride; p3 = p3 op stride; } \
79  template <class T1, class T2, class T3> \
80  inline void To##name(const T1 *&p1, const T2 *&p2, T3 *&p3) const \
81  { p1 = p1 op stride; p2 = p2 op stride; p3 = p3 op stride; } \
82  template <class T1, class T2, class T3> \
83  inline void To##name(const T1 *&p1, T2 *&p2, const T3 *&p3) const \
84  { p1 = p1 op stride; p2 = p2 op stride; p3 = p3 op stride; } \
85  template <class T1, class T2, class T3> \
86  inline void To##name(const T1 *&p1, T2 *&p2, T3 *&p3) const \
87  { p1 = p1 op stride; p2 = p2 op stride; p3 = p3 op stride; } \
88  template <class T1, class T2, class T3> \
89  inline void To##name(T1 *&p1, const T2 *&p2, const T3 *&p3) const \
90  { p1 = p1 op stride; p2 = p2 op stride; p3 = p3 op stride; } \
91  template <class T1, class T2, class T3> \
92  inline void To##name(T1 *&p1, const T2 *&p2, T3 *&p3) const \
93  { p1 = p1 op stride; p2 = p2 op stride; p3 = p3 op stride; } \
94  template <class T1, class T2, class T3> \
95  inline void To##name(T1 *&p1, T2 *&p2, const T3 *&p3) const \
96  { p1 = p1 op stride; p2 = p2 op stride; p3 = p3 op stride; } \
97  template <class T1, class T2, class T3> \
98  inline void To##name(T1 *&p1, T2 *&p2, T3 *&p3) const \
99  { p1 = p1 op stride; p2 = p2 op stride; p3 = p3 op stride; }
100 
101 // -----------------------------------------------------------------------------
102 // All ToNext/ToPrev method overloads
103 #define _ToMethod(name, stride) \
104  _ToMethod1(Next##name, +, stride) \
105  _ToMethod2(Next##name, +, stride) \
106  _ToMethod3(Next##name, +, stride) \
107  _ToMethod1(Prev##name, -, stride) \
108  _ToMethod2(Prev##name, -, stride) \
109  _ToMethod3(Prev##name, -, stride) \
110 
111 ////////////////////////////////////////////////////////////////////////////////
112 // Fast image iterator declaration
113 ////////////////////////////////////////////////////////////////////////////////
114 
115 /**
116  * Helper for iterating over an image region using raw image pointers
117  *
118  * This class makes it convenient to set a specific image region using one or
119  * more of the many available setter methods and calculates the start and end
120  * index of the first and last voxel in the region. Moreover, it computes how
121  * many voxels have to be skipped when moving from one line of the image to
122  * another, from one slice to another, or from one frame of an image sequence
123  * to another. It therefore helps to iterate over the set image region using
124  * a pointer to the image data. This makes the low-level iteration of an image
125  * using such fast image pointers more convenient to implement.
126  *
127  * An instance of this class does not keep track of the current position of the
128  * image pointer. It can therefore not tell when it reached the end of a line,
129  * slice, or image frame/channel. This lies yet in the responsibility of the user.
130  *
131  * Note that a single instance can (and for the sake of speed should be) used
132  * to move pointers to more than one image if needed. Herefore, all images must
133  * have the same size, however. Otherwise, use different instances.
134  *
135  * The following example demonstrates how to iterate over a 5x5x3 neighborhood
136  * of a 3D image centered at voxel (128, 128, 64).
137  * \code
138  * GreyImage im(256, 256, 128);
139  * ImageRegion it(image);
140  *
141  * // Set image region to iterate over
142  * it.SetCenter(128, 128, 64);
143  * it.SetRadius( 5, 5, 3);
144  *
145  * // Get pointer to start of image region
146  * GreyPixel *p = it.GetPointerToBegin(image);
147  *
148  * // Use image iterator to advance pointer from one voxel to the other
149  * // while iterating over the voxels of the set image region
150  * GreyPixel min = MIRTK_MAX_GREY;
151  * GreyPixel max = MIRTK_MIN_GREY;
152  * for (int k = it.BeginZ(); k != it.EndZ(); ++k) {
153  * for (int j = it.BeginY(); j != it.EndY(); ++j) {
154  * for (int i = it.BeginX(); i != it.EndX(); ++i) {
155  * if (*p < min) min = *p;
156  * if (*p > max) max = *p;
157  * it.ToNextColumn(p);
158  * }
159  * it.ToNextLine(p);
160  * }
161  * it.ToNextSlice(p);
162  * }
163  * \endcode
164  *
165  * \sa See ConstImageIterator, ImageIterator, ConstGenericImageIterator,
166  * and GenericImageIterator for more advanced image iterators which do not
167  * require the use of up to four for-loops, but only one while-loop as these
168  * keep track of the position of the iterator themselves and decide with each
169  * increment whether to move the iterator to the next column, line, slice, or
170  * frame/channel. This, however, comes with the expense of more decisions and
171  * operations to be made per voxel and results in a noticeably slower iteration.
172  *
173  * \sa ForEachVoxel template functions for another convenient and fast way of
174  * performing a single operation per voxel. An example of such operation is
175  * the GetMin class which can be used as Operation template argument
176  * of the ForEachVoxel functions. These template functions and basic
177  * voxel-wise operators are defined in the mirtkVoxelFunction.h header file.
178  */
179 
181 {
182 public:
183 
184  // ---------------------------------------------------------------------------
185  // Construction/Destruction
186 
187  /// Constructor
188  ImageRegion(const ImageAttributes &);
189 
190  /// Constructor
192 
193  /// Constructor
195 
196  /// Constructor
197  ImageRegion(const BaseImage &);
198 
199  /// Constructor
200  ImageRegion(const BaseImage &, const blocked_range2d<int> &);
201 
202  /// Constructor
203  ImageRegion(const BaseImage &, const blocked_range3d<int> &);
204 
205  /// Constructor
206  ImageRegion(const BaseImage *);
207 
208  /// Constructor
209  ImageRegion(const BaseImage *, const blocked_range2d<int> &);
210 
211  /// Constructor
212  ImageRegion(const BaseImage *, const blocked_range3d<int> &);
213 
214  /// Copy constructor
215  ImageRegion(const ImageRegion &);
216 
217  /// Assignment operator
219 
220  /// Destructor
221  ~ImageRegion();
222 
223  // ---------------------------------------------------------------------------
224  // Initialization
225 
226  /// Initialize iteration range and calculate strides
227  ///
228  /// This method determines the begin and end indices of the image region and
229  /// reduces the size of the region in each dimension individually if it is
230  /// outside the image domain. Use IsOutside to check if the resulting image
231  /// region is completely outside the image domain and NumberOfVoxels to get
232  /// the actual number of voxels that are within the overlap of the set image
233  /// region and the image domain.
234  ///
235  /// The Initialize method is called by GetPointerToBegin or GetPointerToEnd
236  /// when necessary, i.e., when the image region has been modified. If the
237  /// image pointer is initialized otherwise, the Initialize method has to be
238  /// called explicitly after the region has been specified. Note that the
239  /// constructor initializes the iterator already. Thus, if the region is
240  /// not adjusted after construction of the iterator, there is no need to
241  /// re-initialize it.
242  void Initialize();
243 
244  // ---------------------------------------------------------------------------
245  // Image attributes
246 
247  /// Whether the image is a 3D+t image sequence
248  /// (i.e., number of voxels in t dimension > 1 and dt > 0)
249  bool IsImageSequence() const;
250 
251  /// Whether the image is a scalar image
252  /// (i.e., number of voxels in t dimension is 1)
253  bool IsScalarImage() const;
254 
255  /// Number of voxels in the entire image
256  int NumberOfImageVoxels() const;
257 
258  /// Get number of image channels
259  /// (i.e., number of voxels in t dimension if dt <= 0 or 1 otherwise)
260  int NumberOfImageChannels() const;
261 
262  /// Get number of vector components
263  /// (i.e., number of voxels in t dimension if dt <= 0 or 1 otherwise)
264  int NumberOfVectorComponents() const;
265 
266  /// Get number of iterated frames
267  /// (i.e., number of voxels in t dimension if dt > 0 or 1 otherwise)
268  int NumberOfSequenceFrames() const;
269 
270  // ---------------------------------------------------------------------------
271  // Region attributes
272 
273  /// Whether the image region is a 3D+t image sequence
274  /// (i.e., number of voxels in t dimension > 1 and dt > 0)
275  bool IsSequence() const;
276 
277  /// Whether the image region is scalar
278  /// (i.e., number of voxels in t dimension is 1)
279  bool IsScalar() const;
280 
281  /// Number of voxels in set image region
282  int MaxNumberOfVoxels() const;
283 
284  /// Get number of channels in set image region
285  int MaxNumberOfChannels() const;
286 
287  /// Get number of vector components in set image region
288  int MaxNumberOfComponents() const;
289 
290  /// Get number of frames in set image region
291  int MaxNumberOfFrames() const;
292 
293  /// Number of voxels in overlap of set image region and image domain
294  int NumberOfVoxels() const;
295 
296  /// Get number of channels in overlap of set image region and image domain
297  int NumberOfChannels() const;
298 
299  /// Get number of vector components in overlap of set image region and image domain
300  int NumberOfComponents() const;
301 
302  /// Get number of frames in overlap of set image region and image domain
303  int NumberOfFrames() const;
304 
305  // ---------------------------------------------------------------------------
306  // Region/Neighborhood
307 
308  /// Set start of image region
309  void SetStart(int, int, int = 0, int = -1);
310 
311  /// Set size of image region
312  void SetSize(int);
313 
314  /// Set size of image region
315  void SetSize(int, int, int = 1, int = 1);
316 
317  /// Set center of image region
318  void SetCenter(int, int, int = 0, int = -1);
319 
320  /// Set radius of image region
321  void SetRadius(int);
322 
323  /// Set radius of image region
324  void SetRadius(int, int, int = 0, int = 0);
325 
326  /// Set 2D image region
327  void SetRegion(int, int, int, int);
328 
329  /// Set 2D image region
330  void SetRegion(const blocked_range2d<int> &);
331 
332  /// Set 3D image region
333  void SetRegion(int, int, int, int, int, int);
334 
335  /// Set 3D image region
336  void SetRegion(const blocked_range3d<int> &);
337 
338  /// Set 4D image region
339  void SetRegion(int, int, int, int, int, int, int, int);
340 
341  /// Set 2D neighborhood
342  void SetNeighborhood(int, int, int, int);
343 
344  /// Set 3D neighborhood
345  void SetNeighborhood(int, int, int, int, int, int);
346 
347  /// Set 4D neighborhood
348  void SetNeighborhood(int, int, int, int, int, int, int, int);
349 
350  /// Set temporal region
351  void SetFrame(int);
352 
353  /// Set temporal region
354  void SetFrame(int, int);
355 
356  /// Set temporal region
357  void SetFrame(const blocked_range<int> &);
358 
359  /// Set temporal region
360  void SetChannel(int);
361 
362  /// Set temporal region
363  void SetChannel(int, int);
364 
365  /// Set temporal region
366  void SetChannel(const blocked_range<int> &);
367 
368  /// Set temporal region
369  void SetComponent(int);
370 
371  /// Set temporal region
372  void SetComponent(int, int);
373 
374  /// Set temporal region
375  void SetComponent(const blocked_range<int> &);
376 
377  // ---------------------------------------------------------------------------
378  // Iteration range
379 
380  /// Get start of image region to iterate over in x dimension
381  inline int BeginX() const { return _Begin._x; }
382 
383  /// Get start of image region to iterate over in y dimension
384  inline int BeginY() const { return _Begin._y; }
385 
386  /// Get start of image region to iterate over in z dimension
387  inline int BeginZ() const { return _Begin._z; }
388 
389  /// Get start of image region to iterate over in t dimension
390  inline int BeginT() const { return _Begin._t; }
391 
392  /// Get end of image region to iterate over in x dimension
393  inline int EndX() const { return _End ._x; }
394 
395  /// Get end of image region to iterate over in y dimension
396  inline int EndY() const { return _End ._y; }
397 
398  /// Get end of image region to iterate over in z dimension
399  inline int EndZ() const { return _End ._z; }
400 
401  /// Get end of image region to iterate over in t dimension
402  inline int EndT() const { return _End ._t; }
403 
404  // ---------------------------------------------------------------------------
405  // Strides
406 
407  /// Get stride between columns in number of voxels
408  inline int ColumnStride() const { return 1; }
409 
410  /// Get stride between rows/lines in number of voxels
411  inline int LineStride() const { return _LineStride; }
412 
413  /// Get stride between slices in number of voxels
414  inline int SliceStride() const { return _SliceStride; }
415 
416  /// Get stride between frames in number of voxels
417  inline int FrameStride() const { return _FrameStride; }
418 
419  // ---------------------------------------------------------------------------
420  // Get initial image pointer
421 
422  /// Get raw image pointer to first voxel of of region
423  template <class VoxelType>
424  const VoxelType *GetPointerToBegin(const BaseImage &) const;
425 
426  /// Get raw image pointer to first voxel of of region
427  template <class VoxelType>
428  const VoxelType *GetPointerToBegin(const BaseImage *) const;
429 
430  /// Get raw image pointer to first voxel of of region
431  template <class VoxelType>
432  const VoxelType *GetPointerToBegin(const GenericImage<VoxelType> &) const;
433 
434  /// Get raw image pointer to first voxel of of region
435  template <class VoxelType>
436  VoxelType *GetPointerToBegin(GenericImage<VoxelType> &) const;
437 
438  /// Get raw image pointer to first voxel of of region
439  template <class VoxelType>
440  const VoxelType *GetPointerToBegin(const GenericImage<VoxelType> *) const;
441 
442  /// Get raw image pointer to first voxel of of region
443  template <class VoxelType>
444  VoxelType *GetPointerToBegin(GenericImage<VoxelType> *) const;
445 
446  /// Get raw image pointer to last voxel image of region
447  template <class VoxelType>
448  const VoxelType *GetPointerToEnd(const BaseImage &) const;
449 
450  /// Get raw image pointer to last voxel image of region
451  template <class VoxelType>
452  const VoxelType *GetPointerToEnd(const BaseImage *) const;
453 
454  /// Get raw image pointer to last voxel image of region
455  template <class VoxelType>
456  const VoxelType *GetPointerToEnd(const GenericImage<VoxelType> &) const;
457 
458  /// Get raw image pointer to last voxel image of region
459  template <class VoxelType>
460  VoxelType *GetPointerToEnd(GenericImage<VoxelType> &) const;
461 
462  /// Get raw image pointer to last voxel image of region
463  template <class VoxelType>
464  const VoxelType *GetPointerToEnd(const GenericImage<VoxelType> *) const;
465 
466  /// Get raw image pointer to last voxel image of region
467  template <class VoxelType>
468  VoxelType *GetPointerToEnd(GenericImage<VoxelType> *) const;
469 
470  // ---------------------------------------------------------------------------
471  // Get next/previous image pointer
472 
473  // Declaration and inline definition of Next/Prev methods
474  _NextPrevMethod(Column, 1)
475  _NextPrevMethod(Row, _LineStride)
476  _NextPrevMethod(Line, _LineStride)
477  _NextPrevMethod(Slice, _SliceStride)
478  _NextPrevMethod(Page, _SliceStride)
479  _NextPrevMethod(Channel, _FrameStride)
480  _NextPrevMethod(Component, _FrameStride)
481  _NextPrevMethod(Frame, _FrameStride)
482 
483  // ---------------------------------------------------------------------------
484  // Increment/decrement image pointer
485 
486  // Declaration and inline definition of ToNext/ToPrev methods
487  _ToMethod(Column, 1)
488  _ToMethod(Row, _LineStride)
489  _ToMethod(Line, _LineStride)
490  _ToMethod(Slice, _SliceStride)
491  _ToMethod(Page, _SliceStride)
492  _ToMethod(Channel, _FrameStride)
493  _ToMethod(Component, _FrameStride)
494  _ToMethod(Frame, _FrameStride)
495 
496  // ---------------------------------------------------------------------------
497  // Members
498 protected:
499 
500  // Image attributes
501  Vector4D<int> _DataSize; ///< Size of the entire image
502  bool _IsImageSequence; ///< Whether the image is a sequence
503 
504  // Region attributes
505  Vector4D<int> _Index; ///< Start of set image region
506  Vector4D<int> _Size; ///< Size of set image region
507  Vector4D<int> _Begin; ///< First index of actual image region
508  Vector4D<int> _End; ///< Last index of actual image region
509 
510  // Strides in number of voxels
511  int _LineStride; ///< Increment at end of line in number of voxels
512  int _SliceStride; ///< Increment at end of slice in number of voxels
513  int _FrameStride; ///< Increment at end of frame in number of voxels
514 
515 };
516 
517 //////////////////////////////////////////////////////////////////////////////
518 // Inline definitions
519 //////////////////////////////////////////////////////////////////////////////
520 
521 // ===========================================================================
522 // Initialization
523 // ===========================================================================
524 
525 // ---------------------------------------------------------------------------
527 {
528  // Set iteration range
529  _Begin = _Index;
530  _End = _Index + _Size;
531  // Handle boundary conditions
532  if (_Begin._x < 0) _Begin._x = 0;
533  if (_Begin._y < 0) _Begin._y = 0;
534  if (_Begin._z < 0) _Begin._z = 0;
535  if (_Begin._t < 0) _Begin._t = 0;
536  if (_End ._x > _DataSize._x) _End ._x = _DataSize._x;
537  if (_End ._y > _DataSize._y) _End ._y = _DataSize._y;
538  if (_End ._z > _DataSize._z) _End ._z = _DataSize._z;
539  if (_End ._t > _DataSize._t) _End ._t = _DataSize._t;
540  // Calculate strides in number of voxels
541  const int nx = _End._x - _Begin._x;
542  const int ny = _End._y - _Begin._y;
543  const int nz = _End._z - _Begin._z;
544  _LineStride = (_DataSize._x - nx);
545  _SliceStride = (_DataSize._y - ny) * _DataSize._x - nx;
546  _FrameStride = ((_DataSize._z - nz) * _DataSize._y - ny) * _DataSize._x - nx;
547 }
548 
549 // ===========================================================================
550 // Image attributes
551 // ===========================================================================
552 
553 // ---------------------------------------------------------------------------
554 inline bool ImageRegion::IsImageSequence() const
555 {
556  return _IsImageSequence;
557 }
558 
559 // ---------------------------------------------------------------------------
560 inline bool ImageRegion::IsScalarImage() const
561 {
562  return _DataSize._t == 1;
563 }
564 
565 // ---------------------------------------------------------------------------
567 {
569 }
570 
571 // ---------------------------------------------------------------------------
573 {
574  return _IsImageSequence ? 1 : _DataSize._t;
575 }
576 
577 // ---------------------------------------------------------------------------
579 {
580  return NumberOfImageChannels();
581 }
582 
583 // ---------------------------------------------------------------------------
585 {
586  return _IsImageSequence ? _DataSize._t : 1;
587 }
588 
589 // ===========================================================================
590 // Region attributes
591 // ===========================================================================
592 
593 // ---------------------------------------------------------------------------
594 inline bool ImageRegion::IsSequence() const
595 {
596  return _Size._t > 1 && _IsImageSequence;
597 }
598 
599 // ---------------------------------------------------------------------------
600 inline bool ImageRegion::IsScalar() const
601 {
602  return _Size._t == 1;
603 }
604 
605 // ---------------------------------------------------------------------------
607 {
608  return _Size._x * _Size._y * _Size._z * _Size._t;
609 }
610 
611 // ---------------------------------------------------------------------------
613 {
614  return IsSequence() ? 1 : _Size._t;
615 }
616 
617 // ---------------------------------------------------------------------------
619 {
620  return MaxNumberOfChannels();
621 }
622 
623 // ---------------------------------------------------------------------------
625 {
626  return IsSequence() ? _Size._t : 1;
627 }
628 
629 // ---------------------------------------------------------------------------
630 inline int ImageRegion::NumberOfVoxels() const
631 {
632  return (_End._x - _Begin._x) * (_End._y - _Begin._y) * (_End._z - _Begin._z) * (_End._t - _Begin._t);
633 }
634 
635 // ---------------------------------------------------------------------------
637 {
638  return IsSequence() ? 1 : (_End._t - _Begin._t);
639 }
640 
641 // ---------------------------------------------------------------------------
643 {
644  return NumberOfChannels();
645 }
646 
647 // ---------------------------------------------------------------------------
648 inline int ImageRegion::NumberOfFrames() const
649 {
650  return IsSequence() ? (_End._t - _Begin._t) : 1;
651 }
652 
653 // ===========================================================================
654 // Region
655 // ===========================================================================
656 
657 // ---------------------------------------------------------------------------
658 inline void ImageRegion::SetStart(int i, int j, int k, int l)
659 {
660  _Index._x = i;
661  _Index._y = j;
662  _Index._z = k;
663  if (l >= 0) _Index._t = l;
664  _Begin._x = -1; // mark as invalid
665 }
666 
667 // ---------------------------------------------------------------------------
668 inline void ImageRegion::SetCenter(int i, int j, int k, int l)
669 {
670  _Index._x = i - _Size._x/2;
671  _Index._y = j - _Size._y/2;
672  _Index._z = k - _Size._z/2;
673  if (l >= 0) _Index._t = l;
674  _Begin._x = -1; // mark as invalid
675 }
676 
677 // ---------------------------------------------------------------------------
678 inline void ImageRegion::SetSize(int s)
679 {
680  _Size = s;
681  _Begin._x = -1; // mark as invalid
682 }
683 
684 // ---------------------------------------------------------------------------
685 inline void ImageRegion::SetSize(int ni, int nj, int nk, int nl)
686 {
687  _Size._x = ni;
688  _Size._y = nj;
689  _Size._z = nk;
690  _Size._t = nl;
691  _Begin._x = -1; // mark as invalid
692 }
693 
694 // ---------------------------------------------------------------------------
695 inline void ImageRegion::SetRadius(int r)
696 {
697  _Size = 2 * r + 1;
698  _Begin._x = -1; // mark as invalid
699 }
700 
701 // ---------------------------------------------------------------------------
702 inline void ImageRegion::SetRadius(int ri, int rj, int rk, int rl)
703 {
704  _Size._x = 2 * ri + 1;
705  _Size._y = 2 * rj + 1;
706  _Size._z = 2 * rk + 1;
707  _Size._t = 2 * rl + 1;
708  _Begin._x = -1; // mark as invalid
709 }
710 
711 // ---------------------------------------------------------------------------
712 inline void ImageRegion::SetRegion(int bi, int bj, int ei, int ej)
713 {
714  _Index._x = bi;
715  _Index._y = bj;
716  _Index._z = 0;
717  _Size ._x = ei - bi;
718  _Size ._y = ej - bj;
719  _Size ._z = 1;
720  _Begin._x = -1; // mark as invalid
721 }
722 
723 // ---------------------------------------------------------------------------
725 {
726  SetRegion(r.cols().begin(), r.rows().begin(), r.cols().end(), r.rows().end());
727 }
728 
729 // ---------------------------------------------------------------------------
730 inline void ImageRegion::SetRegion(int bi, int bj, int bk, int ei, int ej, int ek)
731 {
732  _Index._x = bi;
733  _Index._y = bj;
734  _Index._z = bk;
735  _Size ._x = ei - bi;
736  _Size ._y = ej - bj;
737  _Size ._z = ek - bk;
738  _Begin._x = -1; // mark as invalid
739 }
740 
741 // ---------------------------------------------------------------------------
742 inline void ImageRegion::SetRegion(int bi, int bj, int bk, int bl, int ei, int ej, int ek, int el)
743 {
744  _Index._x = bi;
745  _Index._y = bj;
746  _Index._z = bk;
747  _Index._t = bl;
748  _Size ._x = ei - bi;
749  _Size ._y = ej - bj;
750  _Size ._z = ek - bk;
751  _Size ._t = el - bl;
752  _Begin._x = -1; // mark as invalid
753 }
754 
755 // ---------------------------------------------------------------------------
757 {
758  SetRegion(r.cols().begin(), r.rows().begin(), r.pages().begin(),
759  r.cols().end(), r.rows().end(), r.pages().end());
760 }
761 
762 // ---------------------------------------------------------------------------
763 inline void ImageRegion::SetChannel(int l)
764 {
765  if (!_IsImageSequence) {
766  if (l < 0 || l >= _DataSize._t) {
767  cerr << "ImageRegion::SetChannel: Index out of bounds" << endl;
768  exit(1);
769  }
770  _Index._t = l;
771  _Begin._x = -1; // mark as invalid
772  } else if (l != 0) {
773  cerr << "ImageRegion::SetChannel: Index out of bounds (an image sequence can only have one channel)" << endl;
774  exit(1);
775  }
776 }
777 
778 // ---------------------------------------------------------------------------
779 inline void ImageRegion::SetChannel(int bl, int el)
780 {
781  if (!_IsImageSequence) {
782  if (bl < 0 || bl >= _DataSize._t || el < 0 || el >= _DataSize._t) {
783  cerr << "ImageRegion::SetChannel: Index out of bounds" << endl;
784  exit(1);
785  }
786  _Index._t = bl;
787  _Size ._t = el - bl;
788  _Begin._x = -1; // mark as invalid
789  } else if (bl != 0 || el != 0) {
790  cerr << "ImageRegion::SetChannel: Index out of bounds (an image sequence can only have one channel)" << endl;
791  exit(1);
792  }
793 }
794 
795 // ---------------------------------------------------------------------------
797 {
798  SetChannel(r.begin(), r.end());
799 }
800 
801 // ---------------------------------------------------------------------------
802 inline void ImageRegion::SetComponent(int l)
803 {
804  if (!_IsImageSequence) {
805  if (l < 0 || l >= _DataSize._t) {
806  cerr << "ImageRegion::SetComponent: Index out of bounds" << endl;
807  exit(1);
808  }
809  _Index._t = l;
810  _Begin._x = -1; // mark as invalid
811  } else if (l != 0) {
812  cerr << "ImageRegion::SetComponent: Index out of bounds (an image sequence can only have one component)" << endl;
813  exit(1);
814  }
815 }
816 
817 // ---------------------------------------------------------------------------
818 inline void ImageRegion::SetComponent(int bl, int el)
819 {
820  if (!_IsImageSequence) {
821  if (bl < 0 || bl >= _DataSize._t || el < 0 || el >= _DataSize._t) {
822  cerr << "ImageRegion::SetComponent: Index out of bounds" << endl;
823  exit(1);
824  }
825  _Index._t = bl;
826  _Size ._t = el - bl;
827  _Begin._x = -1; // mark as invalid
828  } else if (bl != 0 || el != 0) {
829  cerr << "ImageRegion::SetComponent: Index out of bounds (an image sequence can only have one component)" << endl;
830  exit(1);
831  }
832 }
833 
834 // ---------------------------------------------------------------------------
836 {
837  SetComponent(r.begin(), r.end());
838 }
839 
840 // ---------------------------------------------------------------------------
841 inline void ImageRegion::SetFrame(int l)
842 {
843  if (_IsImageSequence) {
844  if (l < 0 || l >= _DataSize._t) {
845  cerr << "ImageRegion::SetFrame: Index out of bounds" << endl;
846  exit(1);
847  }
848  _Index._t = l;
849  _Begin._x = -1; // mark as invalid
850  } else if (l != 0) {
851  cerr << "ImageRegion::SetFrame: Index out of bounds (image seems to have multiple channels/vector components instead)" << endl;
852  exit(1);
853  }
854 }
855 
856 // ---------------------------------------------------------------------------
857 inline void ImageRegion::SetFrame(int bl, int el)
858 {
859  if (_IsImageSequence) {
860  if (bl < 0 || bl >= _DataSize._t || el < 0 || el >= _DataSize._t) {
861  cerr << "ImageRegion::SetFrame: Index out of bounds" << endl;
862  exit(1);
863  }
864  _Index._t = bl;
865  _Size ._t = el - bl;
866  _Begin._x = -1; // mark as invalid
867  } else if (bl != 0 || el != 0) {
868  cerr << "ImageRegion::SetFrame: Index out of bounds (image seems to have multiple channels/vector components instead)" << endl;
869  exit(1);
870  }
871 }
872 
873 // ---------------------------------------------------------------------------
875 {
876  SetFrame(r.begin(), r.end());
877 }
878 
879 // ===========================================================================
880 // Construction/Destruction
881 // ===========================================================================
882 
883 // ---------------------------------------------------------------------------
885 :
886  _DataSize (attr._x, attr._y, attr._z, attr._t),
887  _IsImageSequence(attr._t > 1 && attr._dt > .0),
888  _Index (0, 0, 0, 0),
889  _Size (attr._x, attr._y, attr._z, attr._t)
890 {
891  Initialize();
892 }
893 
894 // ---------------------------------------------------------------------------
896 :
897  _DataSize (attr._x, attr._y, attr._z, attr._t),
898  _IsImageSequence(attr._t > 1 && attr._dt > .0),
899  _Index (0, 0, 0, 0),
900  _Size (region.cols ().end() - region.cols ().begin(),
901  region.rows ().end() - region.rows ().begin(), 1, 1)
902 {
903  Initialize();
904 }
905 
906 // ---------------------------------------------------------------------------
908 :
909  _DataSize (attr._x, attr._y, attr._z, attr._t),
910  _IsImageSequence(attr._t > 1 && attr._dt > .0),
911  _Index (0, 0, 0, 0),
912  _Size (region.cols ().end() - region.cols ().begin(),
913  region.rows ().end() - region.rows ().begin(),
914  region.pages().end() - region.pages().begin(), 1)
915 {
916  Initialize();
917 }
918 
919 // ---------------------------------------------------------------------------
921 :
922  _DataSize (image.X(), image.Y(), image.Z(), image.T()),
923  _IsImageSequence(image.T() > 1 && image.GetTSize() > .0),
924  _Index (0, 0, 0, 0),
925  _Size (image.X(), image.Y(), image.GetZ(), image.T())
926 {
927  Initialize();
928 }
929 
930 // ---------------------------------------------------------------------------
931 inline ImageRegion::ImageRegion(const BaseImage &image, const blocked_range2d<int> &region)
932 :
933  _DataSize (image.X(), image.Y(), image.Z(), image.T()),
934  _IsImageSequence(image.T() > 1 && image.GetTSize() > .0),
935  _Index (0, 0, 0, 0),
936  _Size (region.cols ().end() - region.cols ().begin(),
937  region.rows ().end() - region.rows ().begin(), 1, 1)
938 {
939  Initialize();
940 }
941 
942 // ---------------------------------------------------------------------------
943 inline ImageRegion::ImageRegion(const BaseImage &image, const blocked_range3d<int> &region)
944 :
945  _DataSize (image.X(), image.Y(), image.Z(), image.T()),
946  _IsImageSequence(image.T() > 1 && image.GetTSize() > .0),
947  _Index (0, 0, 0, 0),
948  _Size (region.cols ().end() - region.cols ().begin(),
949  region.rows ().end() - region.rows ().begin(),
950  region.pages().end() - region.pages().begin(), 1)
951 {
952  Initialize();
953 }
954 
955 // ---------------------------------------------------------------------------
957 :
958  _DataSize (image->X(), image->Y(), image->Z(), image->T()),
959  _IsImageSequence(image->T() > 1 && image->GetTSize() > .0),
960  _Index (0, 0, 0, 0),
961  _Size (image->X(), image->Y(), image->Z(), image->T())
962 {
963  Initialize();
964 }
965 
966 // ---------------------------------------------------------------------------
967 inline ImageRegion::ImageRegion(const BaseImage *image, const blocked_range2d<int> &region)
968 :
969  _DataSize (image->X(), image->Y(), image->Z(), image->T()),
970  _IsImageSequence(image->T() > 1 && image->GetTSize() > .0),
971  _Index (0, 0, 0, 0),
972  _Size (region.cols ().end() - region.cols ().begin(),
973  region.rows ().end() - region.rows ().begin(), 1, 1)
974 {
975  Initialize();
976 }
977 
978 // ---------------------------------------------------------------------------
979 inline ImageRegion::ImageRegion(const BaseImage *image, const blocked_range3d<int> &region)
980 :
981  _DataSize (image->X(), image->Y(), image->Z(), image->T()),
982  _IsImageSequence(image->T() > 1 && image->GetTSize() > .0),
983  _Index (0, 0, 0, 0),
984  _Size (region.cols ().end() - region.cols ().begin(),
985  region.rows ().end() - region.rows ().begin(),
986  region.pages().end() - region.pages().begin(), 1)
987 {
988  Initialize();
989 }
990 
991 // ---------------------------------------------------------------------------
993 :
994  _DataSize (other._DataSize),
996  _Index (other._Index),
997  _Size (other._Size),
998  _Begin (other._Begin),
999  _End (other._End),
1000  _LineStride (other._LineStride),
1001  _SliceStride (other._SliceStride),
1002  _FrameStride (other._FrameStride)
1003 {
1004 }
1005 
1006 // ---------------------------------------------------------------------------
1008 {
1009  _DataSize = rhs._DataSize;
1011  _Index = rhs._Index;
1012  _Size = rhs._Size;
1013  _Begin = rhs._Begin;
1014  _End = rhs._End;
1015  _LineStride = rhs._LineStride;
1016  _SliceStride = rhs._SliceStride;
1017  _FrameStride = rhs._FrameStride;
1018  return *this;
1019 }
1020 
1021 // ---------------------------------------------------------------------------
1023 {
1024 }
1025 
1026 // =============================================================================
1027 // Initialize image pointer
1028 // =============================================================================
1029 
1030 // -----------------------------------------------------------------------------
1031 template <class VoxelType>
1032 inline const VoxelType *ImageRegion::GetPointerToBegin(const BaseImage &image) const
1033 {
1034  if (image.GetScalarType() != voxel_info<VoxelType>::type()) {
1035  cerr << "ImageRegion::GetPointerToBegin: Type of image differs from VoxelType template argument" << endl;
1036  exit(1);
1037  }
1038  if (_Begin._x < 0) const_cast<ImageRegion *>(this)->Initialize();
1039  return reinterpret_cast<const VoxelType *>(image.GetScalarPointer(_Begin._x, _Begin._y, _Begin._z, _Begin._t));
1040 }
1041 
1042 // -----------------------------------------------------------------------------
1043 template <class VoxelType>
1044 inline const VoxelType *ImageRegion::GetPointerToBegin(const BaseImage *image) const
1045 {
1046  if (image->GetScalarType() != voxel_info<VoxelType>::type()) {
1047  cerr << "ImageRegion::GetPointerToBegin: Type of image differs from VoxelType template argument" << endl;
1048  exit(1);
1049  }
1050  if (_Begin._x < 0) const_cast<ImageRegion *>(this)->Initialize();
1051  return reinterpret_cast<const VoxelType *>(image->GetScalarPointer(_Begin._x, _Begin._y, _Begin._z, _Begin._t));
1052 }
1053 
1054 // -----------------------------------------------------------------------------
1055 template <class VoxelType>
1056 inline const VoxelType *ImageRegion::GetPointerToBegin(const GenericImage<VoxelType> &image) const
1057 {
1058  if (_Begin._x < 0) const_cast<ImageRegion *>(this)->Initialize();
1059  return image.GetPointerToVoxels(_Begin._x, _Begin._y, _Begin._z, _Begin._t);
1060 }
1061 
1062 // -----------------------------------------------------------------------------
1063 template <class VoxelType>
1065 {
1066  if (_Begin._x < 0) const_cast<ImageRegion *>(this)->Initialize();
1067  return image.GetPointerToVoxels(_Begin._x, _Begin._y, _Begin._z, _Begin._t);
1068 }
1069 
1070 // -----------------------------------------------------------------------------
1071 template <class VoxelType>
1072 inline const VoxelType *ImageRegion::GetPointerToBegin(const GenericImage<VoxelType> *image) const
1073 {
1074  if (_Begin._x < 0) const_cast<ImageRegion *>(this)->Initialize();
1075  return image->GetPointerToVoxels(_Begin._x, _Begin._y, _Begin._z, _Begin._t);
1076 }
1077 
1078 // -----------------------------------------------------------------------------
1079 template <class VoxelType>
1081 {
1082  if (_Begin._x < 0) const_cast<ImageRegion *>(this)->Initialize();
1083  return image->GetPointerToVoxels(_Begin._x, _Begin._y, _Begin._z, _Begin._t);
1084 }
1085 
1086 // -----------------------------------------------------------------------------
1087 template <class VoxelType>
1088 inline const VoxelType *ImageRegion::GetPointerToEnd(const BaseImage &image) const
1089 {
1090  if (image.GetScalarType() != voxel_info<VoxelType>::type()) {
1091  cerr << "ImageRegion::GetPointerToEnd: Type of image differs from VoxelType template argument" << endl;
1092  exit(1);
1093  }
1094  if (_Begin._x < 0) const_cast<ImageRegion *>(this)->Initialize();
1095  return reinterpret_cast<const VoxelType *>(image.GetScalarPointer(_End._x - 1, _End._y - 1, _End._z - 1, _End._t - 1));
1096 }
1097 
1098 // -----------------------------------------------------------------------------
1099 template <class VoxelType>
1100 inline const VoxelType *ImageRegion::GetPointerToEnd(const BaseImage *image) const
1101 {
1102  if (image->GetScalarType() != voxel_info<VoxelType>::type()) {
1103  cerr << "ImageRegion::GetPointerToEnd: Type of image differs from VoxelType template argument" << endl;
1104  exit(1);
1105  }
1106  if (_Begin._x < 0) const_cast<ImageRegion *>(this)->Initialize();
1107  return reinterpret_cast<const VoxelType *>(image->GetScalarPointer(_End._x - 1, _End._y - 1, _End._z - 1, _End._t - 1));
1108 }
1109 
1110 // -----------------------------------------------------------------------------
1111 template <class VoxelType>
1112 inline const VoxelType *ImageRegion::GetPointerToEnd(const GenericImage<VoxelType> &image) const
1113 {
1114  if (_Begin._x < 0) const_cast<ImageRegion *>(this)->Initialize();
1115  return image.GetPointerToVoxels(_End._x - 1, _End._y - 1, _End._z - 1, _End._t - 1);
1116 }
1117 
1118 // -----------------------------------------------------------------------------
1119 template <class VoxelType>
1121 {
1122  if (_Begin._x < 0) const_cast<ImageRegion *>(this)->Initialize();
1123  return image.GetPointerToVoxels(_End._x - 1, _End._y - 1, _End._z - 1, _End._t - 1);
1124 }
1125 
1126 // -----------------------------------------------------------------------------
1127 template <class VoxelType>
1128 inline const VoxelType *ImageRegion::GetPointerToEnd(const GenericImage<VoxelType> *image) const
1129 {
1130  if (_Begin._x < 0) const_cast<ImageRegion *>(this)->Initialize();
1131  return image->GetPointerToVoxels(_End._x - 1, _End._y - 1, _End._z - 1, _End._t - 1);
1132 }
1133 
1134 // -----------------------------------------------------------------------------
1135 template <class VoxelType>
1137 {
1138  if (_Begin._x < 0) const_cast<ImageRegion *>(this)->Initialize();
1139  return image->GetPointerToVoxels(_End._x - 1, _End._y - 1, _End._z - 1, _End._t - 1);
1140 }
1141 
1142 //////////////////////////////////////////////////////////////////////////////
1143 // Undefine local macros
1144 //////////////////////////////////////////////////////////////////////////////
1145 
1146 #undef _NextPrevMethod
1147 #undef _ToMethod1
1148 #undef _ToMethod2
1149 #undef _ToMethod3
1150 #undef _ToMethod
1151 
1152 
1153 } // namespace mirtk
1154 
1155 #endif // MIRTK_ImageRegion_H
int GetScalarType() const
Definition: BaseImage.h:1782
void SetRadius(int)
Set radius of image region.
Definition: ImageRegion.h:695
int MaxNumberOfChannels() const
Get number of channels in set image region.
Definition: ImageRegion.h:612
void SetNeighborhood(int, int, int, int)
Set 2D neighborhood.
int NumberOfImageChannels() const
Definition: ImageRegion.h:572
int NumberOfImageVoxels() const
Number of voxels in the entire image.
Definition: ImageRegion.h:566
int BeginZ() const
Get start of image region to iterate over in z dimension.
Definition: ImageRegion.h:387
Two-dimensional range.
Definition: Parallel.h:168
int NumberOfComponents() const
Get number of vector components in overlap of set image region and image domain.
Definition: ImageRegion.h:642
bool IsImageSequence() const
Definition: ImageRegion.h:554
int _SliceStride
Increment at end of slice in number of voxels.
Definition: ImageRegion.h:512
Vector4D< int > _Size
Size of set image region.
Definition: ImageRegion.h:506
int NumberOfFrames() const
Get number of frames in overlap of set image region and image domain.
Definition: ImageRegion.h:648
int EndY() const
Get end of image region to iterate over in y dimension.
Definition: ImageRegion.h:396
int MaxNumberOfFrames() const
Get number of frames in set image region.
Definition: ImageRegion.h:624
T _z
The z component.
Definition: Vector4D.h:45
One-dimensional range.
Definition: Parallel.h:155
void SetCenter(int, int, int=0, int=-1)
Set center of image region.
Definition: ImageRegion.h:668
Vector4D< int > _Begin
First index of actual image region.
Definition: ImageRegion.h:507
bool IsScalarImage() const
Definition: ImageRegion.h:560
void SetRegion(int, int, int, int)
Set 2D image region.
Definition: ImageRegion.h:712
int ColumnStride() const
Get stride between columns in number of voxels.
Definition: ImageRegion.h:408
bool IsScalar() const
Definition: ImageRegion.h:600
T _t
The t component.
Definition: Vector4D.h:46
Definition: IOConfig.h:41
int BeginT() const
Get start of image region to iterate over in t dimension.
Definition: ImageRegion.h:390
const VoxelType * GetPointerToEnd(const BaseImage &) const
Get raw image pointer to last voxel image of region.
Definition: ImageRegion.h:1088
void SetSize(int)
Set size of image region.
Definition: ImageRegion.h:678
VoxelType * GetPointerToVoxels(int=0, int=0, int=0, int=0)
Definition: GenericImage.h:849
int FrameStride() const
Get stride between frames in number of voxels.
Definition: ImageRegion.h:417
void SetFrame(int)
Set temporal region.
Definition: ImageRegion.h:841
int LineStride() const
Get stride between rows/lines in number of voxels.
Definition: ImageRegion.h:411
void SetStart(int, int, int=0, int=-1)
Set start of image region.
Definition: ImageRegion.h:658
int NumberOfChannels() const
Get number of channels in overlap of set image region and image domain.
Definition: ImageRegion.h:636
bool _IsImageSequence
Whether the image is a sequence.
Definition: ImageRegion.h:502
bool IsSequence() const
Definition: ImageRegion.h:594
int EndZ() const
Get end of image region to iterate over in z dimension.
Definition: ImageRegion.h:399
int NumberOfVoxels() const
Number of voxels in overlap of set image region and image domain.
Definition: ImageRegion.h:630
T _x
The x component.
Definition: Vector4D.h:43
int MaxNumberOfVoxels() const
Number of voxels in set image region.
Definition: ImageRegion.h:606
Three-dimensional range.
Definition: Parallel.h:197
int NumberOfVectorComponents() const
Definition: ImageRegion.h:578
int EndX() const
Get end of image region to iterate over in x dimension.
Definition: ImageRegion.h:393
ImageRegion & operator=(const ImageRegion &)
Assignment operator.
Definition: ImageRegion.h:1007
void * GetScalarPointer(int=0, int=0, int=0, int=0)
Definition: BaseImage.h:1770
Vector4D< int > _DataSize
Size of the entire image.
Definition: ImageRegion.h:501
int MaxNumberOfComponents() const
Get number of vector components in set image region.
Definition: ImageRegion.h:618
int EndT() const
Get end of image region to iterate over in t dimension.
Definition: ImageRegion.h:402
const VoxelType * GetPointerToBegin(const BaseImage &) const
Get raw image pointer to first voxel of of region.
Definition: ImageRegion.h:1032
void SetComponent(int)
Set temporal region.
Definition: ImageRegion.h:802
int _LineStride
Increment at end of line in number of voxels.
Definition: ImageRegion.h:511
ImageRegion(const ImageAttributes &)
Constructor.
Definition: ImageRegion.h:884
int BeginY() const
Get start of image region to iterate over in y dimension.
Definition: ImageRegion.h:384
Vector4D< int > _Index
Start of set image region.
Definition: ImageRegion.h:505
~ImageRegion()
Destructor.
Definition: ImageRegion.h:1022
int BeginX() const
Get start of image region to iterate over in x dimension.
Definition: ImageRegion.h:381
int NumberOfSequenceFrames() const
Definition: ImageRegion.h:584
int _FrameStride
Increment at end of frame in number of voxels.
Definition: ImageRegion.h:513
T _y
The y component.
Definition: Vector4D.h:44
Vector4D< int > _End
Last index of actual image region.
Definition: ImageRegion.h:508
int SliceStride() const
Get stride between slices in number of voxels.
Definition: ImageRegion.h:414
void SetChannel(int)
Set temporal region.
Definition: ImageRegion.h:763