Medical Imaging Interaction Toolkit  2024.12.99-0da743f6
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
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 
491  virtual ImageDataItemPointer GetSliceData(int s = 0,
492  int t = 0,
493  int n = 0,
494  void *data = nullptr,
495  ImportMemoryManagementType importMemoryManagement = CopyMemory) const;
496 
500  virtual ImageDataItemPointer GetVolumeData(int t = 0,
501  int n = 0,
502  void *data = nullptr,
503  ImportMemoryManagementType importMemoryManagement = CopyMemory) const;
504 
508  virtual ImageDataItemPointer GetChannelData(int n = 0,
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 
529  void ComputeOffsetTable();
530 
531  virtual bool IsValidTimeStep(int t) const;
532 
533  void Expand(unsigned int timeSteps) override;
534 
535  virtual ImageDataItemPointer AllocateSliceData(
536  int s = 0,
537  int t = 0,
538  int n = 0,
539  void *data = nullptr,
540  ImportMemoryManagementType importMemoryManagement = CopyMemory) const;
541 
542  virtual ImageDataItemPointer AllocateVolumeData(
543  int t = 0, int n = 0, void *data = nullptr, ImportMemoryManagementType importMemoryManagement = CopyMemory) const;
544 
545  virtual ImageDataItemPointer AllocateChannelData(
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 
635  MITKCORE_EXPORT bool Equal(const mitk::Image &leftHandSide,
636  const mitk::Image &rightHandSide,
637  ScalarType eps,
638  bool verbose);
639 
640 } // namespace mitk
641 
642 #endif
mitk::ImageVtkWriteAccessor
ImageVtkWriteAccessor class provides any image write access which is required by Vtk methods.
Definition: mitkImageVtkWriteAccessor.h:29
mitk::ChannelDescriptor
An object which holds all essential information about a single channel of an Image.
Definition: mitkChannelDescriptor.h:27
mitk::eps
const MITKCORE_EXPORT ScalarType eps
mitk::ImageStatisticsHolder
Class holding the statistics information about a single mitk::Image.
Definition: mitkImageStatisticsHolder.h:36
mitk::Image::HistogramType
itk::Statistics::Histogram< double > HistogramType
Definition: mitkImage.h:88
mitkImageAccessorBase.h
mitk::TimeGeometry
Definition: mitkTimeGeometry.h:45
mitk::SubImageSelector
Base class of all classes providing access to parts of an image.
Definition: mitkSubImageSelector.h:31
mitk::Image::StatisticsHolderPointer
mitk::ImageStatisticsHolder * StatisticsHolderPointer
Definition: mitkImage.h:89
mitk::SlicedData
Super class of data objects consisting of slices.
Definition: mitkSlicedData.h:37
mitk::Image::m_Dimensions
unsigned int * m_Dimensions
Definition: mitkImage.h:568
mitk::PlaneGeometry
Describes a two-dimensional, rectangular plane.
Definition: mitkPlaneGeometry.h:78
mitk::ImageWriteAccessor
ImageWriteAccessor class to get locked write-access for a particular image part.
Definition: mitkImageWriteAccessor.h:25
mitk::SlicedGeometry3D::InitializeEvenlySpaced
virtual void InitializeEvenlySpaced(mitk::PlaneGeometry *geometry2D, unsigned int slices)
Completely initialize this instance as evenly-spaced with slices parallel to the provided PlaneGeomet...
mitk::Image::ImportMemoryManagementType
ImportMemoryManagementType
Definition: mitkImage.h:93
MITK_ERROR
#define MITK_ERROR
Definition: mitkLog.h:211
mitk::BaseGeometry::SetOrigin
void SetOrigin(const Point3D &origin)
Set the origin, i.e. the upper-left corner of the plane.
mitk::Image::m_Slices
ImageDataItemPointerArray m_Slices
Definition: mitkImage.h:563
mitk::ImageAccessorBase
Definition: mitkImageAccessorBase.h:48
mitk::Image
Image class for storing images.
Definition: mitkImage.h:69
mitk::Equal
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.
itk::SmartPointer< ImageDataItem >
mitk::Image::m_ImageStatistics
StatisticsHolderPointer m_ImageStatistics
Definition: mitkImage.h:577
mitk::Image::MutexHolder
std::lock_guard< std::mutex > MutexHolder
Definition: mitkImage.h:521
mitk::ProportionalTimeGeometry::New
static Pointer New()
mitk
Find image slices visible on a given plane.
Definition: RenderingTests.dox:1
mitk::ImageReadAccessor
ImageReadAccessor class to get locked read access for a particular image part.
Definition: mitkImageReadAccessor.h:27
mitkProportionalTimeGeometry.h
mitk::Image::ManageMemory
@ ManageMemory
Definition: mitkImage.h:96
mitk::Image::ImageDataItemPointer
itk::SmartPointer< ImageDataItem > ImageDataItemPointer
Definition: mitkImage.h:84
mitk::GetPixelType
Definition: mitkPixelTypeList.h:89
MITK_DEBUG
#define MITK_DEBUG
Definition: mitkLog.h:217
mitk::Image::m_Dimension
unsigned int m_Dimension
Definition: mitkImage.h:566
mitk::Vector< ScalarType, 3 >
mitkSlicedData.h
MitkCoreExports.h
mitk::BaseGeometry
BaseGeometry Describes the geometry of a data object.
Definition: mitkBaseGeometry.h:94
mitk::Point< ScalarType, 3 >
mitk::Matrix
Definition: mitkMatrix.h:25
mitk::Image::m_Channels
ImageDataItemPointerArray m_Channels
Definition: mitkImage.h:561
mitkImageDataItem.h
mitk::FillVector3D
void FillVector3D(Tout &out, mitk::ScalarType x, mitk::ScalarType y, mitk::ScalarType z)
Definition: mitkArray.h:105
mitk::Image::InitializeByItk
void InitializeByItk(const itkImageType *itkimage, int channels=1, int tDim=-1, int sDim=-1)
Definition: mitkImage.h:315
mitk::Image::m_CompleteData
ImageDataItemPointer m_CompleteData
Definition: mitkImage.h:573
mitk::PixelType
Class for defining the data type of pixels.
Definition: mitkPixelType.h:51
mitk::Image::GetStatistics
StatisticsHolderPointer GetStatistics() const
Returns a pointer to the ImageStatisticsHolder object that holds all statistics information for the i...
Definition: mitkImage.h:518
mitk::BaseData
Base of all data objects.
Definition: mitkBaseData.h:42
mitk::Image::m_ImageDescriptor
ImageDescriptor::Pointer m_ImageDescriptor
Definition: mitkImage.h:570
mitk::Image::CopyMemory
@ CopyMemory
Definition: mitkImage.h:95
mitkImageDescriptor.h
mitk::SlicedGeometry3D
Describes the geometry of a data object consisting of slices.
Definition: mitkSlicedGeometry3D.h:62
mitk::ImageVtkReadAccessor
ImageVtkReadAccessor class provides any image read access which is required by Vtk methods.
Definition: mitkImageVtkReadAccessor.h:29
itk
SET FUNCTIONS.
Definition: itkIntelligentBinaryClosingFilter.h:30
mitkCloneMacro
#define mitkCloneMacro(classname)
Definition: mitkCommon.h:154
MITK_WARN
#define MITK_WARN
Definition: mitkLog.h:210
mitk::Image::ReferenceMemory
@ ReferenceMemory
Definition: mitkImage.h:97
mitkBaseData.h
mitkLevelWindow.h
mitk::Image::m_ImageDataArraysLock
std::mutex m_ImageDataArraysLock
Definition: mitkImage.h:564
mitk::Image::m_OffsetTable
size_t * m_OffsetTable
Definition: mitkImage.h:572
mitkClassMacro
#define mitkClassMacro(className, SuperClassName)
Definition: mitkCommon.h:36
itk::Image
class ITK_EXPORT Image
Definition: mitkGeometryClipImageFilter.h:25
itk::MutexLockHolder
Definition: mitkImage.h:36
mitk::Image::m_Volumes
ImageDataItemPointerArray m_Volumes
Definition: mitkImage.h:562
mitk::Image::ImageDataItemPointerArray
std::vector< ImageDataItemPointer > ImageDataItemPointerArray
Vector container of SmartPointers to ImageDataItems; Class is only for internal usage to allow conven...
Definition: mitkImage.h:106
mitk::Image::GetImageDescriptor
ImageDescriptor::Pointer GetImageDescriptor() const
Definition: mitkImage.h:482
mitk::Image::GetChannelDescriptor
ChannelDescriptor GetChannelDescriptor(int id=0) const
Definition: mitkImage.h:483
MITKCORE_EXPORT
#define MITKCORE_EXPORT
Definition: MitkCoreExports.h:15
mitkImageVtkWriteAccessor.h
mitk::BaseGeometry::GetIndexToWorldTransform
mitk::AffineTransform3D * GetIndexToWorldTransform()
Get the transformation used to convert from index to world coordinates.
mitk::ScalarType
double ScalarType
Definition: mitkNumericConstants.h:20
mitkPlaneGeometry.h
mitk::BaseGeometry::SetSpacing
void SetSpacing(const mitk::Vector3D &aSpacing, bool enforceSetSpacing=false)
Set the spacing (m_Spacing).