Medical Imaging Interaction Toolkit  2025.12.02
Medical Imaging Interaction Toolkit
mitkImage.h
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #ifndef mitkImage_h
14 #define mitkImage_h
15 
16 #include "mitkBaseData.h"
17 #include "mitkImageAccessorBase.h"
18 #include "mitkImageDataItem.h"
19 #include "mitkImageDescriptor.h"
21 #include "mitkLevelWindow.h"
22 #include "mitkPlaneGeometry.h"
23 #include "mitkSlicedData.h"
24 #include <MitkCoreExports.h>
26 
27 #ifndef __itkHistogram_h
28 #include <itkHistogram.h>
29 #endif
30 
31 class vtkImageData;
32 
33 namespace itk
34 {
35  template <class T>
37 }
38 
39 namespace mitk
40 {
41  class SubImageSelector;
42  class ImageTimeSelector;
43 
44  class ImageStatisticsHolder;
45 
70  {
71  friend class SubImageSelector;
72 
73  friend class ImageAccessorBase;
74  friend class ImageVtkReadAccessor;
75  friend class ImageVtkWriteAccessor;
76  friend class ImageReadAccessor;
77  friend class ImageWriteAccessor;
78 
79  public:
81 
82  itkFactorylessNewMacro(Self);
83 
84  itkCloneMacro(Self);
85 
88  typedef itk::Statistics::Histogram<double> HistogramType;
90 
94  {
98  DontManageMemory = ReferenceMemory
99  };
100 
106  typedef std::vector<ImageDataItemPointer> ImageDataItemPointerArray;
107 
108  public:
112  const mitk::PixelType GetPixelType(int n = 0) const;
113 
117  unsigned int GetDimension() const;
118 
124  unsigned int GetDimension(int i) const;
125 
126  public:
130  virtual vtkImageData *GetVtkImageData(int t = 0, int n = 0);
131  virtual const vtkImageData *GetVtkImageData(int t = 0, int n = 0) const;
132 
136  bool IsSliceSet(int s = 0, int t = 0, int n = 0) const override;
137 
141  bool IsVolumeSet(int t = 0, int n = 0) const override;
142 
146  bool IsChannelSet(int n = 0) const override;
147 
160  virtual bool SetSlice(const void *data, int s = 0, int t = 0, int n = 0);
161 
174  virtual bool SetVolume(const void *data, int t = 0, int n = 0);
175 
188  virtual bool SetChannel(const void *data, int n = 0);
189 
199  virtual bool SetImportSlice(
200  void *data, int s = 0, int t = 0, int n = 0, ImportMemoryManagementType importMemoryManagement = CopyMemory);
201 
211  virtual bool SetImportVolume(void *data,
212  int t = 0,
213  int n = 0,
214  ImportMemoryManagementType importMemoryManagement = CopyMemory);
215 
216  virtual bool SetImportVolume(const void *const_data, int t = 0, int n = 0);
217 
227  virtual bool SetImportChannel(void *data,
228  int n = 0,
229  ImportMemoryManagementType importMemoryManagement = CopyMemory);
230 
235  virtual void Initialize(const mitk::PixelType &type,
236  unsigned int dimension,
237  const unsigned int *dimensions,
238  unsigned int channels = 1);
239 
248  virtual void Initialize(const mitk::PixelType &type,
249  const mitk::BaseGeometry &geometry,
250  unsigned int channels = 1,
251  int tDim = 1);
252 
261  virtual void Initialize(const mitk::PixelType &type,
262  const mitk::TimeGeometry &geometry,
263  unsigned int channels = 1,
264  int tDim = -1);
265 
274  virtual void Initialize(const mitk::PixelType &type,
275  int sDim,
276  const mitk::PlaneGeometry &geometry2d,
277  unsigned int channels = 1,
278  int tDim = 1);
279 
285  virtual void Initialize(const mitk::Image *image);
286 
287  virtual void Initialize(const mitk::ImageDescriptor::Pointer inDesc);
288 
301  virtual void Initialize(vtkImageData *vtkimagedata, int channels = 1, int tDim = -1, int sDim = -1, int pDim = -1);
302 
314  template <typename itkImageType>
315  void InitializeByItk(const itkImageType *itkimage, int channels = 1, int tDim = -1, int sDim = -1)
316  {
317  if (itkimage == nullptr)
318  return;
319 
320  MITK_DEBUG << "Initializing MITK image from ITK image.";
321  // build array with dimensions in each direction with at least 4 entries
322  m_Dimension = itkimage->GetImageDimension();
323  unsigned int i, *tmpDimensions = new unsigned int[m_Dimension > 4 ? m_Dimension : 4];
324  for (i = 0; i < m_Dimension; ++i)
325  tmpDimensions[i] = itkimage->GetLargestPossibleRegion().GetSize().GetSize()[i];
326  if (m_Dimension < 4)
327  {
328  unsigned int *p;
329  for (i = 0, p = tmpDimensions + m_Dimension; i < 4 - m_Dimension; ++i, ++p)
330  *p = 1;
331  }
332 
333  // overwrite number of slices if sDim is set
334  if ((m_Dimension > 2) && (sDim >= 0))
335  tmpDimensions[2] = sDim;
336  // overwrite number of time points if tDim is set
337  if ((m_Dimension > 3) && (tDim >= 0))
338  tmpDimensions[3] = tDim;
339 
340  // rough initialization of Image
341  // mitk::PixelType importType = ImportItkPixelType( itkimage::PixelType );
342 
343  Initialize(
344  MakePixelType<itkImageType>(itkimage->GetNumberOfComponentsPerPixel()), m_Dimension, tmpDimensions, channels);
345  const typename itkImageType::SpacingType &itkspacing = itkimage->GetSpacing();
346 
347  MITK_DEBUG << "ITK spacing " << itkspacing;
348  // access spacing of itk::Image
349  Vector3D spacing;
350  FillVector3D(spacing, itkspacing[0], 1.0, 1.0);
351  if (m_Dimension >= 2)
352  spacing[1] = itkspacing[1];
353  if (m_Dimension >= 3)
354  spacing[2] = itkspacing[2];
355 
356  // access origin of itk::Image
357  Point3D origin;
358  const typename itkImageType::PointType &itkorigin = itkimage->GetOrigin();
359  MITK_DEBUG << "ITK origin " << itkorigin;
360  FillVector3D(origin, itkorigin[0], 0.0, 0.0);
361  if (m_Dimension >= 2)
362  origin[1] = itkorigin[1];
363  if (m_Dimension >= 3)
364  origin[2] = itkorigin[2];
365 
366  // access direction of itk::Imagm_PixelType = new mitk::PixelType(type);e and include spacing
367  const typename itkImageType::DirectionType &itkdirection = itkimage->GetDirection();
368  MITK_DEBUG << "ITK direction " << itkdirection;
369  mitk::Matrix3D matrix;
370  matrix.SetIdentity();
371  unsigned int j, itkDimMax3 = (m_Dimension >= 3 ? 3 : m_Dimension);
372  // check if spacing has no zero entry and itkdirection has no zero columns
373  bool itkdirectionOk = true;
374  mitk::ScalarType columnSum;
375  for (j = 0; j < itkDimMax3; ++j)
376  {
377  columnSum = 0.0;
378  for (i = 0; i < itkDimMax3; ++i)
379  {
380  columnSum += fabs(itkdirection[i][j]);
381  }
382  if (columnSum < mitk::eps)
383  {
384  itkdirectionOk = false;
385  }
386  if ((spacing[j] < -mitk::eps) // (normally sized) negative value
387  &&
388  (j == 2) && (m_Dimensions[2] == 1))
389  {
390  // Negative spacings can occur when reading single DICOM slices with ITK via GDCMIO
391  // In these cases spacing is not determined by ITK correctly (because it distinguishes correctly
392  // between slice thickness and inter slice distance -- slice distance is meaningless for
393  // single slices).
394  // I experienced that ITK produced something meaningful nonetheless because it is
395  // evaluating the tag "(0018,0088) Spacing between slices" as a fallback. This tag is not
396  // reliable (http://www.itk.org/pipermail/insight-users/2005-September/014711.html)
397  // but gives at least a hint.
398  // In real world cases I experienced that this tag contained the correct inter slice distance
399  // with a negative sign, so we just invert such negative spacings.
400  MITK_WARN << "Illegal value of itk::Image::GetSpacing()[" << j << "]=" << spacing[j]
401  << ". Using inverted value " << -spacing[j];
402  spacing[j] = -spacing[j];
403  }
404  else if (spacing[j] < mitk::eps) // value near zero
405  {
406  MITK_ERROR << "Illegal value of itk::Image::GetSpacing()[" << j << "]=" << spacing[j]
407  << ". Using 1.0 instead.";
408  spacing[j] = 1.0;
409  }
410  }
411  if (itkdirectionOk == false)
412  {
413  MITK_ERROR << "Illegal matrix returned by itk::Image::GetDirection():" << itkdirection
414  << " Using identity instead.";
415  for (i = 0; i < itkDimMax3; ++i)
416  for (j = 0; j < itkDimMax3; ++j)
417  if (i == j)
418  matrix[i][j] = spacing[j];
419  else
420  matrix[i][j] = 0.0;
421  }
422  else
423  {
424  for (i = 0; i < itkDimMax3; ++i)
425  for (j = 0; j < itkDimMax3; ++j)
426  matrix[i][j] = itkdirection[i][j] * spacing[j];
427  }
428 
429  // re-initialize PlaneGeometry with origin and direction
430  PlaneGeometry *planeGeometry = static_cast<PlaneGeometry *>(GetSlicedGeometry(0)->GetPlaneGeometry(0));
431  planeGeometry->SetOrigin(origin);
432  planeGeometry->GetIndexToWorldTransform()->SetMatrix(matrix);
433 
434  // re-initialize SlicedGeometry3D
435  SlicedGeometry3D *slicedGeometry = GetSlicedGeometry(0);
436  slicedGeometry->InitializeEvenlySpaced(planeGeometry, m_Dimensions[2]);
437  slicedGeometry->SetSpacing(spacing);
438 
439  // re-initialize TimeGeometry
440  ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New();
441  timeGeometry->Initialize(slicedGeometry, m_Dimensions[3]);
442  SetTimeGeometry(timeGeometry);
443 
444  // clean-up
445  delete[] tmpDimensions;
446 
447  this->Initialize();
448  }
449 
454  virtual bool IsValidSlice(int s = 0, int t = 0, int n = 0) const;
455 
460  virtual bool IsValidVolume(int t = 0, int n = 0) const;
461 
466  virtual bool IsValidChannel(int n = 0) const;
467 
473  bool IsRotated() const;
474 
480  unsigned int *GetDimensions() const;
481 
482  ImageDescriptor::Pointer GetImageDescriptor() const { return m_ImageDescriptor; }
483  ChannelDescriptor GetChannelDescriptor(int id = 0) const { return m_ImageDescriptor->GetChannelDescriptor(id); }
486  void SetGeometry(BaseGeometry *aGeometry3D) override;
487 
492  int t = 0,
493  int n = 0,
494  void *data = nullptr,
495  ImportMemoryManagementType importMemoryManagement = CopyMemory) const;
496 
501  int n = 0,
502  void *data = nullptr,
503  ImportMemoryManagementType importMemoryManagement = CopyMemory) const;
504 
509  void *data = nullptr,
510  ImportMemoryManagementType importMemoryManagement = CopyMemory) const;
511 
518  StatisticsHolderPointer GetStatistics() const { return m_ImageStatistics; }
519 
520  protected:
522 
523  typedef std::lock_guard<std::mutex> MutexHolder;
524 
525  int GetSliceIndex(int s = 0, int t = 0, int n = 0) const;
526 
527  int GetVolumeIndex(int t = 0, int n = 0) const;
528 
530 
531  virtual bool IsValidTimeStep(int t) const;
532 
533  void Expand(unsigned int timeSteps) override;
534 
536  int s = 0,
537  int t = 0,
538  int n = 0,
539  void *data = nullptr,
540  ImportMemoryManagementType importMemoryManagement = CopyMemory) const;
541 
543  int t = 0, int n = 0, void *data = nullptr, ImportMemoryManagementType importMemoryManagement = CopyMemory) const;
544 
546  int n = 0, void *data = nullptr, ImportMemoryManagementType importMemoryManagement = CopyMemory) const;
547 
548  Image();
549 
550  Image(const Image &other);
551 
552  ~Image() override;
553 
554  void Clear() override;
555 
557  void Initialize() override;
558 
559  void PrintSelf(std::ostream &os, itk::Indent indent) const override;
560 
564  mutable std::mutex m_ImageDataArraysLock;
565 
566  unsigned int m_Dimension;
567 
568  unsigned int *m_Dimensions;
569 
571 
572  size_t *m_OffsetTable;
574 
575  // Image statistics Holder replaces the former implementation directly inside this class
576  friend class ImageStatisticsHolder;
578 
579  private:
580  ImageDataItemPointer GetSliceData_unlocked(
581  int s, int t, int n, void *data, ImportMemoryManagementType importMemoryManagement) const;
582  ImageDataItemPointer GetVolumeData_unlocked(int t,
583  int n,
584  void *data,
585  ImportMemoryManagementType importMemoryManagement) const;
586  ImageDataItemPointer GetChannelData_unlocked(int n,
587  void *data,
588  ImportMemoryManagementType importMemoryManagement) const;
589 
590  ImageDataItemPointer AllocateSliceData_unlocked(
591  int s, int t, int n, void *data, ImportMemoryManagementType importMemoryManagement) const;
592  ImageDataItemPointer AllocateVolumeData_unlocked(int t,
593  int n,
594  void *data,
595  ImportMemoryManagementType importMemoryManagement) const;
596  ImageDataItemPointer AllocateChannelData_unlocked(int n,
597  void *data,
598  ImportMemoryManagementType importMemoryManagement) const;
599 
600  bool IsSliceSet_unlocked(int s, int t, int n) const;
601  bool IsVolumeSet_unlocked(int t, int n) const;
602  bool IsChannelSet_unlocked(int n) const;
603 
605  mutable std::vector<ImageAccessorBase *> m_Readers;
607  mutable std::vector<ImageAccessorBase *> m_Writers;
609  mutable std::vector<ImageAccessorBase *> m_VtkReaders;
610 
612  mutable std::mutex m_ReadWriteLock;
614  mutable std::mutex m_VtkReadersLock;
615  };
616 
617 
618  using ImageDimensionVectorType = std::vector<unsigned int>;
620 
639  MITKCORE_EXPORT bool Equal(const mitk::Image &leftHandSide,
640  const mitk::Image &rightHandSide,
641  ScalarType eps,
642  bool verbose);
643 
644 } // namespace mitk
645 
646 #endif
#define MITKCORE_EXPORT
BaseGeometry Describes the geometry of a data object.
void SetSpacing(const mitk::Vector3D &aSpacing, bool enforceSetSpacing=false)
Set the spacing (m_Spacing).
mitk::AffineTransform3D * GetIndexToWorldTransform()
Get the transformation used to convert from index to world coordinates.
void SetOrigin(const Point3D &origin)
Set the origin, i.e. the upper-left corner of the plane.
An object which holds all essential information about a single channel of an Image.
ImageReadAccessor class to get locked read access for a particular image part.
Class holding the statistics information about a single mitk::Image.
ImageVtkReadAccessor class provides any image read access which is required by Vtk methods.
ImageVtkWriteAccessor class provides any image write access which is required by Vtk methods.
ImageWriteAccessor class to get locked write-access for a particular image part.
Image class for storing images.
Definition: mitkImage.h:70
virtual void Initialize(const mitk::PixelType &type, int sDim, const mitk::PlaneGeometry &geometry2d, unsigned int channels=1, int tDim=1)
~Image() override
bool IsRotated() const
Returns true if an image is rotated, i.e. its geometry's transformation matrix has nonzero elements b...
ImageDataItemPointerArray m_Slices
Definition: mitkImage.h:563
void SetGeometry(BaseGeometry *aGeometry3D) override
Sets a geometry to an image.
ImageDataItemPointerArray m_Channels
Definition: mitkImage.h:561
ImageDataItemPointer m_CompleteData
Definition: mitkImage.h:573
itk::Statistics::Histogram< double > HistogramType
Definition: mitkImage.h:88
unsigned int * GetDimensions() const
Get the sizes of all dimensions as an integer-array.
void Expand(unsigned int timeSteps) override
Expands the TimeGeometry to a number of TimeSteps.
StatisticsHolderPointer m_ImageStatistics
Definition: mitkImage.h:577
virtual bool SetImportVolume(void *data, int t=0, int n=0, ImportMemoryManagementType importMemoryManagement=CopyMemory)
Set data as volume at time t in channel n. It is in the responsibility of the caller to ensure that t...
virtual ImageDataItemPointer AllocateSliceData(int s=0, int t=0, int n=0, void *data=nullptr, ImportMemoryManagementType importMemoryManagement=CopyMemory) const
std::mutex m_ImageDataArraysLock
Definition: mitkImage.h:564
std::vector< ImageDataItemPointer > ImageDataItemPointerArray
Vector container of SmartPointers to ImageDataItems; Class is only for internal usage to allow conven...
Definition: mitkImage.h:106
void Clear() override
Calls ClearData() and InitializeEmpty();.
virtual bool SetImportChannel(void *data, int n=0, ImportMemoryManagementType importMemoryManagement=CopyMemory)
Set data in channel n. It is in the responsibility of the caller to ensure that the data vector data ...
size_t * m_OffsetTable
Definition: mitkImage.h:572
mitk::ImageStatisticsHolder * StatisticsHolderPointer
Definition: mitkImage.h:89
void PrintSelf(std::ostream &os, itk::Indent indent) const override
virtual bool SetSlice(const void *data, int s=0, int t=0, int n=0)
Set data as slice s at time t in channel n. It is in the responsibility of the caller to ensure that ...
std::lock_guard< std::mutex > MutexHolder
Definition: mitkImage.h:521
itk::SmartPointer< ImageDataItem > ImageDataItemPointer
Definition: mitkImage.h:84
virtual void Initialize(const mitk::PixelType &type, const mitk::BaseGeometry &geometry, unsigned int channels=1, int tDim=1)
virtual bool IsValidVolume(int t=0, int n=0) const
Check whether volume at time t in channel n is valid, i.e., is (or can be) inside of the image.
void ComputeOffsetTable()
ImageDescriptor::Pointer GetImageDescriptor() const
Definition: mitkImage.h:482
virtual ImageDataItemPointer GetSliceData(int s=0, int t=0, int n=0, void *data=nullptr, ImportMemoryManagementType importMemoryManagement=CopyMemory) const
ChannelDescriptor GetChannelDescriptor(int id=0) const
Definition: mitkImage.h:483
virtual ImageDataItemPointer AllocateVolumeData(int t=0, int n=0, void *data=nullptr, ImportMemoryManagementType importMemoryManagement=CopyMemory) const
virtual bool SetImportSlice(void *data, int s=0, int t=0, int n=0, ImportMemoryManagementType importMemoryManagement=CopyMemory)
Set data as slice s at time t in channel n. It is in the responsibility of the caller to ensure that ...
int GetVolumeIndex(int t=0, int n=0) const
virtual void Initialize(const mitk::ImageDescriptor::Pointer inDesc)
unsigned int * m_Dimensions
Definition: mitkImage.h:568
void InitializeByItk(const itkImageType *itkimage, int channels=1, int tDim=-1, int sDim=-1)
Definition: mitkImage.h:315
virtual bool IsValidTimeStep(int t) const
virtual ImageDataItemPointer GetChannelData(int n=0, void *data=nullptr, ImportMemoryManagementType importMemoryManagement=CopyMemory) const
virtual void Initialize(vtkImageData *vtkimagedata, int channels=1, int tDim=-1, int sDim=-1, int pDim=-1)
virtual bool IsValidChannel(int n=0) const
Check whether the channel n is valid, i.e., is (or can be) inside of the image.
void Initialize() override
bool IsChannelSet(int n=0) const override
Check whether the channel n is set.
unsigned int GetDimension(int i) const
Get the size of dimension i (e.g., i=0 results in the number of pixels in x-direction).
unsigned int GetDimension() const
Get dimension of the image.
int GetSliceIndex(int s=0, int t=0, int n=0) const
bool IsVolumeSet(int t=0, int n=0) const override
Check whether volume at time t in channel n is set.
Image(const Image &other)
virtual bool SetImportVolume(const void *const_data, int t=0, int n=0)
ImageDescriptor::Pointer m_ImageDescriptor
Definition: mitkImage.h:570
virtual bool SetVolume(const void *data, int t=0, int n=0)
Set data as volume at time t in channel n. It is in the responsibility of the caller to ensure that t...
virtual ImageDataItemPointer AllocateChannelData(int n=0, void *data=nullptr, ImportMemoryManagementType importMemoryManagement=CopyMemory) const
const mitk::PixelType GetPixelType(int n=0) const
Returns the PixelType of channel n.
virtual ImageDataItemPointer GetVolumeData(int t=0, int n=0, void *data=nullptr, ImportMemoryManagementType importMemoryManagement=CopyMemory) const
bool IsSliceSet(int s=0, int t=0, int n=0) const override
Check whether slice s at time t in channel n is set.
virtual void Initialize(const mitk::PixelType &type, const mitk::TimeGeometry &geometry, unsigned int channels=1, int tDim=-1)
Initialize new (or re-initialize) image information by a TimeGeometry.
virtual vtkImageData * GetVtkImageData(int t=0, int n=0)
Get a volume at a specific time t of channel n as a vtkImageData.
unsigned int m_Dimension
Definition: mitkImage.h:566
virtual bool SetChannel(const void *data, int n=0)
Set data in channel n. It is in the responsibility of the caller to ensure that the data vector data ...
virtual const vtkImageData * GetVtkImageData(int t=0, int n=0) const
StatisticsHolderPointer GetStatistics() const
Returns a pointer to the ImageStatisticsHolder object that holds all statistics information for the i...
Definition: mitkImage.h:518
ImportMemoryManagementType
Definition: mitkImage.h:94
@ ReferenceMemory
Definition: mitkImage.h:97
@ ManageMemory
Definition: mitkImage.h:96
virtual void Initialize(const mitk::PixelType &type, unsigned int dimension, const unsigned int *dimensions, unsigned int channels=1)
ImageDataItemPointerArray m_Volumes
Definition: mitkImage.h:562
virtual void Initialize(const mitk::Image *image)
virtual bool IsValidSlice(int s=0, int t=0, int n=0) const
Check whether slice s at time t in channel n is valid, i.e., is (or can be) inside of the image.
Class for defining the data type of pixels.
Definition: mitkPixelType.h:52
Describes a two-dimensional, rectangular plane.
Super class of data objects consisting of slices.
Describes the geometry of a data object consisting of slices.
virtual void InitializeEvenlySpaced(mitk::PlaneGeometry *geometry2D, unsigned int slices)
Completely initialize this instance as evenly-spaced with slices parallel to the provided PlaneGeomet...
Base class of all classes providing access to parts of an image.
#define mitkClassMacro(className, SuperClassName)
Definition: mitkCommon.h:36
#define mitkCloneMacro(classname)
Definition: mitkCommon.h:154
#define MITK_ERROR
Definition: mitkLog.h:211
#define MITK_WARN
Definition: mitkLog.h:210
#define MITK_DEBUG
Definition: mitkLog.h:217
Find image slices visible on a given plane.
MITKCORE_EXPORT const ScalarType eps
MITKCORE_EXPORT ImageDimensionVectorType DetermineImageDimensionsFromTimeGeometry(const TimeGeometry *timeGeometry)
std::vector< unsigned int > ImageDimensionVectorType
Definition: mitkImage.h:618
void FillVector3D(Tout &out, mitk::ScalarType x, mitk::ScalarType y, mitk::ScalarType z)
Definition: mitkArray.h:105
double ScalarType
MITKNEWMODULE_EXPORT bool Equal(mitk::ExampleDataStructure *leftHandSide, mitk::ExampleDataStructure *rightHandSide, mitk::ScalarType eps, bool verbose)
Returns true if the example data structures are considered equal.