GenericImage.h
1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2008-2015 Imperial College London
5  * Copyright 2008-2013 Daniel Rueckert, Julia Schnabel
6  * Copyright 2013-2015 Andreas Schuh
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 #include "mirtk/BaseImage.h" // MUST be before include guard because of
22  // cyclic dependency between BaseImage and
23  // GenericImage
24 
25 #ifndef MIRTK_GenericImage_H
26 #define MIRTK_GenericImage_H
27 
28 #include "mirtk/VoxelCast.h"
29 
30 
31 namespace mirtk {
32 
33 
34 /**
35  * Generic class for 2D or 3D images
36  *
37  * This class implements generic 2D and 3D images. It provides functions
38  * for accessing, reading, writing and manipulating images. This class can
39  * be used for images with arbitrary voxel types using templates.
40  */
41 template <class TVoxel>
42 class GenericImage : public BaseImage
43 {
44  mirtkObjectMacro(GenericImage);
45 
46  // ---------------------------------------------------------------------------
47  // Types
48 
49 public:
50 
51  /// Voxel type
52  typedef TVoxel VoxelType;
53 
54  /// Floating point type corresponding to voxel type
55  /// \note The VoxelType as well as the RealType may be a matrix/vector type!
56  typedef typename voxel_info<VoxelType>::RealType RealType;
57 
58  /// Scalar type corresponding to voxel type
59  typedef typename voxel_info<VoxelType>::ScalarType ScalarType;
60 
61  /// Floating point type corresponding to scalar type of voxel type
62  typedef typename voxel_info<ScalarType>::RealType RealScalarType;
63 
64  // ---------------------------------------------------------------------------
65  // Data members
66 
67 protected:
68 
69  /// Pointer array for access to image data
70  ///
71  /// \note The image data is stored in a contiguous memory block which can
72  /// be alternatively referred to as 1D data array using \c _data.
73  VoxelType ****_matrix;
74 
75  /// Pointer to image data
76  VoxelType *_data;
77 
78  /// Whether image data memory itself is owned by this instance
79  bool _dataOwner;
80 
81  // ---------------------------------------------------------------------------
82  // Construction/Destruction
83 
84  /// Allocate image memory
85  void AllocateImage(VoxelType * = NULL);
86 
87 public:
88 
89  /// Default constructor
90  GenericImage();
91 
92  /// Constructor from image file
93  GenericImage(const char *);
94 
95  /// Constructor for given image size
96  explicit GenericImage(int, int, int = 1, int = 1, VoxelType *data = NULL);
97 
98  /// Constructor for given image size
99  explicit GenericImage(int, int, int, int, int, VoxelType *data = NULL);
100 
101  /// Constructor for given image attributes
102  explicit GenericImage(const ImageAttributes &, VoxelType *data = NULL);
103 
104  /// Constructor for given image attributes
105  explicit GenericImage(const ImageAttributes &, int, VoxelType *data = NULL);
106 
107  /// Copy constructor for image
108  explicit GenericImage(const BaseImage &);
109 
110  /// Copy constructor for image
111  GenericImage(const GenericImage &);
112 
113  /// Copy constructor for image of different type
114  template <class TVoxel2>
116 
117  /// Destructor
118  ~GenericImage();
119 
120  // ---------------------------------------------------------------------------
121  // Initialization
122 
123  /// Create copy of this image
124  virtual BaseImage *Copy() const;
125 
126  /// Initialize a previously allocated image
127  virtual void Initialize();
128 
129  /// Initialize an image
130  virtual void Initialize(const ImageAttributes &, int, VoxelType *data);
131 
132  /// Initialize an image
133  void Initialize(const ImageAttributes &, int);
134 
135  /// Initialize an image
136  void Initialize(const ImageAttributes &, VoxelType *data = NULL);
137 
138  /// Initialize an image
139  void Initialize(int, int, int, int, int, VoxelType *data = NULL);
140 
141  /// Initialize an image
142  void Initialize(int, int, int = 1, int = 1, VoxelType *data = NULL);
143 
144  /// Copy image data from 1D array
145  void CopyFrom(const VoxelType *);
146 
147  /// Copy image data from other image of same size
148  void CopyFrom(const BaseImage &);
149 
150  /// Copy image data from other image of same size
151  void CopyFrom(const GenericImage &);
152 
153  /// Assign constant value to each voxel
154  GenericImage& operator= (VoxelType);
155 
156  /// Assignment operator with implicit cast to double and then VoxelType
158 
159  /// Assignment operator
161 
162  /// Assignment operator with implicit cast
163  template <class TVoxel2>
165 
166  /// Cast to bool, checks if this image has been initialized and ready for use
167  operator bool() const;
168 
169  /// Clear an image
170  void Clear();
171 
172  // ---------------------------------------------------------------------------
173  // Lattice
174 
175  /// Number of vector components per voxel
176  int N() const;
177 
178  // ---------------------------------------------------------------------------
179  // Image data access
180 
181  /// Function for pixel get access
182  VoxelType Get(int) const;
183 
184  /// Function for pixel get access
185  VoxelType Get(int, int, int = 0, int = 0) const;
186 
187  /// Function for pixel put access
188  void Put(int, VoxelType);
189 
190  /// Function for pixel put access
191  void Put(int, int, VoxelType);
192 
193  /// Function for pixel put access
194  void Put(int, int, int, VoxelType);
195 
196  /// Function for pixel put access
197  void Put(int, int, int, int, VoxelType);
198 
199  /// Function for pixel access from via operators
200  VoxelType& operator()(int);
201 
202  /// Function for pixel access from via operators
203  const VoxelType& operator()(int) const;
204 
205  /// Function for pixel access from via operators
206  VoxelType& operator()(int, int, int = 0, int = 0);
207 
208  /// Function for pixel access from via operators
209  const VoxelType& operator()(int, int, int = 0, int = 0) const;
210 
211  // ---------------------------------------------------------------------------
212  // Type independent access to scalar image data
213 
214  /// Function for pixel get access as double
215  virtual double GetAsDouble(int) const;
216 
217  /// Function for pixel get access as double
218  virtual double GetAsDouble(int, int, int = 0, int = 0) const;
219 
220  /// Function for pixel put access
221  virtual void PutAsDouble(int, double);
222 
223  /// Function for pixel put access
224  virtual void PutAsDouble(int, int, double);
225 
226  /// Function for pixel put access
227  virtual void PutAsDouble(int, int, int, double);
228 
229  /// Function for pixel put access
230  virtual void PutAsDouble(int, int, int, int, double);
231 
232  /// Function for pixel get access as double
233  virtual void GetAsVector(Vector &, int) const;
234 
235  /// Function for pixel get access as double
236  virtual void GetAsVector(Vector &, int, int, int = 0, int = 0) const;
237 
238  /// Function for pixel get access as double
239  virtual Vector GetAsVector(int) const;
240 
241  /// Function for pixel get access as double
242  virtual Vector GetAsVector(int, int, int = 0, int = 0) const;
243 
244  /// Function for pixel put access
245  virtual void PutAsVector(int, const Vector &);
246 
247  /// Function for pixel put access
248  virtual void PutAsVector(int, int, const Vector &);
249 
250  /// Function for pixel put access
251  virtual void PutAsVector(int, int, int, const Vector &);
252 
253  /// Function for pixel put access
254  virtual void PutAsVector(int, int, int, int, const Vector &);
255 
256  // ---------------------------------------------------------------------------
257  // Access to raw image data
258 
259  /// Get raw pointer to contiguous image data
260  VoxelType *Data(int = 0);
261 
262  /// Get raw pointer to contiguous image data
263  VoxelType *Data(int, int, int = 0, int = 0);
264 
265  /// Get raw pointer to contiguous image data
266  const VoxelType *Data(int = 0) const;
267 
268  /// Get raw pointer to contiguous image data
269  const VoxelType *Data(int, int, int = 0, int = 0) const;
270 
271  /// Get raw pointer to contiguous image data
272  virtual void *GetDataPointer(int = 0);
273 
274  /// Get raw pointer to contiguous image data
275  virtual const void *GetDataPointer(int = 0) const;
276 
277  /// Get raw pointer to contiguous image data
278  virtual void *GetDataPointer(int, int, int = 0, int = 0);
279 
280  /// Get raw pointer to contiguous image data
281  virtual const void *GetDataPointer(int, int, int = 0, int = 0) const;
282 
283  /// Get enumeration value corresponding to voxel type
284  virtual int GetDataType() const;
285 
286  /// Get size of each voxel in bytes
287  virtual int GetDataTypeSize() const;
288 
289  /// Minimum value a pixel can hold without overflowing
290  virtual double GetDataTypeMin() const;
291 
292  /// Maximum value a pixel can hold without overflowing
293  virtual double GetDataTypeMax() const;
294 
295  // ---------------------------------------------------------------------------
296  // Region-of-interest extraction
297 
298  /// Get image consisting of specified 2D slice
299  GenericImage GetRegion(int, int) const;
300 
301  /// Get image consisting of specified 2D slice
302  void GetRegion(GenericImage &, int, int) const;
303 
304  /// Get image consisting of specified 2D slice
305  virtual void GetRegion(BaseImage *&, int, int) const;
306 
307  /// Get image consisting of specified 3D subregion
308  GenericImage GetRegion(int, int, int,
309  int, int, int) const;
310 
311  /// Get image consisting of specified 3D subregion
312  void GetRegion(GenericImage &, int, int, int,
313  int, int, int) const;
314 
315  /// Get image consisting of specified 3D subregion
316  virtual void GetRegion(BaseImage *&, int, int, int,
317  int, int, int) const;
318 
319  /// Get image consisting of specified 4D subregion
320  GenericImage GetRegion(int, int, int, int,
321  int, int, int, int) const;
322 
323  /// Get image consisting of specified 4D subregion
324  void GetRegion(GenericImage &, int, int, int, int,
325  int, int, int, int) const;
326 
327  /// Get image consisting of specified 4D subregion
328  virtual void GetRegion(BaseImage *&, int, int, int, int,
329  int, int, int, int) const;
330 
331  /// Get time instance (i.e., frame) or channel of image
332  GenericImage GetFrame(int, int = -1) const;
333 
334  /// Get time instance (i.e., frame) or channel of image
335  void GetFrame(GenericImage &, int, int = -1) const;
336 
337  /// Get time instance (i.e., frame) or channel of image
338  virtual void GetFrame(BaseImage *&, int, int = -1) const;
339 
340  // ---------------------------------------------------------------------------
341  // Image arithmetic
342 
343  /// Equality operator
344  /// \note Use explicit negation for inequality comparison.
345  /// The overloaded != operator is used for binarization of the image.
346  template <class TVoxel2>
347  bool operator== (const GenericImage<TVoxel2> &) const;
348 
349  GenericImage& operator+=(const GenericImage &); ///< Add image
350  GenericImage& operator-=(const GenericImage &); ///< Subtract image
351  GenericImage& operator*=(const GenericImage &); ///< Multipy voxels
352  GenericImage& operator/=(const GenericImage &); ///< Divide voxels
353 
354  GenericImage& operator+=(double); ///< Add scalar
355  GenericImage& operator-=(double); ///< Subtract scalar
356  GenericImage& operator*=(double); ///< Multiply by scalar
357  GenericImage& operator/=(double); ///< Divide by scalar
358 
359  GenericImage operator+ (const GenericImage &) const; ///< Add images
360  GenericImage operator- (const GenericImage &) const; ///< Subtract images
361  GenericImage operator* (const GenericImage &) const; ///< Multiply images voxel-wise
362  GenericImage operator/ (const GenericImage &) const; ///< Divide images voxel-wise
363 
364  GenericImage operator+ (double) const; ///< Add scalar to image
365  GenericImage operator- (double) const; ///< Subtract scalar from image
366  GenericImage operator* (double) const; ///< Multiply image by scalar
367  GenericImage operator/ (double) const; ///< Divide image by scalar
368 
369  // ---------------------------------------------------------------------------
370  // Thresholding
371 
372  // Import other overload
374 
375  /// Put background value
376  virtual void PutBackgroundValueAsDouble(double, bool);
377 
378  GenericImage& operator>=(VoxelType); ///< Clamp image given upper threshold
379  GenericImage& operator<=(VoxelType); ///< Clamp image given lower threshold
380 
381  GenericImage operator> (VoxelType) const; ///< Clamp image given upper threshold
382  GenericImage operator< (VoxelType) const; ///< Clamp image given lower threshold
383 
384  /// Get binary mask for voxels which are not equal the scalar
385  BinaryImage operator!=(VoxelType) const;
386 
387  // ---------------------------------------------------------------------------
388  // Common image statistics
389 
390  /// Minimum and maximum pixel values get accessor
391  void GetMinMax(VoxelType &, VoxelType &) const;
392 
393  /// Minimum and maximum pixel values get accessor with padding
394  void GetMinMax(VoxelType &, VoxelType &, VoxelType) const;
395 
396  /// Linearly rescale intensities
397  void PutMinMax(VoxelType, VoxelType);
398 
399  /// Mean pixel value
400  ///
401  /// \param[in] fg Calculate mean of foreground only.
402  RealType Mean(bool fg = true) const;
403 
404  /// Average pixel values get accessor
405  /// \deprecated Use Mean instead.
406  RealType GetAverage(int = 1) const;
407 
408  /// Standard Deviation of the pixels
409  RealType GetSD(int = 1) const;
410 
411  /// Get Max Intensity position around the point
412  void GetMaxPosition(Point &, int = 1, int = 0) const;
413 
414  /// Get Gravity center position of a given window
415  void GravityCenter(Point &, int = 1, int = 0) const;
416 
417  // ---------------------------------------------------------------------------
418  // Common image manipulations
419 
420  virtual void ReflectX(bool modify_axes = false); ///< Reflect image along x
421  virtual void ReflectY(bool modify_axes = false); ///< Reflect image along y
422  virtual void ReflectZ(bool modify_axes = false); ///< Reflect image along z
423  virtual void ReflectT(bool modify_axes = false); ///< Reflect image along t
424 
425  virtual void FlipXY(bool modify_origin = false); ///< Flip x and y axis, always also swaps voxel size
426  virtual void FlipXZ(bool modify_origin = false); ///< Flip x and z axis, always also swaps voxel size
427  virtual void FlipYZ(bool modify_origin = false); ///< Flip y and z axis, always also swaps voxel size
428  virtual void FlipXT(bool modify_origin = false); ///< Flip x and t axis, always also swaps voxel size
429  virtual void FlipYT(bool modify_origin = false); ///< Flip y and t axis, always also swaps voxel size
430  virtual void FlipZT(bool modify_origin = false); ///< Flip z and t axis, always also swaps voxel size
431 
432  virtual void SwapXY(bool modify_axes = true); ///< Swap x and y axis
433  virtual void SwapXZ(bool modify_axes = true); ///< Swap x and z axis
434  virtual void SwapYZ(bool modify_axes = true); ///< Swap y and z axis
435  virtual void SwapXT(bool modify_axes = true); ///< Swap x and t axis
436  virtual void SwapYT(bool modify_axes = true); ///< Swap y and t axis
437  virtual void SwapZT(bool modify_axes = true); ///< Swap z and t axis
438 
439  bool CropPad(int margin = 0); ///< Crop/pad image background
440 
441  // ---------------------------------------------------------------------------
442  // VTK interface
443  #if MIRTK_Image_WITH_VTK
444 
445  /// Convert image to VTK structured points
446  ///
447  /// \note Use only when MIRTK_Image_WITH_VTK is 1.
448  virtual void ImageToVTK(vtkStructuredPoints *) const;
449 
450  /// Convert VTK structured points to image
451  ///
452  /// \note Use only when MIRTK_Image_WITH_VTK is 1.
453  virtual void VTKToImage(vtkStructuredPoints *);
454 
455  #endif // MIRTK_Image_WITH_VTK
456  // ---------------------------------------------------------------------------
457  // I/O
458 
459  /// Read image from file
460  virtual void Read(const char *);
461 
462  /// Write image to file
463  virtual void Write(const char *) const;
464 
465  // ---------------------------------------------------------------------------
466  // Deprecated
467 
468  /// Minimum and maximum pixel values get accessor
469  /// \deprecated Use respective overloaded method of GetMinMax instead.
470  void GetMinMax(VoxelType *, VoxelType *) const;
471 
472  /// Minimum and maximum pixel values get accessor with padding
473  /// \deprecated Use respective overloaded method of GetMinMax instead.
474  void GetMinMax(VoxelType *, VoxelType *, VoxelType) const;
475 
476  /// Minimum and maximum pixel values get accessor with padding
477  /// \deprecated Use respective overloaded method of GetMinMax instead.
478  void GetMinMaxPad(VoxelType *, VoxelType *, VoxelType) const;
479 
480  /// \returns Raw pointer to contiguous image data.
481  /// \deprecated Use Data instead.
482  VoxelType *GetPointerToVoxels(int = 0, int = 0, int = 0, int = 0);
483 
484  /// \returns Raw pointer to contiguous image data.
485  /// \deprecated Use Data instead.
486  const VoxelType *GetPointerToVoxels(int = 0, int = 0, int = 0, int = 0) const;
487 
488 };
489 
490 ////////////////////////////////////////////////////////////////////////////////
491 // Inline definitions
492 ////////////////////////////////////////////////////////////////////////////////
493 
494 // =============================================================================
495 // Initialization
496 // =============================================================================
497 
498 // -----------------------------------------------------------------------------
499 template <class VoxelType> template <class VoxelType2>
501 {
502  this->Initialize(image.GetImageAttributes());
503  VoxelType *ptr1 = this->GetPointerToVoxels();
504  const VoxelType2 *ptr2 = image.GetPointerToVoxels();
505  for (int idx = 0; idx < _NumberOfVoxels; idx++) {
506  ptr1[idx] = voxel_cast<VoxelType>(ptr2[idx]);
507  }
508  if (image.OwnsMask()) {
509  _mask = new BinaryImage(*image.GetMask());
510  _maskOwner = true;
511  } else {
512  _mask = const_cast<BinaryImage *>(image.GetMask());
513  _maskOwner = false;
514  }
515  if (image.HasBackgroundValue()) {
516  this->PutBackgroundValueAsDouble(image.GetBackgroundValueAsDouble());
517  }
518  return *this;
519 }
520 
521 // -----------------------------------------------------------------------------
522 template <class VoxelType>
524 {
525  return bool(_attr) && _matrix != nullptr;
526 }
527 
528 // =============================================================================
529 // Lattice
530 // =============================================================================
531 
532 // -----------------------------------------------------------------------------
533 template <class VoxelType>
534 inline int GenericImage<VoxelType>::N() const
535 {
536  return voxel_info<VoxelType>::vector_size();
537 }
538 
539 // =============================================================================
540 // Image data access
541 // =============================================================================
542 
543 // -----------------------------------------------------------------------------
544 template <class VoxelType>
545 inline void GenericImage<VoxelType>::Put(int index, VoxelType val)
546 {
547  _data[index] = val;
548 }
549 
550 // -----------------------------------------------------------------------------
551 template <class VoxelType>
552 inline void GenericImage<VoxelType>::Put(int x, int y, VoxelType val)
553 {
554  _matrix[0][0][y][x] = val;
555 }
556 
557 // -----------------------------------------------------------------------------
558 template <class VoxelType>
559 inline void GenericImage<VoxelType>::Put(int x, int y, int z, VoxelType val)
560 {
561  _matrix[0][z][y][x] = val;
562 }
563 
564 // -----------------------------------------------------------------------------
565 template <class VoxelType>
566 inline void GenericImage<VoxelType>::Put(int x, int y, int z, int t, VoxelType val)
567 {
568  _matrix[t][z][y][x] = val;
569 }
570 
571 // -----------------------------------------------------------------------------
572 template <class VoxelType>
574 {
575  return _data[index];
576 }
577 
578 // -----------------------------------------------------------------------------
579 template <class VoxelType>
580 inline VoxelType GenericImage<VoxelType>::Get(int x, int y, int z, int t) const
581 {
582  return _matrix[t][z][y][x];
583 }
584 
585 // -----------------------------------------------------------------------------
586 template <class VoxelType>
588 {
589  return _data[index];
590 }
591 
592 // -----------------------------------------------------------------------------
593 template <class VoxelType>
594 inline const VoxelType &GenericImage<VoxelType>::operator ()(int index) const
595 {
596  return _data[index];
597 }
598 
599 // -----------------------------------------------------------------------------
600 template <class VoxelType>
601 inline VoxelType& GenericImage<VoxelType>::operator()(int x, int y, int z, int t)
602 {
603  return _matrix[t][z][y][x];
604 }
605 
606 // -----------------------------------------------------------------------------
607 template <class VoxelType>
608 inline const VoxelType& GenericImage<VoxelType>::operator()(int x, int y, int z, int t) const
609 {
610  return _matrix[t][z][y][x];
611 }
612 
613 // =============================================================================
614 // Image arithmetics
615 // =============================================================================
616 
617 // -----------------------------------------------------------------------------
618 template <class VoxelType> template <class VoxelType2>
620 {
621  if (this->GetImageAttributes() != image.GetImageAttributes()) return false;
622  const VoxelType *ptr1 = this->GetPointerToVoxels();
623  const VoxelType2 *ptr2 = image.GetPointerToVoxels();
624  for (int idx = 0; idx < image; ++idx) {
625  if (IsForeground(idx) && image.IsForeground(idx) && ptr1[idx] != ptr2[idx]) {
626  return false;
627  }
628  }
629  return true;
630 }
631 
632 // =============================================================================
633 // Type independent access to scalar image data
634 // =============================================================================
635 
636 // -----------------------------------------------------------------------------
637 template <class VoxelType>
638 inline void GenericImage<VoxelType>::PutAsDouble(int index, double val)
639 {
640  _data[index] = voxel_cast<VoxelType>(val);
641 }
642 
643 // -----------------------------------------------------------------------------
644 template <class VoxelType>
645 inline void GenericImage<VoxelType>::PutAsDouble(int x, int y, double val)
646 {
647  _matrix[0][0][y][x] = voxel_cast<VoxelType>(val);
648 }
649 
650 // -----------------------------------------------------------------------------
651 template <class VoxelType>
652 inline void GenericImage<VoxelType>::PutAsDouble(int x, int y, int z, double val)
653 {
654  _matrix[0][z][y][x] = voxel_cast<VoxelType>(val);
655 }
656 
657 // -----------------------------------------------------------------------------
658 template <class VoxelType>
659 inline void GenericImage<VoxelType>::PutAsDouble(int x, int y, int z, int t, double val)
660 {
661  _matrix[t][z][y][x] = voxel_cast<VoxelType>(val);
662 }
663 
664 // -----------------------------------------------------------------------------
665 template <class VoxelType>
666 inline double GenericImage<VoxelType>::GetAsDouble(int index) const
667 {
668  return voxel_cast<double>(_data[index]);
669 }
670 
671 // -----------------------------------------------------------------------------
672 template <class VoxelType>
673 inline double GenericImage<VoxelType>::GetAsDouble(int x, int y, int z, int t) const
674 {
675  return voxel_cast<double>(_matrix[t][z][y][x]);
676 }
677 
678 // -----------------------------------------------------------------------------
679 template <class VoxelType>
680 inline void GenericImage<VoxelType>::PutAsVector(int index, const Vector &value)
681 {
682  _data[index] = voxel_cast<VoxelType>(value);
683 }
684 
685 // -----------------------------------------------------------------------------
686 template <class VoxelType>
687 inline void GenericImage<VoxelType>::PutAsVector(int x, int y, const Vector &value)
688 {
689  _matrix[0][0][y][x] = voxel_cast<VoxelType>(value);
690 }
691 
692 // -----------------------------------------------------------------------------
693 template <class VoxelType>
694 inline void GenericImage<VoxelType>::PutAsVector(int x, int y, int z, const Vector &value)
695 {
696  _matrix[0][z][y][x] = voxel_cast<VoxelType>(value);
697 }
698 
699 // -----------------------------------------------------------------------------
700 template <class VoxelType>
701 inline void GenericImage<VoxelType>::PutAsVector(int x, int y, int z, int t, const Vector &value)
702 {
703  _matrix[t][z][y][x] = voxel_cast<VoxelType>(value);
704 }
705 
706 // -----------------------------------------------------------------------------
707 template <class VoxelType>
708 inline void GenericImage<VoxelType>::GetAsVector(Vector &value, int index) const
709 {
710  value = voxel_cast<Vector>(_data[index]);
711 }
712 
713 // -----------------------------------------------------------------------------
714 template <class VoxelType>
715 inline void GenericImage<VoxelType>::GetAsVector(Vector &value, int x, int y, int z, int t) const
716 {
717  value = voxel_cast<Vector>(_matrix[t][z][y][x]);
718 }
719 
720 // -----------------------------------------------------------------------------
721 template <class VoxelType>
723 {
724  return voxel_cast<Vector>(_data[index]);
725 }
726 
727 // -----------------------------------------------------------------------------
728 template <class VoxelType>
729 inline Vector GenericImage<VoxelType>::GetAsVector(int x, int y, int z, int t) const
730 {
731  return voxel_cast<Vector>(_matrix[t][z][y][x]);
732 }
733 
734 // =============================================================================
735 // Access to raw image data
736 // =============================================================================
737 
738 // -----------------------------------------------------------------------------
739 template <class VoxelType>
741 {
742  return _data + i;
743 }
744 
745 // -----------------------------------------------------------------------------
746 template <class VoxelType>
747 inline const VoxelType *GenericImage<VoxelType>::Data(int i) const
748 {
749  return _data + i;
750 }
751 
752 // -----------------------------------------------------------------------------
753 template <class VoxelType>
754 inline VoxelType *GenericImage<VoxelType>::Data(int x, int y, int z, int t)
755 {
756  return &_matrix[t][z][y][x];
757 }
758 
759 // -----------------------------------------------------------------------------
760 template <class VoxelType>
761 inline const VoxelType *GenericImage<VoxelType>::Data(int x, int y, int z, int t) const
762 {
763  return &_matrix[t][z][y][x];
764 }
765 
766 // -----------------------------------------------------------------------------
767 template <class VoxelType>
769 {
770  return _data + i;
771 }
772 
773 // -----------------------------------------------------------------------------
774 template <class VoxelType>
775 inline const void *GenericImage<VoxelType>::GetDataPointer(int i) const
776 {
777  return _data + i;
778 }
779 
780 // -----------------------------------------------------------------------------
781 template <class VoxelType>
782 inline void *GenericImage<VoxelType>::GetDataPointer(int x, int y, int z, int t)
783 {
784  return &_matrix[t][z][y][x];
785 }
786 
787 // -----------------------------------------------------------------------------
788 template <class VoxelType>
789 inline const void *GenericImage<VoxelType>::GetDataPointer(int x, int y, int z, int t) const
790 {
791  return &_matrix[t][z][y][x];
792 }
793 
794 // -----------------------------------------------------------------------------
795 template <class VoxelType>
797 {
798  return voxel_info<VoxelType>::type();
799 }
800 
801 // -----------------------------------------------------------------------------
802 template <class VoxelType>
804 {
805  return static_cast<int>(sizeof(VoxelType));
806 }
807 
808 // -----------------------------------------------------------------------------
809 template <class VoxelType>
811 {
812  return voxel_limits<VoxelType>::min();
813 }
814 
815 // -----------------------------------------------------------------------------
816 template <class VoxelType>
818 {
819  return voxel_limits<VoxelType>::max();
820 }
821 
822 // =============================================================================
823 // Deprecated
824 // =============================================================================
825 
826 // -----------------------------------------------------------------------------
827 template <class VoxelType>
829 {
830  this->GetMinMax(*min, *max);
831 }
832 
833 // -----------------------------------------------------------------------------
834 template <class VoxelType>
836 {
837  this->GetMinMax(*min, *max, pad);
838 }
839 
840 // -----------------------------------------------------------------------------
841 template <class VoxelType>
843 {
844  this->GetMinMax(*min, *max, pad);
845 }
846 
847 // -----------------------------------------------------------------------------
848 template <class VoxelType>
849 inline VoxelType *GenericImage<VoxelType>::GetPointerToVoxels(int x, int y, int z, int t)
850 {
851  return &_matrix[t][z][y][x];
852 }
853 
854 // -----------------------------------------------------------------------------
855 template <class VoxelType>
856 inline const VoxelType *GenericImage<VoxelType>::GetPointerToVoxels(int x, int y, int z, int t) const
857 {
858  return &_matrix[t][z][y][x];
859 }
860 
861 ////////////////////////////////////////////////////////////////////////////////
862 // Convert between (deprecated) 3D+t vector field and vector-valued 3D images
863 ////////////////////////////////////////////////////////////////////////////////
864 
865 // -----------------------------------------------------------------------------
866 template <class T>
867 inline void Copy(const GenericImage<Vector3D<T> > &in, GenericImage<T> &out)
868 {
869  if (in.T() != 1) {
870  Throw(ERR_InvalidArgument, __FUNCTION__, "Input image must be 3D without temporal components");
871  }
872  if (out.Attributes().EqualInSpace(in.Attributes()) && out.T() == 3) {
873  out.PutTSize(0.);
874  } else {
875  out.Initialize(in.Attributes(), 3);
876  }
877  const Vector3D<T> *v = in.Data();
878  T *x = out.Data(0, 0, 0, 0);
879  T *y = out.Data(0, 0, 0, 1);
880  T *z = out.Data(0, 0, 0, 2);
881  const int nvox = in.NumberOfVoxels();
882  for (int idx = 0; idx < nvox; ++idx, ++x, ++y, ++z, ++v) {
883  (*x) = v->_x;
884  (*y) = v->_y;
885  (*z) = v->_z;
886  }
887 }
888 
889 // -----------------------------------------------------------------------------
890 template <class T>
891 inline void Copy(const GenericImage<Vector4D<T> > &in, GenericImage<T> &out)
892 {
893  if (in.T() != 1) {
894  Throw(ERR_InvalidArgument, __FUNCTION__, "Input image must be 3D without temporal components");
895  }
896  if (out.Attributes().EqualInSpace(in.Attributes()) && out.T() == 4) {
897  out.PutTSize(0.);
898  } else {
899  out.Initialize(in.Attributes(), 4);
900  }
901  const Vector4D<T> *v = in.Data();
902  T *x = out.Data(0, 0, 0, 0);
903  T *y = out.Data(0, 0, 0, 1);
904  T *z = out.Data(0, 0, 0, 2);
905  T *t = out.Data(0, 0, 0, 3);
906  const int nvox = in.NumberOfVoxels();
907  for (int idx = 0; idx < nvox; ++idx, ++x, ++y, ++z, ++t, ++v) {
908  (*x) = v->_x;
909  (*y) = v->_y;
910  (*z) = v->_z;
911  (*t) = v->_t;
912  }
913 }
914 
915 // -----------------------------------------------------------------------------
916 template <int N, class T>
917 inline void Copy(const GenericImage<VectorND<N, T> > &in, GenericImage<T> &out)
918 {
919  if (in.T() != 1) {
920  Throw(ERR_InvalidArgument, __FUNCTION__, "Input image must be 3D without temporal components");
921  }
922  if (out.Attributes().EqualInSpace(in.Attributes()) && out.T() == N) {
923  out.PutTSize(0.);
924  } else {
925  out.Initialize(in.Attributes(), N);
926  }
927  const VectorND<N, T> *v = in.Data();
928  const int nvox = in.NumberOfVoxels();
929  for (int idx = 0; idx < nvox; ++idx, ++v) {
930  const T *c = v->_v;
931  T *p = out.Data(idx);
932  for (int i = 0; i < N; ++i, p += nvox, ++c) {
933  (*p) = (*c);
934  }
935  }
936 }
937 
938 // -----------------------------------------------------------------------------
939 template <class T>
940 inline void Copy(const GenericImage<T> &in, GenericImage<Vector3D<T> > &out)
941 {
942  if (in.T() != 3) {
943  Throw(ERR_InvalidArgument, __FUNCTION__, "Input image must have 3 components in the temporal dimension");
944  }
945  if (!out.Attributes().EqualInSpace(in.Attributes()) || out.T() != 1) {
946  out.Initialize(in.Attributes(), 1);
947  }
948  const T *x = in.Data(0, 0, 0, 0);
949  const T *y = in.Data(0, 0, 0, 1);
950  const T *z = in.Data(0, 0, 0, 2);
951  Vector3D<T> *v = out.Data();
952  for (int idx = 0; idx < out.NumberOfVoxels(); ++idx, ++x, ++y, ++z, ++v) {
953  v->_x = (*x);
954  v->_y = (*y);
955  v->_z = (*z);
956  }
957 }
958 
959 // -----------------------------------------------------------------------------
960 template <class T>
961 inline void Copy(const GenericImage<T> &in, GenericImage<Vector4D<T> > &out)
962 {
963  if (in.T() != 4) {
964  Throw(ERR_InvalidArgument, __FUNCTION__, "Input image must have 4 components in the temporal dimension");
965  }
966  if (!out.Attributes().EqualInSpace(in.Attributes()) || out.T() != 1) {
967  out.Initialize(in.Attributes(), 1);
968  }
969  const T *x = in.Data(0, 0, 0, 0);
970  const T *y = in.Data(0, 0, 0, 1);
971  const T *z = in.Data(0, 0, 0, 2);
972  const T *t = in.Data(0, 0, 0, 3);
973  Vector4D<T> *v = out.Data();
974  for (int idx = 0; idx < out.NumberOfVoxels(); ++idx, ++x, ++y, ++z, ++t, ++v) {
975  v->_x = (*x);
976  v->_y = (*y);
977  v->_z = (*z);
978  v->_t = (*t);
979  }
980 }
981 
982 // -----------------------------------------------------------------------------
983 template <int N, class T>
984 inline void Copy(const GenericImage<T> &in, GenericImage<VectorND<N, T> > &out)
985 {
986  if (in.T() != N) {
987  Throw(ERR_InvalidArgument, __FUNCTION__, "Input image must have ", N, " components in the temporal dimension");
988  }
989  if (!out.Attributes().EqualInSpace(in.Attributes()) || out.T() != 1) {
990  out.Initialize(in.Attributes(), 1);
991  }
992  Vector3D<T> *v = out.Data();
993  const int nvox = out.NumberOfVoxels();
994  for (int idx = 0; idx < nvox; ++idx, ++v) {
995  const T *p = in.Data(idx);
996  T *c = v->_v;
997  for (int i = 0; i < N; ++i, p += nvox, ++c) {
998  (*c) = (*p);
999  }
1000  }
1001 }
1002 
1003 ////////////////////////////////////////////////////////////////////////////////
1004 // Common specializations
1005 ////////////////////////////////////////////////////////////////////////////////
1006 
1010 
1011 
1012 } // namespace mirtk
1013 
1014 #endif // MIRTK_GenericImage_H
int _NumberOfVoxels
Total number of voxels.
Definition: BaseImage.h:102
bool operator==(const GenericImage< TVoxel2 > &) const
virtual void ReflectX(bool modify_axes=false)
Reflect image along x.
VoxelType * Data(int=0)
Get raw pointer to contiguous image data.
Definition: GenericImage.h:740
virtual void FlipZT(bool modify_origin=false)
Flip z and t axis, always also swaps voxel size.
GenericImage & operator=(VoxelType)
Assign constant value to each voxel.
BinaryImage * _mask
Foreground mask.
Definition: BaseImage.h:111
voxel_info< VoxelType >::RealType RealType
Definition: GenericImage.h:56
void PutBackgroundValueAsDouble(double)
Put background value.
Definition: BaseImage.h:1394
GenericImage operator*(const GenericImage &) const
Multiply images voxel-wise.
GenericImage & operator-=(const GenericImage &)
Subtract image.
void Clear()
Clear an image.
virtual void FlipXY(bool modify_origin=false)
Flip x and y axis, always also swaps voxel size.
void GetMinMax(VoxelType &, VoxelType &) const
Minimum and maximum pixel values get accessor.
RealType GetSD(int=1) const
Standard Deviation of the pixels.
void Put(int, VoxelType)
Function for pixel put access.
Definition: GenericImage.h:545
VoxelType * _data
Pointer to image data.
Definition: GenericImage.h:76
virtual void FlipYT(bool modify_origin=false)
Flip y and t axis, always also swaps voxel size.
GenericImage & operator/=(const GenericImage &)
Divide voxels.
virtual void ReflectZ(bool modify_axes=false)
Reflect image along z.
void GetMaxPosition(Point &, int=1, int=0) const
Get Max Intensity position around the point.
GenericImage operator>(VoxelType) const
Clamp image given upper threshold.
RealType GetAverage(int=1) const
void CopyFrom(const VoxelType *)
Copy image data from 1D array.
GenericImage operator<(VoxelType) const
Clamp image given lower threshold.
T _z
The z component.
Definition: Vector4D.h:45
const ImageAttributes & GetImageAttributes() const
Definition: BaseImage.h:1735
virtual void SwapXY(bool modify_axes=true)
Swap x and y axis.
RealType Mean(bool fg=true) const
bool IsForeground(int) const
Whether voxel is within foreground without index-out-of-bounds check.
Definition: BaseImage.h:1455
virtual void * GetDataPointer(int=0)
Get raw pointer to contiguous image data.
Definition: GenericImage.h:768
virtual BaseImage * Copy() const
Create copy of this image.
int N() const
Number of vector components per voxel.
Definition: GenericImage.h:534
ImageAttributes _attr
Image attributes.
Definition: BaseImage.h:99
T _t
The t component.
Definition: Vector4D.h:46
void AllocateImage(VoxelType *=NULL)
Allocate image memory.
GenericImage & operator>=(VoxelType)
Clamp image given upper threshold.
virtual void FlipXT(bool modify_origin=false)
Flip x and t axis, always also swaps voxel size.
Definition: IOConfig.h:41
VoxelType * GetPointerToVoxels(int=0, int=0, int=0, int=0)
Definition: GenericImage.h:849
virtual void SwapXZ(bool modify_axes=true)
Swap x and z axis.
T _v[N]
Vector components.
Definition: VectorND.h:60
VoxelType **** _matrix
Definition: GenericImage.h:73
virtual void PutAsDouble(int, double)
Function for pixel put access.
Definition: GenericImage.h:638
virtual void FlipYZ(bool modify_origin=false)
Flip y and z axis, always also swaps voxel size.
virtual int GetDataType() const
Get enumeration value corresponding to voxel type.
Definition: GenericImage.h:796
void PutMinMax(VoxelType, VoxelType)
Linearly rescale intensities.
virtual void Read(const char *)
Read image from file.
voxel_info< VoxelType >::ScalarType ScalarType
Scalar type corresponding to voxel type.
Definition: GenericImage.h:59
voxel_info< ScalarType >::RealType RealScalarType
Floating point type corresponding to scalar type of voxel type.
Definition: GenericImage.h:62
GenericImage operator-(const GenericImage &) const
Subtract images.
~GenericImage()
Destructor.
virtual void SwapYT(bool modify_axes=true)
Swap y and t axis.
T _x
The x component.
Definition: Vector4D.h:43
virtual void ReflectY(bool modify_axes=false)
Reflect image along y.
bool CropPad(int margin=0)
Crop/pad image background.
virtual double GetDataTypeMax() const
Maximum value a pixel can hold without overflowing.
Definition: GenericImage.h:817
VoxelType & operator()(int)
Function for pixel access from via operators.
Definition: GenericImage.h:587
GenericImage GetRegion(int, int) const
Get image consisting of specified 2D slice.
virtual void SwapXT(bool modify_axes=true)
Swap x and t axis.
virtual double GetAsDouble(int) const
Function for pixel get access as double.
Definition: GenericImage.h:666
void GetMinMaxPad(VoxelType *, VoxelType *, VoxelType) const
Definition: GenericImage.h:842
virtual void PutAsVector(int, const Vector &)
Function for pixel put access.
Definition: GenericImage.h:680
virtual void FlipXZ(bool modify_origin=false)
Flip x and z axis, always also swaps voxel size.
void Throw(ErrorType err, const char *func, Args... args) const
Definition: Object.h:166
bool _dataOwner
Whether image data memory itself is owned by this instance.
Definition: GenericImage.h:79
GenericImage & operator*=(const GenericImage &)
Multipy voxels.
GenericImage< BinaryPixel > BinaryImage
Binary image as used for masks (0: off, otherwise: on)
Definition: BaseImage.h:52
GenericImage & operator<=(VoxelType)
Clamp image given lower threshold.
T _z
The z component.
Definition: Vector3D.h:60
virtual void GetAsVector(Vector &, int) const
Function for pixel get access as double.
Definition: GenericImage.h:708
virtual void PutBackgroundValueAsDouble(double, bool)
Put background value.
virtual void Write(const char *) const
Write image to file.
virtual int GetDataTypeSize() const
Get size of each voxel in bytes.
Definition: GenericImage.h:803
T _y
The y component.
Definition: Vector3D.h:59
int T() const
Returns the number of voxels in the t-direction.
Definition: BaseImage.h:892
void GravityCenter(Point &, int=1, int=0) const
Get Gravity center position of a given window.
virtual void SwapYZ(bool modify_axes=true)
Swap y and z axis.
VoxelType Get(int) const
Function for pixel get access.
Definition: GenericImage.h:573
virtual void Initialize()
Initialize a previously allocated image.
GenericImage()
Default constructor.
BinaryImage operator!=(VoxelType) const
Get binary mask for voxels which are not equal the scalar.
virtual void ReflectT(bool modify_axes=false)
Reflect image along t.
T _x
The x component.
Definition: Vector3D.h:58
GenericImage operator/(const GenericImage &) const
Divide images voxel-wise.
virtual double GetDataTypeMin() const
Minimum value a pixel can hold without overflowing.
Definition: GenericImage.h:810
virtual void SwapZT(bool modify_axes=true)
Swap z and t axis.
GenericImage GetFrame(int, int=-1) const
Get time instance (i.e., frame) or channel of image.
T _y
The y component.
Definition: Vector4D.h:44
GenericImage operator+(const GenericImage &) const
Add images.
TVoxel VoxelType
Voxel type.
Definition: GenericImage.h:52
GenericImage & operator+=(const GenericImage &)
Add image.