Medical Imaging Interaction Toolkit  2016.11.0
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,
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.