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