Medical Imaging Interaction Toolkit  2021.02.99-89548602
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_HEADER_INCLUDED_C1C2FCD2
14 #define MITKIMAGE_H_HEADER_INCLUDED_C1C2FCD2
15 
16 #include "mitkBaseData.h"
17 #include "mitkImageAccessorBase.h"
18 #include "mitkImageDataItem.h"
19 #include "mitkImageDescriptor.h"
20 #include "mitkImageVtkAccessor.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 
71  {
72  friend class SubImageSelector;
73 
74  friend class ImageAccessorBase;
75  friend class ImageVtkAccessor;
76  friend class ImageVtkReadAccessor;
77  friend class ImageVtkWriteAccessor;
78  friend class ImageReadAccessor;
79  friend class ImageWriteAccessor;
80 
81  public:
83 
84  itkFactorylessNewMacro(Self);
85 
86  itkCloneMacro(Self);
87 
90  typedef itk::Statistics::Histogram<double> HistogramType;
92 
96  {
100  DontManageMemory = ReferenceMemory
101  };
102 
108  typedef std::vector<ImageDataItemPointer> ImageDataItemPointerArray;
109 
110  public:
114  const mitk::PixelType GetPixelType(int n = 0) const;
115 
119  unsigned int GetDimension() const;
120 
126  unsigned int GetDimension(int i) const;
127 
128  public:
132  virtual vtkImageData *GetVtkImageData(int t = 0, int n = 0);
133  virtual const vtkImageData *GetVtkImageData(int t = 0, int n = 0) const;
134 
138  bool IsSliceSet(int s = 0, int t = 0, int n = 0) const override;
139 
143  bool IsVolumeSet(int t = 0, int n = 0) const override;
144 
148  bool IsChannelSet(int n = 0) const override;
149 
162  virtual bool SetSlice(const void *data, int s = 0, int t = 0, int n = 0);
163 
176  virtual bool SetVolume(const void *data, int t = 0, int n = 0);
177 
190  virtual bool SetChannel(const void *data, int n = 0);
191 
201  virtual bool SetImportSlice(
202  void *data, int s = 0, int t = 0, int n = 0, ImportMemoryManagementType importMemoryManagement = CopyMemory);
203 
213  virtual bool SetImportVolume(void *data,
214  int t = 0,
215  int n = 0,
216  ImportMemoryManagementType importMemoryManagement = CopyMemory);
217 
218  virtual bool SetImportVolume(const void *const_data, int t = 0, int n = 0);
219 
229  virtual bool SetImportChannel(void *data,
230  int n = 0,
231  ImportMemoryManagementType importMemoryManagement = CopyMemory);
232 
237  virtual void Initialize(const mitk::PixelType &type,
238  unsigned int dimension,
239  const unsigned int *dimensions,
240  unsigned int channels = 1);
241 
250  virtual void Initialize(const mitk::PixelType &type,
251  const mitk::BaseGeometry &geometry,
252  unsigned int channels = 1,
253  int tDim = 1);
254 
263  virtual void Initialize(const mitk::PixelType &type,
264  const mitk::TimeGeometry &geometry,
265  unsigned int channels = 1,
266  int tDim = -1);
267 
276  virtual void Initialize(const mitk::PixelType &type,
277  int sDim,
278  const mitk::PlaneGeometry &geometry2d,
279  unsigned int channels = 1,
280  int tDim = 1);
281 
287  virtual void Initialize(const mitk::Image *image);
288 
289  virtual void Initialize(const mitk::ImageDescriptor::Pointer inDesc);
290 
303  virtual void Initialize(vtkImageData *vtkimagedata, int channels = 1, int tDim = -1, int sDim = -1, int pDim = -1);
304 
316  template <typename itkImageType>
317  void InitializeByItk(const itkImageType *itkimage, int channels = 1, int tDim = -1, int sDim = -1)
318  {
319  if (itkimage == nullptr)
320  return;
321 
322  MITK_DEBUG << "Initializing MITK image from ITK image.";
323  // build array with dimensions in each direction with at least 4 entries
324  m_Dimension = itkimage->GetImageDimension();
325  unsigned int i, *tmpDimensions = new unsigned int[m_Dimension > 4 ? m_Dimension : 4];
326  for (i = 0; i < m_Dimension; ++i)
327  tmpDimensions[i] = itkimage->GetLargestPossibleRegion().GetSize().GetSize()[i];
328  if (m_Dimension < 4)
329  {
330  unsigned int *p;
331  for (i = 0, p = tmpDimensions + m_Dimension; i < 4 - m_Dimension; ++i, ++p)
332  *p = 1;
333  }
334 
335  // overwrite number of slices if sDim is set
336  if ((m_Dimension > 2) && (sDim >= 0))
337  tmpDimensions[2] = sDim;
338  // overwrite number of time points if tDim is set
339  if ((m_Dimension > 3) && (tDim >= 0))
340  tmpDimensions[3] = tDim;
341 
342  // rough initialization of Image
343  // mitk::PixelType importType = ImportItkPixelType( itkimage::PixelType );
344 
345  Initialize(
346  MakePixelType<itkImageType>(itkimage->GetNumberOfComponentsPerPixel()), m_Dimension, tmpDimensions, channels);
347  const typename itkImageType::SpacingType &itkspacing = itkimage->GetSpacing();
348 
349  MITK_DEBUG << "ITK spacing " << itkspacing;
350  // access spacing of itk::Image
351  Vector3D spacing;
352  FillVector3D(spacing, itkspacing[0], 1.0, 1.0);
353  if (m_Dimension >= 2)
354  spacing[1] = itkspacing[1];
355  if (m_Dimension >= 3)
356  spacing[2] = itkspacing[2];
357 
358  // access origin of itk::Image
359  Point3D origin;
360  const typename itkImageType::PointType &itkorigin = itkimage->GetOrigin();
361  MITK_DEBUG << "ITK origin " << itkorigin;
362  FillVector3D(origin, itkorigin[0], 0.0, 0.0);
363  if (m_Dimension >= 2)
364  origin[1] = itkorigin[1];
365  if (m_Dimension >= 3)
366  origin[2] = itkorigin[2];
367 
368  // access direction of itk::Imagm_PixelType = new mitk::PixelType(type);e and include spacing
369  const typename itkImageType::DirectionType &itkdirection = itkimage->GetDirection();
370  MITK_DEBUG << "ITK direction " << itkdirection;
371  mitk::Matrix3D matrix;
372  matrix.SetIdentity();
373  unsigned int j, itkDimMax3 = (m_Dimension >= 3 ? 3 : m_Dimension);
374  // check if spacing has no zero entry and itkdirection has no zero columns
375  bool itkdirectionOk = true;
376  mitk::ScalarType columnSum;
377  for (j = 0; j < itkDimMax3; ++j)
378  {
379  columnSum = 0.0;
380  for (i = 0; i < itkDimMax3; ++i)
381  {
382  columnSum += fabs(itkdirection[i][j]);
383  }
384  if (columnSum < mitk::eps)
385  {
386  itkdirectionOk = false;
387  }
388  if ((spacing[j] < -mitk::eps) // (normally sized) negative value
389  &&
390  (j == 2) && (m_Dimensions[2] == 1))
391  {
392  // Negative spacings can occur when reading single DICOM slices with ITK via GDCMIO
393  // In these cases spacing is not determind by ITK correctly (because it distinguishes correctly
394  // between slice thickness and inter slice distance -- slice distance is meaningless for
395  // single slices).
396  // I experienced that ITK produced something meaningful nonetheless because is is
397  // evaluating the tag "(0018,0088) Spacing between slices" as a fallback. This tag is not
398  // reliable (http://www.itk.org/pipermail/insight-users/2005-September/014711.html)
399  // but gives at least a hint.
400  // In real world cases I experienced that this tag contained the correct inter slice distance
401  // with a negative sign, so we just invert such negative spacings.
402  MITK_WARN << "Illegal value of itk::Image::GetSpacing()[" << j << "]=" << spacing[j]
403  << ". Using inverted value " << -spacing[j];
404  spacing[j] = -spacing[j];
405  }
406  else if (spacing[j] < mitk::eps) // value near zero
407  {
408  MITK_ERROR << "Illegal value of itk::Image::GetSpacing()[" << j << "]=" << spacing[j]
409  << ". Using 1.0 instead.";
410  spacing[j] = 1.0;
411  }
412  }
413  if (itkdirectionOk == false)
414  {
415  MITK_ERROR << "Illegal matrix returned by itk::Image::GetDirection():" << itkdirection
416  << " Using identity instead.";
417  for (i = 0; i < itkDimMax3; ++i)
418  for (j = 0; j < itkDimMax3; ++j)
419  if (i == j)
420  matrix[i][j] = spacing[j];
421  else
422  matrix[i][j] = 0.0;
423  }
424  else
425  {
426  for (i = 0; i < itkDimMax3; ++i)
427  for (j = 0; j < itkDimMax3; ++j)
428  matrix[i][j] = itkdirection[i][j] * spacing[j];
429  }
430 
431  // re-initialize PlaneGeometry with origin and direction
432  PlaneGeometry *planeGeometry = static_cast<PlaneGeometry *>(GetSlicedGeometry(0)->GetPlaneGeometry(0));
433  planeGeometry->SetOrigin(origin);
434  planeGeometry->GetIndexToWorldTransform()->SetMatrix(matrix);
435 
436  // re-initialize SlicedGeometry3D
437  SlicedGeometry3D *slicedGeometry = GetSlicedGeometry(0);
438  slicedGeometry->InitializeEvenlySpaced(planeGeometry, m_Dimensions[2]);
439  slicedGeometry->SetSpacing(spacing);
440 
441  // re-initialize TimeGeometry
442  ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New();
443  timeGeometry->Initialize(slicedGeometry, m_Dimensions[3]);
444  SetTimeGeometry(timeGeometry);
445 
446  // clean-up
447  delete[] tmpDimensions;
448 
449  this->Initialize();
450  }
451 
456  virtual bool IsValidSlice(int s = 0, int t = 0, int n = 0) const;
457 
462  virtual bool IsValidVolume(int t = 0, int n = 0) const;
463 
468  virtual bool IsValidChannel(int n = 0) const;
469 
475  bool IsRotated() const;
476 
482  unsigned int *GetDimensions() const;
483 
484  ImageDescriptor::Pointer GetImageDescriptor() const { return m_ImageDescriptor; }
485  ChannelDescriptor GetChannelDescriptor(int id = 0) const { return m_ImageDescriptor->GetChannelDescriptor(id); }
488  void SetGeometry(BaseGeometry *aGeometry3D) override;
489 
493  virtual ImageDataItemPointer GetSliceData(int s = 0,
494  int t = 0,
495  int n = 0,
496  void *data = nullptr,
497  ImportMemoryManagementType importMemoryManagement = CopyMemory) const;
498 
502  virtual ImageDataItemPointer GetVolumeData(int t = 0,
503  int n = 0,
504  void *data = nullptr,
505  ImportMemoryManagementType importMemoryManagement = CopyMemory) const;
506 
510  virtual ImageDataItemPointer GetChannelData(int n = 0,
511  void *data = nullptr,
512  ImportMemoryManagementType importMemoryManagement = CopyMemory) const;
513 
520  StatisticsHolderPointer GetStatistics() const { return m_ImageStatistics; }
521 
522  protected:
524 
526 
527  int GetSliceIndex(int s = 0, int t = 0, int n = 0) const;
528 
529  int GetVolumeIndex(int t = 0, int n = 0) const;
530 
531  void ComputeOffsetTable();
532 
533  virtual bool IsValidTimeStep(int t) const;
534 
535  void Expand(unsigned int timeSteps) override;
536 
537  virtual ImageDataItemPointer AllocateSliceData(
538  int s = 0,
539  int t = 0,
540  int n = 0,
541  void *data = nullptr,
542  ImportMemoryManagementType importMemoryManagement = CopyMemory) const;
543 
544  virtual ImageDataItemPointer AllocateVolumeData(
545  int t = 0, int n = 0, void *data = nullptr, ImportMemoryManagementType importMemoryManagement = CopyMemory) const;
546 
547  virtual ImageDataItemPointer AllocateChannelData(
548  int n = 0, void *data = nullptr, ImportMemoryManagementType importMemoryManagement = CopyMemory) const;
549 
550  Image();
551 
552  Image(const Image &other);
553 
554  ~Image() override;
555 
556  void Clear() override;
557 
559  void Initialize() override;
560 
561  void PrintSelf(std::ostream &os, itk::Indent indent) const override;
562 
563  mutable ImageDataItemPointerArray m_Channels;
564  mutable ImageDataItemPointerArray m_Volumes;
565  mutable ImageDataItemPointerArray m_Slices;
566  mutable itk::SimpleFastMutexLock m_ImageDataArraysLock;
567 
568  unsigned int m_Dimension;
569 
570  unsigned int *m_Dimensions;
571 
573 
574  size_t *m_OffsetTable;
575  ImageDataItemPointer m_CompleteData;
576 
577  // Image statistics Holder replaces the former implementation directly inside this class
578  friend class ImageStatisticsHolder;
579  StatisticsHolderPointer m_ImageStatistics;
580 
581  private:
582  ImageDataItemPointer GetSliceData_unlocked(
583  int s, int t, int n, void *data, ImportMemoryManagementType importMemoryManagement) const;
584  ImageDataItemPointer GetVolumeData_unlocked(int t,
585  int n,
586  void *data,
587  ImportMemoryManagementType importMemoryManagement) const;
588  ImageDataItemPointer GetChannelData_unlocked(int n,
589  void *data,
590  ImportMemoryManagementType importMemoryManagement) const;
591 
592  ImageDataItemPointer AllocateSliceData_unlocked(
593  int s, int t, int n, void *data, ImportMemoryManagementType importMemoryManagement) const;
594  ImageDataItemPointer AllocateVolumeData_unlocked(int t,
595  int n,
596  void *data,
597  ImportMemoryManagementType importMemoryManagement) const;
598  ImageDataItemPointer AllocateChannelData_unlocked(int n,
599  void *data,
600  ImportMemoryManagementType importMemoryManagement) const;
601 
602  bool IsSliceSet_unlocked(int s, int t, int n) const;
603  bool IsVolumeSet_unlocked(int t, int n) const;
604  bool IsChannelSet_unlocked(int n) const;
605 
607  mutable std::vector<ImageAccessorBase *> m_Readers;
609  mutable std::vector<ImageAccessorBase *> m_Writers;
611  mutable std::vector<ImageAccessorBase *> m_VtkReaders;
612 
614  itk::SimpleFastMutexLock m_ReadWriteLock;
616  itk::SimpleFastMutexLock m_VtkReadersLock;
617  };
618 
637  MITKCORE_EXPORT bool Equal(const mitk::Image &leftHandSide,
638  const mitk::Image &rightHandSide,
639  ScalarType eps,
640  bool verbose);
641 
642 } // namespace mitk
643 
644 #endif /* MITKIMAGE_H_HEADER_INCLUDED_C1C2FCD2 */
itk::SmartPointer< ImageDataItem > ImageDataItemPointer
Definition: mitkImage.h:86
unsigned int * m_Dimensions
Definition: mitkImage.h:570
MITKCORE_EXPORT const ScalarType eps
void SetSpacing(const mitk::Vector3D &aSpacing, bool enforceSetSpacing=false)
Set the spacing (m_Spacing).
#define MITKCORE_EXPORT
Base of all data objects.
Definition: mitkBaseData.h:42
#define MITK_ERROR
Definition: mitkLogMacros.h:20
double ScalarType
ImageDataItemPointerArray m_Slices
Definition: mitkImage.h:565
vcl_size_t * m_OffsetTable
Definition: mitkImage.h:574
#define MITK_DEBUG
Definition: mitkLogMacros.h:22
DataCollection - Class to facilitate loading/accessing structured data.
ImageDataItemPointerArray m_Channels
Definition: mitkImage.h:563
StatisticsHolderPointer GetStatistics() const
Returns a pointer to the ImageStatisticsHolder object that holds all statistics information for the i...
Definition: mitkImage.h:520
An object which holds all essential information about a single channel of an Image.
ImageVtkAccessor class provides any image read access which is required by Vtk methods.
void FillVector3D(Tout &out, mitk::ScalarType x, mitk::ScalarType y, mitk::ScalarType z)
Definition: mitkArray.h:106
ImageDataItemPointerArray m_Volumes
Definition: mitkImage.h:564
ChannelDescriptor GetChannelDescriptor(int id=0) const
Definition: mitkImage.h:485
itk::Statistics::Histogram< double > HistogramType
Definition: mitkImage.h:90
itk::SimpleFastMutexLock m_ImageDataArraysLock
Definition: mitkImage.h:566
mitk::ImageStatisticsHolder * StatisticsHolderPointer
Definition: mitkImage.h:91
StatisticsHolderPointer m_ImageStatistics
Definition: mitkImage.h:579
virtual void InitializeEvenlySpaced(mitk::PlaneGeometry *geometry2D, unsigned int slices)
Completely initialize this instance as evenly-spaced with slices parallel to the provided PlaneGeomet...
class ITK_EXPORT Image
#define MITK_WARN
Definition: mitkLogMacros.h:19
Super class of data objects consisting of slices.
std::vector< ImageDataItemPointer > ImageDataItemPointerArray
Vector container of SmartPointers to ImageDataItems; Class is only for internal usage to allow conven...
Definition: mitkImage.h:108
#define mitkClassMacro(className, SuperClassName)
Definition: mitkCommon.h:40
void SetOrigin(const Point3D &origin)
Set the origin, i.e. the upper-left corner of the plane.
Image class for storing images.
Definition: mitkImage.h:70
unsigned int m_Dimension
Definition: mitkImage.h:568
itk::MutexLockHolder< itk::SimpleFastMutexLock > MutexHolder
Definition: mitkImage.h:523
Describes the geometry of a data object consisting of slices.
#define mitkCloneMacro(classname)
Definition: mitkCommon.h:158
Class holding the statistics informations about a single mitk::Image.
ImageVtkReadAccessor class provides any image read access which is required by Vtk methods...
mitk::AffineTransform3D * GetIndexToWorldTransform()
Get the transformation used to convert from index to world coordinates.
Base class of all classes providing access to parts of an image.
ImageWriteAccessor class to get locked write-access for a particular image part.
Describes a two-dimensional, rectangular plane.
ImageDescriptor::Pointer GetImageDescriptor() const
Definition: mitkImage.h:484
ImageReadAccessor class to get locked read access for a particular image part.
ImageVtkWriteAccessor class provides any image write access which is required by Vtk methods...
ImageDataItemPointer m_CompleteData
Definition: mitkImage.h:575
MITKCORE_EXPORT bool Equal(const mitk::Image &leftHandSide, const mitk::Image &rightHandSide, ScalarType eps, bool verbose)
Equal A function comparing two images for beeing equal in meta- and imagedata.
ImportMemoryManagementType
Definition: mitkImage.h:95
BaseGeometry Describes the geometry of a data object.
void InitializeByItk(const itkImageType *itkimage, int channels=1, int tDim=-1, int sDim=-1)
Definition: mitkImage.h:317
Class for defining the data type of pixels.
Definition: mitkPixelType.h:51
ImageDescriptor::Pointer m_ImageDescriptor
Definition: mitkImage.h:572