Medical Imaging Interaction Toolkit  2018.4.99-87d68d9f
Medical Imaging Interaction Toolkit
mitkImage.cpp
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 // MITK
14 #include "mitkImage.h"
19 #include "mitkPixelTypeMultiplex.h"
21 
22 // VTK
23 #include <vtkImageData.h>
24 
25 // ITK
26 #include <itkMutexLockHolder.h>
27 
28 // Other
29 #include <cmath>
30 
31 #define FILL_C_ARRAY(_arr, _size, _value) \
32  for (unsigned int i = 0u; i < _size; i++) \
33  \
34  { \
35  _arr[i] = _value; \
36  }
37 
39  : m_Dimension(0),
40  m_Dimensions(nullptr),
41  m_ImageDescriptor(nullptr),
42  m_OffsetTable(nullptr),
43  m_CompleteData(nullptr),
44  m_ImageStatistics(nullptr)
45 {
46  m_Dimensions = new unsigned int[MAX_IMAGE_DIMENSIONS];
48 
49  m_Initialized = false;
50 }
51 
53  : SlicedData(other),
54  m_Dimension(0),
55  m_Dimensions(nullptr),
56  m_ImageDescriptor(nullptr),
57  m_OffsetTable(nullptr),
58  m_CompleteData(nullptr),
59  m_ImageStatistics(nullptr)
60 {
61  m_Dimensions = new unsigned int[MAX_IMAGE_DIMENSIONS];
63 
64  this->Initialize(other.GetPixelType(), other.GetDimension(), other.GetDimensions());
65 
66  // Since the above called "Initialize" method doesn't take the geometry into account we need to set it
67  // here manually
68  TimeGeometry::Pointer cloned = other.GetTimeGeometry()->Clone();
69  this->SetTimeGeometry(cloned.GetPointer());
70 
71  if (this->GetDimension() > 3)
72  {
73  const unsigned int time_steps = this->GetDimension(3);
74 
75  for (unsigned int i = 0u; i < time_steps; ++i)
76  {
77  ImageDataItemPointer volume = other.GetVolumeData(i);
78 
79  this->SetVolume(volume->GetData(), i);
80  }
81  }
82  else
83  {
84  ImageDataItemPointer volume = other.GetVolumeData(0);
85 
86  this->SetVolume(volume->GetData(), 0);
87  }
88 }
89 
91 {
92  this->Clear();
93 
94  m_ReferenceCount = 3;
95  m_ReferenceCount = 0;
96 
97  delete[] m_OffsetTable;
98  delete m_ImageStatistics;
99 }
100 
102 {
103  return this->m_ImageDescriptor->GetChannelTypeById(n);
104 }
105 
106 unsigned int mitk::Image::GetDimension() const
107 {
108  return m_Dimension;
109 }
110 
111 unsigned int mitk::Image::GetDimension(int i) const
112 {
113  if ((i >= 0) && (i < (int)m_Dimension))
114  return m_Dimensions[i];
115  return 1;
116 }
117 
119 {
120  if (m_Initialized == false)
121  {
122  if (GetSource().IsNull())
123  return nullptr;
124  if (GetSource()->Updating() == false)
125  GetSource()->UpdateOutputInformation();
126  }
128 
129  // update channel's data
130  // if data was not available at creation point, the m_Data of channel descriptor is nullptr
131  // if data present, it won't be overwritten
132  m_ImageDescriptor->GetChannelDescriptor(0).SetData(m_CompleteData->GetData());
133 
134  return m_CompleteData->GetData();
135 }
136 
137 template <class T>
138 void AccessPixel(const mitk::PixelType ptype, void *data, const unsigned int offset, double &value)
139 {
140  value = 0.0;
141  if (data == nullptr)
142  return;
143 
144  if (ptype.GetBpe() != 24)
145  {
146  value = (double)(((T *)data)[offset]);
147  }
148  else
149  {
150  const unsigned int rgboffset = offset;
151 
152  double returnvalue = (((T *)data)[rgboffset]);
153  returnvalue += (((T *)data)[rgboffset + 1]);
154  returnvalue += (((T *)data)[rgboffset + 2]);
155  value = returnvalue;
156  }
157 }
158 
159 double mitk::Image::GetPixelValueByIndex(const itk::Index<3> &position, unsigned int timestep, unsigned int component)
160 {
161  double value = 0;
162  if (this->GetTimeSteps() < timestep)
163  {
164  timestep = this->GetTimeSteps();
165  }
166 
167  value = 0.0;
168 
169  const unsigned int *imageDims = this->m_ImageDescriptor->GetDimensions();
170  const mitk::PixelType ptype = this->m_ImageDescriptor->GetChannelTypeById(0);
171 
172  // Comparison ?>=0 not needed since all position[i] and timestep are unsigned int
173  // (position[0]>=0 && position[1] >=0 && position[2]>=0 && timestep>=0)
174  // bug-11978 : we still need to catch index with negative values
175  if (position[0] < 0 || position[1] < 0 || position[2] < 0)
176  {
177  MITK_WARN << "Given position (" << position << ") is out of image range, returning 0.";
178  }
179  // check if the given position is inside the index range of the image, the 3rd dimension needs to be compared only if
180  // the dimension is not 0
181  else if ((unsigned int)position[0] >= imageDims[0] || (unsigned int)position[1] >= imageDims[1] ||
182  (imageDims[2] && (unsigned int)position[2] >= imageDims[2]))
183  {
184  MITK_WARN << "Given position (" << position << ") is out of image range, returning 0.";
185  }
186  else
187  {
188  const unsigned int offset = component +
189  ptype.GetNumberOfComponents() * (position[0] + position[1] * imageDims[0] +
190  position[2] * imageDims[0] * imageDims[1] +
191  timestep * imageDims[0] * imageDims[1] * imageDims[2]);
192 
193  mitkPixelTypeMultiplex3(AccessPixel, ptype, this->GetData(), offset, value);
194  }
195 
196  return value;
197 }
198 
200  unsigned int timestep,
201  unsigned int component)
202 {
203  double value = 0.0;
204  if (this->GetTimeSteps() < timestep)
205  {
206  timestep = this->GetTimeSteps();
207  }
208 
209  itk::Index<3> itkIndex;
210  this->GetGeometry()->WorldToIndex(position, itkIndex);
211 
212  value = this->GetPixelValueByIndex(itkIndex, timestep, component);
213 
214  return value;
215 }
216 
217 vtkImageData *mitk::Image::GetVtkImageData(int t, int n)
218 {
219  if (m_Initialized == false)
220  {
221  if (GetSource().IsNull())
222  return nullptr;
223  if (GetSource()->Updating() == false)
224  GetSource()->UpdateOutputInformation();
225  }
226  ImageDataItemPointer volume = GetVolumeData(t, n);
227  return volume.GetPointer() == nullptr ? nullptr : volume->GetVtkImageAccessor(this)->GetVtkImageData();
228 }
229 
230 const vtkImageData *mitk::Image::GetVtkImageData(int t, int n) const
231 {
232  if (m_Initialized == false)
233  {
234  if (GetSource().IsNull())
235  return nullptr;
236  if (GetSource()->Updating() == false)
237  GetSource()->UpdateOutputInformation();
238  }
239  ImageDataItemPointer volume = GetVolumeData(t, n);
240  return volume.GetPointer() == nullptr ? nullptr : volume->GetVtkImageAccessor(this)->GetVtkImageData();
241 }
242 
244  int s, int t, int n, void *data, ImportMemoryManagementType importMemoryManagement) const
245 {
247  return GetSliceData_unlocked(s, t, n, data, importMemoryManagement);
248 }
249 
250 mitk::Image::ImageDataItemPointer mitk::Image::GetSliceData_unlocked(
251  int s, int t, int n, void *data, ImportMemoryManagementType importMemoryManagement) const
252 {
253  if (IsValidSlice(s, t, n) == false)
254  return nullptr;
255 
256  const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize();
257 
258  // slice directly available?
259  int pos = GetSliceIndex(s, t, n);
260  if (m_Slices[pos].GetPointer() != nullptr)
261  {
262  return m_Slices[pos];
263  }
264 
265  // is slice available as part of a volume that is available?
266  ImageDataItemPointer sl, ch, vol;
267  vol = m_Volumes[GetVolumeIndex(t, n)];
268  if ((vol.GetPointer() != nullptr) && (vol->IsComplete()))
269  {
270  sl = new ImageDataItem(*vol,
272  t,
273  2,
274  data,
275  importMemoryManagement == ManageMemory,
276  ((size_t)s) * m_OffsetTable[2] * (ptypeSize));
277  sl->SetComplete(true);
278  return m_Slices[pos] = sl;
279  }
280 
281  // is slice available as part of a channel that is available?
282  ch = m_Channels[n];
283  if ((ch.GetPointer() != nullptr) && (ch->IsComplete()))
284  {
285  sl = new ImageDataItem(*ch,
287  t,
288  2,
289  data,
290  importMemoryManagement == ManageMemory,
291  (((size_t)s) * m_OffsetTable[2] + ((size_t)t) * m_OffsetTable[3]) * (ptypeSize));
292  sl->SetComplete(true);
293  return m_Slices[pos] = sl;
294  }
295 
296  // slice is unavailable. Can we calculate it?
297  if ((GetSource().IsNotNull()) && (GetSource()->Updating() == false))
298  {
299  // ... wir mussen rechnen!!! ....
300  m_RequestedRegion.SetIndex(0, 0);
301  m_RequestedRegion.SetIndex(1, 0);
302  m_RequestedRegion.SetIndex(2, s);
303  m_RequestedRegion.SetIndex(3, t);
304  m_RequestedRegion.SetIndex(4, n);
305  m_RequestedRegion.SetSize(0, m_Dimensions[0]);
306  m_RequestedRegion.SetSize(1, m_Dimensions[1]);
307  m_RequestedRegion.SetSize(2, 1);
308  m_RequestedRegion.SetSize(3, 1);
309  m_RequestedRegion.SetSize(4, 1);
311  GetSource()->Update();
312  if (IsSliceSet_unlocked(s, t, n))
313  // yes: now we can call ourselves without the risk of a endless loop (see "if" above)
314  return GetSliceData_unlocked(s, t, n, data, importMemoryManagement);
315  else
316  return nullptr;
317  }
318  else
319  {
320  ImageDataItemPointer item = AllocateSliceData_unlocked(s, t, n, data, importMemoryManagement);
321  item->SetComplete(true);
322  return item;
323  }
324 }
325 
327  int n,
328  void *data,
329  ImportMemoryManagementType importMemoryManagement) const
330 {
332  return GetVolumeData_unlocked(t, n, data, importMemoryManagement);
333 }
334 mitk::Image::ImageDataItemPointer mitk::Image::GetVolumeData_unlocked(
335  int t, int n, void *data, ImportMemoryManagementType importMemoryManagement) const
336 {
337  if (IsValidVolume(t, n) == false)
338  return nullptr;
339 
340  ImageDataItemPointer ch, vol;
341 
342  // volume directly available?
343  int pos = GetVolumeIndex(t, n);
344  vol = m_Volumes[pos];
345  if ((vol.GetPointer() != nullptr) && (vol->IsComplete()))
346  return vol;
347 
348  const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize();
349 
350  // is volume available as part of a channel that is available?
351  ch = m_Channels[n];
352  if ((ch.GetPointer() != nullptr) && (ch->IsComplete()))
353  {
354  vol = new ImageDataItem(*ch,
356  t,
357  3,
358  data,
359  importMemoryManagement == ManageMemory,
360  (((size_t)t) * m_OffsetTable[3]) * (ptypeSize));
361  vol->SetComplete(true);
362  return m_Volumes[pos] = vol;
363  }
364 
365  // let's see if all slices of the volume are set, so that we can (could) combine them to a volume
366  bool complete = true;
367  unsigned int s;
368  for (s = 0; s < m_Dimensions[2]; ++s)
369  {
370  if (m_Slices[GetSliceIndex(s, t, n)].GetPointer() == nullptr)
371  {
372  complete = false;
373  break;
374  }
375  }
376  if (complete)
377  {
378  // if there is only single slice we do not need to combine anything
379  if (m_Dimensions[2] <= 1)
380  {
382  sl = GetSliceData_unlocked(0, t, n, data, importMemoryManagement);
383  vol = new ImageDataItem(*sl, m_ImageDescriptor, t, 3, data, importMemoryManagement == ManageMemory);
384  vol->SetComplete(true);
385  }
386  else
387  {
388  mitk::PixelType chPixelType = this->m_ImageDescriptor->GetChannelTypeById(n);
389 
390  vol = m_Volumes[pos];
391  // ok, let's combine the slices!
392  if (vol.GetPointer() == nullptr)
393  {
394  vol = new ImageDataItem(chPixelType, t, 3, m_Dimensions, nullptr, true);
395  }
396  vol->SetComplete(true);
397  size_t size = m_OffsetTable[2] * (ptypeSize);
398  for (s = 0; s < m_Dimensions[2]; ++s)
399  {
400  int posSl;
402  posSl = GetSliceIndex(s, t, n);
403 
404  sl = m_Slices[posSl];
405  if (sl->GetParent() != vol)
406  {
407  // copy data of slices in volume
408  size_t offset = ((size_t)s) * size;
409  std::memcpy(static_cast<char *>(vol->GetData()) + offset, sl->GetData(), size);
410 
411  // FIXME mitkIpPicDescriptor * pic = sl->GetPicDescriptor();
412 
413  // replace old slice with reference to volume
414  sl = new ImageDataItem(
415  *vol, m_ImageDescriptor, t, 2, data, importMemoryManagement == ManageMemory, ((size_t)s) * size);
416  sl->SetComplete(true);
417  // mitkIpFuncCopyTags(sl->GetPicDescriptor(), pic);
418  m_Slices[posSl] = sl;
419  }
420  }
421  // if(vol->GetPicDescriptor()->info->tags_head==nullptr)
422  // mitkIpFuncCopyTags(vol->GetPicDescriptor(), m_Slices[GetSliceIndex(0,t,n)]->GetPicDescriptor());
423  }
424  return m_Volumes[pos] = vol;
425  }
426 
427  // volume is unavailable. Can we calculate it?
428  if ((GetSource().IsNotNull()) && (GetSource()->Updating() == false))
429  {
430  // ... wir muessen rechnen!!! ....
431  m_RequestedRegion.SetIndex(0, 0);
432  m_RequestedRegion.SetIndex(1, 0);
433  m_RequestedRegion.SetIndex(2, 0);
434  m_RequestedRegion.SetIndex(3, t);
435  m_RequestedRegion.SetIndex(4, n);
436  m_RequestedRegion.SetSize(0, m_Dimensions[0]);
437  m_RequestedRegion.SetSize(1, m_Dimensions[1]);
438  m_RequestedRegion.SetSize(2, m_Dimensions[2]);
439  m_RequestedRegion.SetSize(3, 1);
440  m_RequestedRegion.SetSize(4, 1);
442  GetSource()->Update();
443  if (IsVolumeSet_unlocked(t, n))
444  // yes: now we can call ourselves without the risk of a endless loop (see "if" above)
445  return GetVolumeData_unlocked(t, n, data, importMemoryManagement);
446  else
447  return nullptr;
448  }
449  else
450  {
451  ImageDataItemPointer item = AllocateVolumeData_unlocked(t, n, data, importMemoryManagement);
452  item->SetComplete(true);
453  return item;
454  }
455 }
456 
458  void *data,
459  ImportMemoryManagementType importMemoryManagement) const
460 {
462  return GetChannelData_unlocked(n, data, importMemoryManagement);
463 }
464 
465 mitk::Image::ImageDataItemPointer mitk::Image::GetChannelData_unlocked(
466  int n, void *data, ImportMemoryManagementType importMemoryManagement) const
467 {
468  if (IsValidChannel(n) == false)
469  return nullptr;
470  ImageDataItemPointer ch, vol;
471  ch = m_Channels[n];
472  if ((ch.GetPointer() != nullptr) && (ch->IsComplete()))
473  return ch;
474 
475  // let's see if all volumes are set, so that we can (could) combine them to a channel
476  if (IsChannelSet_unlocked(n))
477  {
478  // if there is only one time frame we do not need to combine anything
479  if (m_Dimensions[3] <= 1)
480  {
481  vol = GetVolumeData_unlocked(0, n, data, importMemoryManagement);
482  ch = new ImageDataItem(*vol,
484  0,
485  m_ImageDescriptor->GetNumberOfDimensions(),
486  data,
487  importMemoryManagement == ManageMemory);
488  ch->SetComplete(true);
489  }
490  else
491  {
492  const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize();
493 
494  ch = m_Channels[n];
495  // ok, let's combine the volumes!
496  if (ch.GetPointer() == nullptr)
497  ch = new ImageDataItem(this->m_ImageDescriptor, -1, nullptr, true);
498  ch->SetComplete(true);
499  size_t size = m_OffsetTable[m_Dimension - 1] * (ptypeSize);
500  unsigned int t;
501  auto slicesIt = m_Slices.begin() + n * m_Dimensions[2] * m_Dimensions[3];
502  for (t = 0; t < m_Dimensions[3]; ++t)
503  {
504  int posVol;
506 
507  posVol = GetVolumeIndex(t, n);
508  vol = GetVolumeData_unlocked(t, n, data, importMemoryManagement);
509 
510  if (vol->GetParent() != ch)
511  {
512  // copy data of volume in channel
513  size_t offset = ((size_t)t) * m_OffsetTable[3] * (ptypeSize);
514  std::memcpy(static_cast<char *>(ch->GetData()) + offset, vol->GetData(), size);
515 
516  // REVEIW FIX mitkIpPicDescriptor * pic = vol->GetPicDescriptor();
517 
518  // replace old volume with reference to channel
519  vol = new ImageDataItem(*ch, m_ImageDescriptor, t, 3, data, importMemoryManagement == ManageMemory, offset);
520  vol->SetComplete(true);
521  // mitkIpFuncCopyTags(vol->GetPicDescriptor(), pic);
522 
523  m_Volumes[posVol] = vol;
524 
525  // get rid of slices - they may point to old volume
526  ImageDataItemPointer dnull = nullptr;
527  for (unsigned int i = 0; i < m_Dimensions[2]; ++i, ++slicesIt)
528  {
529  assert(slicesIt != m_Slices.end());
530  *slicesIt = dnull;
531  }
532  }
533  }
534  // REVIEW FIX
535  // if(ch->GetPicDescriptor()->info->tags_head==nullptr)
536  // mitkIpFuncCopyTags(ch->GetPicDescriptor(), m_Volumes[GetVolumeIndex(0,n)]->GetPicDescriptor());
537  }
538  return m_Channels[n] = ch;
539  }
540 
541  // channel is unavailable. Can we calculate it?
542  if ((GetSource().IsNotNull()) && (GetSource()->Updating() == false))
543  {
544  // ... wir muessen rechnen!!! ....
545  m_RequestedRegion.SetIndex(0, 0);
546  m_RequestedRegion.SetIndex(1, 0);
547  m_RequestedRegion.SetIndex(2, 0);
548  m_RequestedRegion.SetIndex(3, 0);
549  m_RequestedRegion.SetIndex(4, n);
550  m_RequestedRegion.SetSize(0, m_Dimensions[0]);
551  m_RequestedRegion.SetSize(1, m_Dimensions[1]);
552  m_RequestedRegion.SetSize(2, m_Dimensions[2]);
553  m_RequestedRegion.SetSize(3, m_Dimensions[3]);
554  m_RequestedRegion.SetSize(4, 1);
556  GetSource()->Update();
557  // did it work?
558  if (IsChannelSet_unlocked(n))
559  // yes: now we can call ourselves without the risk of a endless loop (see "if" above)
560  return GetChannelData_unlocked(n, data, importMemoryManagement);
561  else
562  return nullptr;
563  }
564  else
565  {
566  ImageDataItemPointer item = AllocateChannelData_unlocked(n, data, importMemoryManagement);
567  item->SetComplete(true);
568  return item;
569  }
570 }
571 
572 bool mitk::Image::IsSliceSet(int s, int t, int n) const
573 {
575  return IsSliceSet_unlocked(s, t, n);
576 }
577 
578 bool mitk::Image::IsSliceSet_unlocked(int s, int t, int n) const
579 {
580  if (IsValidSlice(s, t, n) == false)
581  return false;
582 
583  if (m_Slices[GetSliceIndex(s, t, n)].GetPointer() != nullptr)
584  {
585  return true;
586  }
587 
588  ImageDataItemPointer ch, vol;
589  vol = m_Volumes[GetVolumeIndex(t, n)];
590  if ((vol.GetPointer() != nullptr) && (vol->IsComplete()))
591  {
592  return true;
593  }
594  ch = m_Channels[n];
595  if ((ch.GetPointer() != nullptr) && (ch->IsComplete()))
596  {
597  return true;
598  }
599  return false;
600 }
601 
602 bool mitk::Image::IsVolumeSet(int t, int n) const
603 {
605  return IsVolumeSet_unlocked(t, n);
606 }
607 
608 bool mitk::Image::IsVolumeSet_unlocked(int t, int n) const
609 {
610  if (IsValidVolume(t, n) == false)
611  return false;
612  ImageDataItemPointer ch, vol;
613 
614  // volume directly available?
615  vol = m_Volumes[GetVolumeIndex(t, n)];
616  if ((vol.GetPointer() != nullptr) && (vol->IsComplete()))
617  return true;
618 
619  // is volume available as part of a channel that is available?
620  ch = m_Channels[n];
621  if ((ch.GetPointer() != nullptr) && (ch->IsComplete()))
622  return true;
623 
624  // let's see if all slices of the volume are set, so that we can (could) combine them to a volume
625  unsigned int s;
626  for (s = 0; s < m_Dimensions[2]; ++s)
627  {
628  if (m_Slices[GetSliceIndex(s, t, n)].GetPointer() == nullptr)
629  {
630  return false;
631  }
632  }
633  return true;
634 }
635 
636 bool mitk::Image::IsChannelSet(int n) const
637 {
639  return IsChannelSet_unlocked(n);
640 }
641 
642 bool mitk::Image::IsChannelSet_unlocked(int n) const
643 {
644  if (IsValidChannel(n) == false)
645  return false;
646  ImageDataItemPointer ch, vol;
647  ch = m_Channels[n];
648  if ((ch.GetPointer() != nullptr) && (ch->IsComplete()))
649 
650  return true;
651  // let's see if all volumes are set, so that we can (could) combine them to a channel
652  unsigned int t;
653  for (t = 0; t < m_Dimensions[3]; ++t)
654  {
655  if (IsVolumeSet_unlocked(t, n) == false)
656  {
657  return false;
658  }
659  }
660  return true;
661 }
662 
663 bool mitk::Image::SetSlice(const void *data, int s, int t, int n)
664 {
665  // const_cast is no risk for ImportMemoryManagementType == CopyMemory
666  return SetImportSlice(const_cast<void *>(data), s, t, n, CopyMemory);
667 }
668 
669 bool mitk::Image::SetVolume(const void *data, int t, int n)
670 {
671  // const_cast is no risk for ImportMemoryManagementType == CopyMemory
672  return SetImportVolume(const_cast<void *>(data), t, n, CopyMemory);
673 }
674 
675 bool mitk::Image::SetChannel(const void *data, int n)
676 {
677  // const_cast is no risk for ImportMemoryManagementType == CopyMemory
678  return SetImportChannel(const_cast<void *>(data), n, CopyMemory);
679 }
680 
681 bool mitk::Image::SetImportSlice(void *data, int s, int t, int n, ImportMemoryManagementType importMemoryManagement)
682 {
683  if (IsValidSlice(s, t, n) == false)
684  return false;
686  const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize();
687 
688  if (IsSliceSet(s, t, n))
689  {
690  sl = GetSliceData(s, t, n, data, importMemoryManagement);
691  if (sl->GetManageMemory() == false)
692  {
693  sl = AllocateSliceData(s, t, n, data, importMemoryManagement);
694  if (sl.GetPointer() == nullptr)
695  return false;
696  }
697  if (sl->GetData() != data)
698  std::memcpy(sl->GetData(), data, m_OffsetTable[2] * (ptypeSize));
699  sl->Modified();
700  // we have changed the data: call Modified()!
701  Modified();
702  }
703  else
704  {
705  sl = AllocateSliceData(s, t, n, data, importMemoryManagement);
706  if (sl.GetPointer() == nullptr)
707  return false;
708  if (sl->GetData() != data)
709  std::memcpy(sl->GetData(), data, m_OffsetTable[2] * (ptypeSize));
710  // we just added a missing slice, which is not regarded as modification.
711  // Therefore, we do not call Modified()!
712  }
713  return true;
714 }
715 
716 bool mitk::Image::SetImportVolume(void *data, int t, int n, ImportMemoryManagementType importMemoryManagement)
717 {
718  if (IsValidVolume(t, n) == false)
719  return false;
720 
721  const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize();
723  if (IsVolumeSet(t, n))
724  {
725  vol = GetVolumeData(t, n, data, importMemoryManagement);
726  if (vol->GetManageMemory() == false)
727  {
728  vol = AllocateVolumeData(t, n, data, importMemoryManagement);
729  if (vol.GetPointer() == nullptr)
730  return false;
731  }
732  if (vol->GetData() != data)
733  std::memcpy(vol->GetData(), data, m_OffsetTable[3] * (ptypeSize));
734  vol->Modified();
735  vol->SetComplete(true);
736  // we have changed the data: call Modified()!
737  Modified();
738  }
739  else
740  {
741  vol = AllocateVolumeData(t, n, data, importMemoryManagement);
742  if (vol.GetPointer() == nullptr)
743  return false;
744  if (vol->GetData() != data)
745  {
746  std::memcpy(vol->GetData(), data, m_OffsetTable[3] * (ptypeSize));
747  }
748  vol->SetComplete(true);
749  this->m_ImageDescriptor->GetChannelDescriptor(n).SetData(vol->GetData());
750  // we just added a missing Volume, which is not regarded as modification.
751  // Therefore, we do not call Modified()!
752  }
753  return true;
754 }
755 
756 bool mitk::Image::SetImportVolume(const void *const_data, int t, int n)
757 {
758  return this->SetImportVolume(const_cast<void*>(const_data), t, n, CopyMemory);
759 }
760 
761 bool mitk::Image::SetImportChannel(void *data, int n, ImportMemoryManagementType importMemoryManagement)
762 {
763  if (IsValidChannel(n) == false)
764  return false;
765 
766  // channel descriptor
767 
768  const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize();
769 
771  if (IsChannelSet(n))
772  {
773  ch = GetChannelData(n, data, importMemoryManagement);
774  if (ch->GetManageMemory() == false)
775  {
776  ch = AllocateChannelData(n, data, importMemoryManagement);
777  if (ch.GetPointer() == nullptr)
778  return false;
779  }
780  if (ch->GetData() != data)
781  std::memcpy(ch->GetData(), data, m_OffsetTable[4] * (ptypeSize));
782  ch->Modified();
783  ch->SetComplete(true);
784  // we have changed the data: call Modified()!
785  Modified();
786  }
787  else
788  {
789  ch = AllocateChannelData(n, data, importMemoryManagement);
790  if (ch.GetPointer() == nullptr)
791  return false;
792  if (ch->GetData() != data)
793  std::memcpy(ch->GetData(), data, m_OffsetTable[4] * (ptypeSize));
794  ch->SetComplete(true);
795 
796  this->m_ImageDescriptor->GetChannelDescriptor(n).SetData(ch->GetData());
797  // we just added a missing Channel, which is not regarded as modification.
798  // Therefore, we do not call Modified()!
799  }
800  return true;
801 }
802 
804 {
805  ImageDataItemPointerArray::iterator it, end;
806  for (it = m_Slices.begin(), end = m_Slices.end(); it != end; ++it)
807  {
808  (*it) = nullptr;
809  }
810  for (it = m_Volumes.begin(), end = m_Volumes.end(); it != end; ++it)
811  {
812  (*it) = nullptr;
813  }
814  for (it = m_Channels.begin(), end = m_Channels.end(); it != end; ++it)
815  {
816  (*it) = nullptr;
817  }
818  m_CompleteData = nullptr;
819 
820  if (m_ImageStatistics == nullptr)
821  {
823  }
824 
826 }
827 
829 {
830  // store the descriptor
831  this->m_ImageDescriptor = inDesc;
832 
833  // initialize image
834  this->Initialize(
835  inDesc->GetChannelDescriptor(0).GetPixelType(), inDesc->GetNumberOfDimensions(), inDesc->GetDimensions(), 1);
836 }
837 
839  unsigned int dimension,
840  const unsigned int *dimensions,
841  unsigned int channels)
842 {
843  Clear();
844 
845  m_Dimension = dimension;
846 
847  if (!dimensions)
848  itkExceptionMacro(<< "invalid zero dimension image");
849 
850  unsigned int i;
851  for (i = 0; i < dimension; ++i)
852  {
853  if (dimensions[i] < 1)
854  itkExceptionMacro(<< "invalid dimension[" << i << "]: " << dimensions[i]);
855  }
856 
857  // create new array since the old was deleted
858  m_Dimensions = new unsigned int[MAX_IMAGE_DIMENSIONS];
859 
860  // initialize the first four dimensions to 1, the remaining 4 to 0
861  FILL_C_ARRAY(m_Dimensions, 4, 1u);
862  FILL_C_ARRAY((m_Dimensions + 4), 4, 0u);
863 
864  // copy in the passed dimension information
865  std::memcpy(m_Dimensions, dimensions, sizeof(unsigned int) * m_Dimension);
866 
868  this->m_ImageDescriptor->Initialize(this->m_Dimensions, this->m_Dimension);
869 
870  for (i = 0; i < 4; ++i)
871  {
872  m_LargestPossibleRegion.SetIndex(i, 0);
873  m_LargestPossibleRegion.SetSize(i, m_Dimensions[i]);
874  }
875  m_LargestPossibleRegion.SetIndex(i, 0);
876  m_LargestPossibleRegion.SetSize(i, channels);
877 
878  if (m_LargestPossibleRegion.GetNumberOfPixels() == 0)
879  {
880  delete[] m_Dimensions;
881  m_Dimensions = nullptr;
882  return;
883  }
884 
885  for (unsigned int i = 0u; i < channels; i++)
886  {
887  this->m_ImageDescriptor->AddNewChannel(type);
888  }
889 
890  PlaneGeometry::Pointer planegeometry = PlaneGeometry::New();
891  planegeometry->InitializeStandardPlane(m_Dimensions[0], m_Dimensions[1]);
892 
894  slicedGeometry->InitializeEvenlySpaced(planegeometry, m_Dimensions[2]);
895 
897  timeGeometry->Initialize(slicedGeometry, m_Dimensions[3]);
898  for (TimeStepType step = 0; step < timeGeometry->CountTimeSteps(); ++step)
899  {
900  timeGeometry->GetGeometryForTimeStep(step)->ImageGeometryOn();
901  }
902  SetTimeGeometry(timeGeometry);
903 
904  ImageDataItemPointer dnull = nullptr;
905 
906  m_Channels.assign(GetNumberOfChannels(), dnull);
907 
908  m_Volumes.assign(GetNumberOfChannels() * m_Dimensions[3], dnull);
909 
910  m_Slices.assign(GetNumberOfChannels() * m_Dimensions[3] * m_Dimensions[2], dnull);
911 
913 
914  Initialize();
915 
916  m_Initialized = true;
917 }
918 
920  const mitk::BaseGeometry &geometry,
921  unsigned int channels,
922  int tDim)
923 {
925  timeGeometry->Initialize(geometry.Clone(), tDim);
926  this->Initialize(type, *timeGeometry, channels, tDim);
927 }
928 
930  const mitk::TimeGeometry &geometry,
931  unsigned int channels,
932  int tDim)
933 {
934  unsigned int dimensions[5];
935  dimensions[0] = (unsigned int)(geometry.GetGeometryForTimeStep(0)->GetExtent(0) + 0.5);
936  dimensions[1] = (unsigned int)(geometry.GetGeometryForTimeStep(0)->GetExtent(1) + 0.5);
937  dimensions[2] = (unsigned int)(geometry.GetGeometryForTimeStep(0)->GetExtent(2) + 0.5);
938  dimensions[3] = (tDim > 0) ? tDim : geometry.CountTimeSteps();
939  dimensions[4] = 0;
940 
941  unsigned int dimension = 2;
942  if (dimensions[2] > 1)
943  dimension = 3;
944  if (dimensions[3] > 1)
945  dimension = 4;
946 
947  Initialize(type, dimension, dimensions, channels);
948  if (geometry.CountTimeSteps() > 1)
949  {
950  TimeGeometry::Pointer cloned = geometry.Clone();
951  SetTimeGeometry(cloned.GetPointer());
952 
953  // make sure the image geometry flag is properly set for all time steps
954  for (TimeStepType step = 0; step < cloned->CountTimeSteps(); ++step)
955  {
956  if (!cloned->GetGeometryCloneForTimeStep(step)->GetImageGeometry())
957  {
958  MITK_WARN("Image.3DnT.Initialize") << " Attempt to initialize an image with a non-image geometry. "
959  "Re-interpretting the initialization geometry for timestep "
960  << step << " as image geometry, the original geometry remains unchanged.";
961  cloned->GetGeometryForTimeStep(step)->ImageGeometryOn();
962  }
963  }
964  }
965  else
966  {
967  // make sure the image geometry coming from outside has proper value of the image geometry flag
968  BaseGeometry::Pointer cloned = geometry.GetGeometryCloneForTimeStep(0)->Clone();
969  if (!cloned->GetImageGeometry())
970  {
971  MITK_WARN("Image.Initialize") << " Attempt to initialize an image with a non-image geometry. Re-interpretting "
972  "the initialization geometry as image geometry, the original geometry remains "
973  "unchanged.";
974  cloned->ImageGeometryOn();
975  }
976 
977  Superclass::SetGeometry(cloned);
978  }
979  /* //Old //TODO_GOETZ Really necessary?
980  mitk::BoundingBox::BoundsArrayType bounds = geometry.GetBoundingBoxInWorld()->GetBounds();
981  if( (bounds[0] != 0.0) || (bounds[2] != 0.0) || (bounds[4] != 0.0) )
982  {
983  SlicedGeometry3D* slicedGeometry = GetSlicedGeometry(0);
984 
985  mitk::Point3D origin; origin.Fill(0.0);
986  slicedGeometry->IndexToWorld(origin, origin);
987 
988  bounds[1]-=bounds[0]; bounds[3]-=bounds[2]; bounds[5]-=bounds[4];
989  bounds[0] = 0.0; bounds[2] = 0.0; bounds[4] = 0.0;
990  this->m_ImageDescriptor->Initialize( this->m_Dimensions, this->m_Dimension );
991  slicedGeometry->SetBounds(bounds);
992  slicedGeometry->GetIndexToWorldTransform()->SetOffset(origin.GetVnlVector().data_block());
993 
994  ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New();
995  timeGeometry->Initialize(slicedGeometry, m_Dimensions[3]);
996  SetTimeGeometry(timeGeometry);
997  }*/
998 }
999 
1001  int,
1002  const mitk::PlaneGeometry &,
1003  bool,
1004  unsigned int,
1005  int)
1006 {
1007  mitkThrow() << "Use this method without the flipped parameter (direction is specified by the handedness of the PlaneGeometry instead).";
1008 }
1009 
1011  int sDim,
1012  const mitk::PlaneGeometry &geometry2d,
1013  unsigned int channels,
1014  int tDim)
1015 {
1017  slicedGeometry->InitializeEvenlySpaced(geometry2d.Clone(), sDim);
1018  Initialize(type, *slicedGeometry, channels, tDim);
1019 }
1020 
1022 {
1023  Initialize(image->GetPixelType(), *image->GetTimeGeometry());
1024 }
1025 
1026 void mitk::Image::Initialize(vtkImageData *vtkimagedata, int channels, int tDim, int sDim, int pDim)
1027 {
1028  if (vtkimagedata == nullptr)
1029  return;
1030 
1031  m_Dimension = vtkimagedata->GetDataDimension();
1032  unsigned int i, *tmpDimensions = new unsigned int[m_Dimension > 4 ? m_Dimension : 4];
1033  for (i = 0; i < m_Dimension; ++i)
1034  tmpDimensions[i] = vtkimagedata->GetDimensions()[i];
1035  if (m_Dimension < 4)
1036  {
1037  unsigned int *p;
1038  for (i = 0, p = tmpDimensions + m_Dimension; i < 4 - m_Dimension; ++i, ++p)
1039  *p = 1;
1040  }
1041 
1042  if (pDim >= 0)
1043  {
1044  tmpDimensions[1] = pDim;
1045  if (m_Dimension < 2)
1046  m_Dimension = 2;
1047  }
1048  if (sDim >= 0)
1049  {
1050  tmpDimensions[2] = sDim;
1051  if (m_Dimension < 3)
1052  m_Dimension = 3;
1053  }
1054  if (tDim >= 0)
1055  {
1056  tmpDimensions[3] = tDim;
1057  if (m_Dimension < 4)
1058  m_Dimension = 4;
1059  }
1060 
1061  mitk::PixelType pixelType(MakePixelType(vtkimagedata));
1062  Initialize(pixelType, m_Dimension, tmpDimensions, channels);
1063 
1064  const double *spacinglist = vtkimagedata->GetSpacing();
1065  Vector3D spacing;
1066  FillVector3D(spacing, spacinglist[0], 1.0, 1.0);
1067  if (m_Dimension >= 2)
1068  spacing[1] = spacinglist[1];
1069  if (m_Dimension >= 3)
1070  spacing[2] = spacinglist[2];
1071 
1072  // access origin of vtkImage
1073  Point3D origin;
1074  double vtkorigin[3];
1075  vtkimagedata->GetOrigin(vtkorigin);
1076  FillVector3D(origin, vtkorigin[0], 0.0, 0.0);
1077  if (m_Dimension >= 2)
1078  origin[1] = vtkorigin[1];
1079  if (m_Dimension >= 3)
1080  origin[2] = vtkorigin[2];
1081 
1082  SlicedGeometry3D *slicedGeometry = GetSlicedGeometry(0);
1083 
1084  // re-initialize PlaneGeometry with origin and direction
1085  auto *planeGeometry = static_cast<PlaneGeometry *>(slicedGeometry->GetPlaneGeometry(0));
1086  planeGeometry->SetOrigin(origin);
1087 
1088  // re-initialize SlicedGeometry3D
1089  slicedGeometry->SetOrigin(origin);
1090  slicedGeometry->SetSpacing(spacing);
1091 
1093  timeGeometry->Initialize(slicedGeometry, m_Dimensions[3]);
1094  SetTimeGeometry(timeGeometry);
1095 
1096  delete[] tmpDimensions;
1097 }
1098 
1099 bool mitk::Image::IsValidSlice(int s, int t, int n) const
1100 {
1101  if (m_Initialized)
1102  return ((s >= 0) && (s < (int)m_Dimensions[2]) && (t >= 0) && (t < (int)m_Dimensions[3]) && (n >= 0) &&
1103  (n < (int)GetNumberOfChannels()));
1104  else
1105  return false;
1106 }
1107 
1108 bool mitk::Image::IsValidVolume(int t, int n) const
1109 {
1110  if (m_Initialized)
1111  return IsValidSlice(0, t, n);
1112  else
1113  return false;
1114 }
1115 
1117 {
1118  if (m_Initialized)
1119  return IsValidSlice(0, 0, n);
1120  else
1121  return false;
1122 }
1123 
1125 {
1126  if (m_OffsetTable != nullptr)
1127  delete[] m_OffsetTable;
1128 
1129  m_OffsetTable = new size_t[m_Dimension > 4 ? m_Dimension + 1 : 4 + 1];
1130 
1131  unsigned int i;
1132  size_t num = 1;
1133  m_OffsetTable[0] = 1;
1134  for (i = 0; i < m_Dimension; ++i)
1135  {
1136  num *= m_Dimensions[i];
1137  m_OffsetTable[i + 1] = num;
1138  }
1139  for (; i < 4; ++i)
1140  m_OffsetTable[i + 1] = num;
1141 }
1142 
1144 {
1145  return ((m_Dimension >= 4 && t <= (int)m_Dimensions[3] && t > 0) || (t == 0));
1146 }
1147 
1148 void mitk::Image::Expand(unsigned int timeSteps)
1149 {
1150  if (timeSteps < 1)
1151  itkExceptionMacro(<< "Invalid timestep in Image!");
1152  Superclass::Expand(timeSteps);
1153 }
1154 
1155 int mitk::Image::GetSliceIndex(int s, int t, int n) const
1156 {
1157  if (IsValidSlice(s, t, n) == false)
1158  return false;
1159  return ((size_t)s) + ((size_t)t) * m_Dimensions[2] + ((size_t)n) * m_Dimensions[3] * m_Dimensions[2]; //??
1160 }
1161 
1162 int mitk::Image::GetVolumeIndex(int t, int n) const
1163 {
1164  if (IsValidVolume(t, n) == false)
1165  return false;
1166  return ((size_t)t) + ((size_t)n) * m_Dimensions[3]; //??
1167 }
1168 
1170  int s, int t, int n, void *data, ImportMemoryManagementType importMemoryManagement) const
1171 {
1173  return AllocateSliceData_unlocked(s, t, n, data, importMemoryManagement);
1174 }
1175 
1176 mitk::Image::ImageDataItemPointer mitk::Image::AllocateSliceData_unlocked(
1177  int s, int t, int n, void *data, ImportMemoryManagementType importMemoryManagement) const
1178 {
1179  int pos;
1180  pos = GetSliceIndex(s, t, n);
1181 
1182  const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize();
1183 
1184  // is slice available as part of a volume that is available?
1185  ImageDataItemPointer sl, ch, vol;
1186  vol = m_Volumes[GetVolumeIndex(t, n)];
1187  if (vol.GetPointer() != nullptr)
1188  {
1189  sl = new ImageDataItem(*vol,
1191  t,
1192  2,
1193  data,
1194  importMemoryManagement == ManageMemory,
1195  ((size_t)s) * m_OffsetTable[2] * (ptypeSize));
1196  sl->SetComplete(true);
1197  return m_Slices[pos] = sl;
1198  }
1199 
1200  // is slice available as part of a channel that is available?
1201  ch = m_Channels[n];
1202  if (ch.GetPointer() != nullptr)
1203  {
1204  sl = new ImageDataItem(*ch,
1206  t,
1207  2,
1208  data,
1209  importMemoryManagement == ManageMemory,
1210  (((size_t)s) * m_OffsetTable[2] + ((size_t)t) * m_OffsetTable[3]) * (ptypeSize));
1211  sl->SetComplete(true);
1212  return m_Slices[pos] = sl;
1213  }
1214 
1215  // allocate new volume (instead of a single slice to keep data together!)
1216  m_Volumes[GetVolumeIndex(t, n)] = vol = AllocateVolumeData_unlocked(t, n, nullptr, importMemoryManagement);
1217  sl = new ImageDataItem(*vol,
1219  t,
1220  2,
1221  data,
1222  importMemoryManagement == ManageMemory,
1223  ((size_t)s) * m_OffsetTable[2] * (ptypeSize));
1224  sl->SetComplete(true);
1225  return m_Slices[pos] = sl;
1226 
1229  // sl=new ImageDataItem(*m_PixelType, 2, m_Dimensions);
1230  // m_Slices[pos]=sl;
1231  // return vol;
1232 }
1233 
1235  int t, int n, void *data, ImportMemoryManagementType importMemoryManagement) const
1236 {
1238  return AllocateVolumeData_unlocked(t, n, data, importMemoryManagement);
1239 }
1240 
1241 mitk::Image::ImageDataItemPointer mitk::Image::AllocateVolumeData_unlocked(
1242  int t, int n, void *data, ImportMemoryManagementType importMemoryManagement) const
1243 {
1244  int pos;
1245  pos = GetVolumeIndex(t, n);
1246 
1247  const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize();
1248 
1249  // is volume available as part of a channel that is available?
1250  ImageDataItemPointer ch, vol;
1251  ch = m_Channels[n];
1252  if (ch.GetPointer() != nullptr)
1253  {
1254  vol = new ImageDataItem(*ch,
1256  t,
1257  3,
1258  data,
1259  importMemoryManagement == ManageMemory,
1260  (((size_t)t) * m_OffsetTable[3]) * (ptypeSize));
1261  return m_Volumes[pos] = vol;
1262  }
1263 
1264  mitk::PixelType chPixelType = this->m_ImageDescriptor->GetChannelTypeById(n);
1265 
1266  // allocate new volume
1267  if (importMemoryManagement == CopyMemory)
1268  {
1269  vol = new ImageDataItem(chPixelType, t, 3, m_Dimensions, nullptr, true);
1270  if (data != nullptr)
1271  std::memcpy(vol->GetData(), data, m_OffsetTable[3] * (ptypeSize));
1272  }
1273  else
1274  {
1275  vol = new ImageDataItem(chPixelType, t, 3, m_Dimensions, data, importMemoryManagement == ManageMemory);
1276  }
1277  m_Volumes[pos] = vol;
1278  return vol;
1279 }
1280 
1282  int n, void *data, ImportMemoryManagementType importMemoryManagement) const
1283 {
1285  return AllocateChannelData_unlocked(n, data, importMemoryManagement);
1286 }
1287 
1288 mitk::Image::ImageDataItemPointer mitk::Image::AllocateChannelData_unlocked(
1289  int n, void *data, ImportMemoryManagementType importMemoryManagement) const
1290 {
1292  // allocate new channel
1293  if (importMemoryManagement == CopyMemory)
1294  {
1295  const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize();
1296 
1297  ch = new ImageDataItem(this->m_ImageDescriptor, -1, nullptr, true);
1298  if (data != nullptr)
1299  std::memcpy(ch->GetData(), data, m_OffsetTable[4] * (ptypeSize));
1300  }
1301  else
1302  {
1303  ch = new ImageDataItem(this->m_ImageDescriptor, -1, data, importMemoryManagement == ManageMemory);
1304  }
1305  m_Channels[n] = ch;
1306  return ch;
1307 }
1308 
1309 unsigned int *mitk::Image::GetDimensions() const
1310 {
1311  return m_Dimensions;
1312 }
1313 
1315 {
1317  delete[] m_Dimensions;
1318  m_Dimensions = nullptr;
1319 }
1320 
1322 {
1323  // Please be aware of the 0.5 offset/pixel-center issue! See Geometry documentation for further information
1324 
1325  if (aGeometry3D->GetImageGeometry() == false)
1326  {
1327  MITK_INFO << "WARNING: Applied a non-image geometry onto an image. Please be SURE that this geometry is "
1328  "pixel-center-based! If it is not, you need to call "
1329  "Geometry3D->ChangeImageGeometryConsideringOriginOffset(true) before calling image->setGeometry(..)\n";
1330  }
1331  Superclass::SetGeometry(aGeometry3D);
1332  for (TimeStepType step = 0; step < GetTimeGeometry()->CountTimeSteps(); ++step)
1333  GetTimeGeometry()->GetGeometryForTimeStep(step)->ImageGeometryOn();
1334 }
1335 
1336 void mitk::Image::PrintSelf(std::ostream &os, itk::Indent indent) const
1337 {
1338  if (m_Initialized)
1339  {
1340  unsigned char i;
1341  os << indent << " Dimension: " << m_Dimension << std::endl;
1342  os << indent << " Dimensions: ";
1343  for (i = 0; i < m_Dimension; ++i)
1344  os << GetDimension(i) << " ";
1345  os << std::endl;
1346 
1347  for (unsigned int ch = 0; ch < this->m_ImageDescriptor->GetNumberOfChannels(); ch++)
1348  {
1349  mitk::PixelType chPixelType = this->m_ImageDescriptor->GetChannelTypeById(ch);
1350 
1351  os << indent << " Channel: " << this->m_ImageDescriptor->GetChannelName(ch) << std::endl;
1352  os << indent << " PixelType: " << chPixelType.GetPixelTypeAsString() << std::endl;
1353  os << indent << " BytesPerElement: " << chPixelType.GetSize() << std::endl;
1354  os << indent << " ComponentType: " << chPixelType.GetComponentTypeAsString() << std::endl;
1355  os << indent << " NumberOfComponents: " << chPixelType.GetNumberOfComponents() << std::endl;
1356  os << indent << " BitsPerComponent: " << chPixelType.GetBitsPerComponent() << std::endl;
1357  }
1358  }
1359  else
1360  {
1361  os << indent << " Image not initialized: m_Initialized: false" << std::endl;
1362  }
1363 
1364  Superclass::PrintSelf(os, indent);
1365 }
1366 
1368 {
1369  const mitk::BaseGeometry *geo = this->GetGeometry();
1370  bool ret = false;
1371 
1372  if (geo)
1373  {
1374  const vnl_matrix_fixed<ScalarType, 3, 3> &mx = geo->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix();
1375  mitk::ScalarType ref = 0;
1376  for (short k = 0; k < 3; ++k)
1377  ref += mx[k][k];
1378  ref /= 1000; // Arbitrary value; if a non-diagonal (nd) element is bigger then this, matrix is considered nd.
1379 
1380  for (short i = 0; i < 3; ++i)
1381  {
1382  for (short j = 0; j < 3; ++j)
1383  {
1384  if (i != j)
1385  {
1386  if (std::abs(mx[i][j]) > ref) // matrix is nd
1387  ret = true;
1388  }
1389  }
1390  }
1391  }
1392  return ret;
1393 }
1394 
1396 {
1398 }
1399 
1400 //## \brief Get the maximum for scalar images
1402 {
1404 }
1405 
1406 //## \brief Get the second smallest value for scalar images
1408 {
1410 }
1411 
1413 {
1415 }
1416 
1418 {
1420 }
1421 
1423 {
1425 }
1426 
1428 {
1430 }
1431 
1433 {
1435 }
1436 
1438 {
1440 }
1441 
1443 {
1445 }
1446 
1447 unsigned int mitk::Image::GetCountOfMaxValuedVoxelsNoRecompute(unsigned int t) const
1448 {
1450 }
1451 
1452 unsigned int mitk::Image::GetCountOfMinValuedVoxelsNoRecompute(unsigned int t) const
1453 {
1455 }
1456 
1457 bool mitk::Equal(const mitk::Image *leftHandSide, const mitk::Image *rightHandSide, ScalarType eps, bool verbose)
1458 {
1459  if ((leftHandSide == nullptr) || (rightHandSide == nullptr))
1460  {
1461  MITK_ERROR << "mitk::Equal(const mitk::Image* leftHandSide, const mitk::Image* rightHandSide, ScalarType eps, bool "
1462  "verbose) does not work with nullptr pointer input.";
1463  return false;
1464  }
1465  return mitk::Equal(*leftHandSide, *rightHandSide, eps, verbose);
1466 }
1467 
1468 bool mitk::Equal(const mitk::Image &leftHandSide, const mitk::Image &rightHandSide, ScalarType eps, bool verbose)
1469 {
1470  bool returnValue = true;
1471 
1472  // Dimensionality
1473  if (rightHandSide.GetDimension() != leftHandSide.GetDimension())
1474  {
1475  if (verbose)
1476  {
1477  MITK_INFO << "[( Image )] Dimensionality differs.";
1478  MITK_INFO << "leftHandSide is " << leftHandSide.GetDimension() << "rightHandSide is "
1479  << rightHandSide.GetDimension();
1480  }
1481  returnValue = false;
1482  }
1483 
1484  // Pair-wise dimension (size) comparison
1485  unsigned int minDimensionality = std::min(rightHandSide.GetDimension(), leftHandSide.GetDimension());
1486  for (unsigned int i = 0; i < minDimensionality; ++i)
1487  {
1488  if (rightHandSide.GetDimension(i) != leftHandSide.GetDimension(i))
1489  {
1490  returnValue = false;
1491  if (verbose)
1492  {
1493  MITK_INFO << "[( Image )] dimension differs.";
1494  MITK_INFO << "leftHandSide->GetDimension(" << i << ") is " << leftHandSide.GetDimension(i)
1495  << "rightHandSide->GetDimension(" << i << ") is " << rightHandSide.GetDimension(i);
1496  }
1497  }
1498  }
1499 
1500  // Pixeltype
1501  mitk::PixelType pixelTypeRightHandSide = rightHandSide.GetPixelType();
1502  mitk::PixelType pixelTypeLeftHandSide = leftHandSide.GetPixelType();
1503  if (!(pixelTypeRightHandSide == pixelTypeLeftHandSide))
1504  {
1505  if (verbose)
1506  {
1507  MITK_INFO << "[( Image )] PixelType differs.";
1508  MITK_INFO << "leftHandSide is " << pixelTypeLeftHandSide.GetTypeAsString() << "rightHandSide is "
1509  << pixelTypeRightHandSide.GetTypeAsString();
1510  }
1511  returnValue = false;
1512  }
1513 
1514  // Geometries
1515  if (!mitk::Equal(*leftHandSide.GetGeometry(), *rightHandSide.GetGeometry(), eps, verbose))
1516  {
1517  if (verbose)
1518  {
1519  MITK_INFO << "[( Image )] Geometries differ.";
1520  }
1521  returnValue = false;
1522  }
1523 
1524  // Pixel values - default mode [ 0 threshold in difference ]
1525  // compare only if all previous checks were successfull, otherwise the ITK filter will throw an exception
1526  if (returnValue)
1527  {
1529 
1530  compareFilter->SetInput(0, &rightHandSide);
1531  compareFilter->SetInput(1, &leftHandSide);
1532  compareFilter->SetTolerance(eps);
1533  compareFilter->Update();
1534 
1535  if ((!compareFilter->GetResult()))
1536  {
1537  returnValue = false;
1538  if (verbose)
1539  {
1540  MITK_INFO << "[(Image)] Pixel values differ: ";
1541  compareFilter->GetCompareResults().PrintSelf();
1542  }
1543  }
1544  }
1545 
1546  return returnValue;
1547 }
bool IsChannelSet(int n=0) const override
Check whether the channel n is set.
Definition: mitkImage.cpp:636
void SetRequestedRegionToLargestPossibleRegion() override
vcl_size_t GetBitsPerComponent() const
Get the number of bits per components.
void SetGeometry(BaseGeometry *aGeometry3D) override
Set the BaseGeometry of the data, which will be referenced (not copied!). It has to be a sub-class of...
itk::SmartPointer< mitk::BaseDataSource > GetSource() const
Get the process object that generated this data object.
unsigned int * m_Dimensions
Definition: mitkImage.h:695
float k(1.0)
ScalarType GetScalarValueMinNoRecompute(unsigned int t=0) const
(DEPRECATED) Get the smallest value for scalar images, but do not recompute it first ...
Definition: mitkImage.cpp:1412
void PrintSelf(std::ostream &os, itk::Indent indent) const override
virtual bool GetImageGeometry() const
Is this an ImageGeometry?
virtual TimeStepType CountTimeSteps() const =0
Returns the number of time steps.
std::string GetTypeAsString() const
Returns a string representing the pixel type and pixel components.
virtual BaseGeometry::Pointer GetGeometryCloneForTimeStep(TimeStepType timeStep) const =0
Returns a clone of the geometry of a specific time point.
ScalarType GetScalarValue2ndMin(int t=0) const
(DEPRECATED) Get the second smallest value for scalar images
Definition: mitkImage.cpp:1407
void SetSpacing(const mitk::Vector3D &aSpacing, bool enforceSetSpacing=false)
Set the spacing (m_Spacing).
unsigned int GetCountOfMinValuedVoxelsNoRecompute(unsigned int t=0) const
(DEPRECATED) Get the count of voxels with the smallest scalar value in the dataset ...
Definition: mitkImage.cpp:1452
virtual ScalarType GetScalarValue2ndMin(int t=0, unsigned int component=0)
Get the second smallest value for scalar images. Recomputation performed only when necessary...
virtual ImageDataItemPointer GetSliceData(int s=0, int t=0, int n=0, void *data=nullptr, ImportMemoryManagementType importMemoryManagement=CopyMemory) const
Definition: mitkImage.cpp:243
~Image() override
Definition: mitkImage.cpp:90
#define MITK_INFO
Definition: mitkLogMacros.h:18
virtual bool IsValidChannel(int n=0) const
Check whether the channel n is valid, i.e., is (or can be) inside of the image.
Definition: mitkImage.cpp:1116
static Pointer New()
const mitk::PixelType GetPixelType(int n=0) const
Returns the PixelType of channel n.
Definition: mitkImage.cpp:101
void Initialize() override
Definition: mitkImage.cpp:803
#define MITK_ERROR
Definition: mitkLogMacros.h:20
double ScalarType
vcl_size_t GetNumberOfComponents() const
Get the number of components of which each element consists.
ImageDataItemPointerArray m_Slices
Definition: mitkImage.h:690
virtual ScalarType GetScalarValue2ndMax(int t=0, unsigned int component=0)
Get the second largest value for scalar images.
unsigned int * GetDimensions() const
Get the sizes of all dimensions as an integer-array.
Definition: mitkImage.cpp:1309
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 ...
Definition: mitkImage.cpp:761
bool IsVolumeSet(int t=0, int n=0) const override
Check whether volume at time t in channel n is set.
Definition: mitkImage.cpp:602
bool IsSliceSet(int s=0, int t=0, int n=0) const override
Get the complete image, i.e., all channels linked together, as a mitkIpPicDescriptor.
Definition: mitkImage.cpp:572
vcl_size_t * m_OffsetTable
Definition: mitkImage.h:699
ScalarType GetScalarValueMax(int t=0) const
(DEPRECATED) Get the maximum for scalar images
Definition: mitkImage.cpp:1401
virtual mitk::ScalarType GetScalarValue2ndMaxNoRecompute(unsigned int t=0)
Get the second largest value for scalar images, but do not recompute it first.
virtual void SetTimeGeometry(TimeGeometry *geometry)
Set the TimeGeometry of the data, which will be referenced (not copied!).
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 ...
Definition: mitkImage.cpp:681
Pointer Clone() const
ImageDataItemPointerArray m_Channels
Definition: mitkImage.h:688
virtual vtkImageData * GetVtkImageData(int t=0, int n=0)
Get a volume at a specific time t of channel n as a vtkImageData.
Definition: mitkImage.cpp:217
Pointer Clone() const
ScalarType GetScalarValue2ndMinNoRecompute(unsigned int t=0) const
(DEPRECATED) Get the second smallest value for scalar images, but do not recompute it first ...
Definition: mitkImage.cpp:1417
RegionType m_RequestedRegion
virtual mitk::ScalarType GetScalarValueMaxNoRecompute(unsigned int t=0)
Get the largest value for scalar images, but do not recompute it first.
void SetGeometry(BaseGeometry *aGeometry3D) override
Sets a geometry to an image.
Definition: mitkImage.cpp:1321
ScalarType GetCountOfMaxValuedVoxels(int t=0) const
(DEPRECATED) Get the count of voxels with the largest scalar value in the dataset ...
Definition: mitkImage.cpp:1442
bool IsRotated() const
Returns true if an image is rotated, i.e. its geometry&#39;s transformation matrix has nonzero elements b...
Definition: mitkImage.cpp:1367
ScalarType GetScalarValueMin(int t=0) const
(DEPRECATED) Get the minimum for scalar images
Definition: mitkImage.cpp:1395
void AccessPixel(const mitk::PixelType ptype, void *data, const unsigned int offset, double &value)
Definition: mitkImage.cpp:138
virtual ImageDataItemPointer GetChannelData(int n=0, void *data=nullptr, ImportMemoryManagementType importMemoryManagement=CopyMemory) const
Definition: mitkImage.cpp:457
void FillVector3D(Tout &out, mitk::ScalarType x, mitk::ScalarType y, mitk::ScalarType z)
Definition: mitkArray.h:106
ImageDataItemPointerArray m_Volumes
Definition: mitkImage.h:689
void PrintSelf(std::ostream &os, itk::Indent indent) const override
Definition: mitkImage.cpp:1336
virtual unsigned int GetCountOfMaxValuedVoxelsNoRecompute(unsigned int t=0)
Get the count of voxels with the largest scalar value in the dataset.
virtual mitk::PlaneGeometry * GetPlaneGeometry(int s) const
Returns the PlaneGeometry of the slice (s).
vcl_size_t GetBpe() const
Get the number of bits per element (of an element)
static Pointer New()
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...
Definition: mitkImage.cpp:669
itk::SimpleFastMutexLock m_ImageDataArraysLock
Definition: mitkImage.h:691
virtual ScalarType GetScalarValueMin(int t=0, unsigned int component=0)
Get the minimum for scalar images. Recomputation performed only when necessary.
static Vector3D offset
virtual ImageDataItemPointer AllocateVolumeData(int t=0, int n=0, void *data=nullptr, ImportMemoryManagementType importMemoryManagement=CopyMemory) const
Definition: mitkImage.cpp:1234
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 ...
Definition: mitkImage.cpp:663
const mitk::TimeGeometry * GetTimeGeometry() const
Return the TimeGeometry of the data as const pointer.
Definition: mitkBaseData.h:61
ScalarType GetCountOfMinValuedVoxels(int t=0) const
(DEPRECATED) Get the count of voxels with the smallest scalar value in the dataset ...
Definition: mitkImage.cpp:1437
StatisticsHolderPointer m_ImageStatistics
Definition: mitkImage.h:704
double GetPixelValueByWorldCoordinate(const mitk::Point3D &position, unsigned int timestep=0, unsigned int component=0)
Get the pixel value at one specific world position.
Definition: mitkImage.cpp:199
MITKCORE_EXPORT mitk::PixelType MakePixelType(vtkImageData *vtkimagedata)
deduct the PixelType for a given vtk image
ScalarType GetScalarValue2ndMax(int t=0) const
(DEPRECATED) Get the second largest value for scalar images
Definition: mitkImage.cpp:1422
#define MITK_WARN
Definition: mitkLogMacros.h:19
unsigned int GetNumberOfChannels() const
Get the number of channels.
void Clear() override
Calls ClearData() and InitializeEmpty();.
Definition: mitkImage.cpp:1314
unsigned int GetDimension() const
Get dimension of the image.
Definition: mitkImage.cpp:106
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...
Definition: mitkImage.cpp:1108
#define mitkPixelTypeMultiplex3(function, ptype, param1, param2, param3)
Super class of data objects consisting of slices.
#define MAX_IMAGE_DIMENSIONS
Defines the maximum of 8 dimensions per image channel taken from ipPicDescriptor. ...
ScalarType GetScalarValue2ndMaxNoRecompute(unsigned int t=0) const
(DEPRECATED) Get the second largest value for scalar images, but do not recompute it first ...
Definition: mitkImage.cpp:1432
virtual ScalarType GetScalarValueMax(int t=0, unsigned int component=0)
Get the maximum for scalar images. Recomputation performed only when necessary.
#define mitkThrow()
static Pointer New()
bool verbose(false)
void SetOrigin(const Point3D &origin)
Set the origin, i.e. the upper-left corner of the plane.
virtual ImageDataItemPointer GetVolumeData(int t=0, int n=0, void *data=nullptr, ImportMemoryManagementType importMemoryManagement=CopyMemory) const
Definition: mitkImage.cpp:326
Image class for storing images.
Definition: mitkImage.h:72
virtual ImageDataItemPointer AllocateChannelData(int n=0, void *data=nullptr, ImportMemoryManagementType importMemoryManagement=CopyMemory) const
Definition: mitkImage.cpp:1281
#define FILL_C_ARRAY(_arr, _size, _value)
Definition: mitkImage.cpp:31
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...
Definition: mitkImage.cpp:716
SlicedGeometry3D * GetSlicedGeometry(unsigned int t=0) const
Convenience access method for the geometry, which is of type SlicedGeometry3D (or a sub-class of it)...
RegionType m_LargestPossibleRegion
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...
Definition: mitkImage.cpp:1099
unsigned int m_Dimension
Definition: mitkImage.h:693
double GetPixelValueByIndex(const itk::Index< 3 > &position, unsigned int timestep=0, unsigned int component=0)
Get the pixel value at one specific index position.
Definition: mitkImage.cpp:159
std::vcl_size_t TimeStepType
mitk::Image::Pointer image
virtual mitk::ScalarType GetScalarValueMinNoRecompute(unsigned int t=0) const
Get the smallest value for scalar images, but do not recompute it first.
void WorldToIndex(const mitk::Point3D &pt_mm, mitk::Point3D &pt_units) const
Convert world coordinates (in mm) of a point to (continuous!) index coordinates.
Describes the geometry of a data object consisting of slices.
vcl_size_t GetSize() const
Get size of the PixelType in bytes.
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 ...
Definition: mitkImage.cpp:675
static T min(T x, T y)
Definition: svm.cpp:53
Class holding the statistics informations about a single mitk::Image.
virtual void Clear()
Calls ClearData() and InitializeEmpty();.
virtual void * GetData()
Get the data vector of the complete image, i.e., of all channels linked together. ...
Definition: mitkImage.cpp:118
virtual bool IsValidTimeStep(int t) const
Definition: mitkImage.cpp:1143
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.
virtual unsigned int GetCountOfMinValuedVoxelsNoRecompute(unsigned int t=0) const
Get the count of voxels with the smallest scalar value in the dataset.
unsigned int GetCountOfMaxValuedVoxelsNoRecompute(unsigned int t=0) const
(DEPRECATED) Get the count of voxels with the largest scalar value in the dataset ...
Definition: mitkImage.cpp:1447
virtual BaseGeometry::Pointer GetGeometryForTimeStep(TimeStepType timeStep) const =0
Returns the geometry which corresponds to the given time step.
void Expand(unsigned int timeSteps) override
Expands the TimeGeometry to a number of TimeSteps.
Definition: mitkImage.cpp:1148
bool m_RequestedRegionInitialized
static Pointer New()
int GetSliceIndex(int s=0, int t=0, int n=0) const
Definition: mitkImage.cpp:1155
virtual ImageDataItemPointer AllocateSliceData(int s=0, int t=0, int n=0, void *data=nullptr, ImportMemoryManagementType importMemoryManagement=CopyMemory) const
Definition: mitkImage.cpp:1169
MITKCORE_EXPORT const ScalarType eps
unsigned int GetTimeSteps() const
Get the number of time steps from the TimeGeometry As the base data has not a data vector given by it...
Definition: mitkBaseData.h:355
void ComputeOffsetTable()
Definition: mitkImage.cpp:1124
Describes a two-dimensional, rectangular plane.
Pointer Clone() const
Internal class for managing references on sub-images.
ScalarType GetScalarValueMaxNoRecompute(unsigned int t=0) const
(DEPRECATED) Get the largest value for scalar images, but do not recompute it first ...
Definition: mitkImage.cpp:1427
mitk::BaseGeometry * GetGeometry(int t=0) const
Return the geometry, which is a TimeGeometry, of the data as non-const pointer.
Definition: mitkBaseData.h:138
virtual void Expand(unsigned int timeSteps)
Expands the TimeGeometry to a number of TimeSteps.
ImageDataItemPointer m_CompleteData
Definition: mitkImage.h:700
mitk::ScalarType GetCountOfMinValuedVoxels(int t=0, unsigned int component=0)
Get the count of voxels with the smallest scalar value in the dataset.
std::string GetComponentTypeAsString() const
Returns a string containing the name of the component.
int GetVolumeIndex(int t=0, int n=0) const
Definition: mitkImage.cpp:1162
std::string GetPixelTypeAsString() const
Returns a string containing the ITK pixel type name.
ImportMemoryManagementType
Definition: mitkImage.h:104
mitk::ScalarType GetCountOfMaxValuedVoxels(int t=0, unsigned int component=0)
Get the count of voxels with the largest scalar value in the dataset.
BaseGeometry Describes the geometry of a data object.
Class for defining the data type of pixels.
Definition: mitkPixelType.h:51
virtual mitk::ScalarType GetScalarValue2ndMinNoRecompute(unsigned int t=0) const
Get the second smallest value for scalar images, but do not recompute it first.
mitk::AffineTransform3D * GetIndexToWorldTransform()
Get the transformation used to convert from index to world coordinates.
ImageDescriptor::Pointer m_ImageDescriptor
Definition: mitkImage.h:697