Medical Imaging Interaction Toolkit  2018.4.99-6aa36ba9
Medical Imaging Interaction Toolkit
mitkDiffImageApplier.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #include "mitkDiffImageApplier.h"
14 
16 #include "mitkImageAccessByItk.h"
17 #include "mitkImageCast.h"
18 #include "mitkImageTimeSelector.h"
19 #include "mitkRenderingManager.h"
21 
22 #include <itkImageRegionConstIterator.h>
23 #include <itkImageSliceIteratorWithIndex.h>
24 
25 #include <type_traits>
26 
28  : m_Image(nullptr),
29  m_SliceDifferenceImage(nullptr),
30  m_SliceIndex(0),
31  m_SliceDimension(0),
32  m_TimeStep(0),
33  m_Dimension0(0),
34  m_Dimension1(0),
35  m_Factor(1.0)
36 {
37 }
38 
40 {
41 }
42 
44 {
45  auto *imageOperation = dynamic_cast<ApplyDiffImageOperation *>(operation);
46  if (imageOperation // we actually have the kind of operation that we can handle
47  &&
48  imageOperation->IsImageStillValid()) // AND the image is not yet deleted
49  {
50  m_Image = imageOperation->GetImage();
51  Image::Pointer image3D = m_Image; // will be changed later in case of 3D+t
52 
53  m_SliceDifferenceImage = imageOperation->GetDiffImage();
54  m_TimeStep = imageOperation->GetTimeStep();
55 
56  m_Factor = imageOperation->GetFactor();
57 
58  if (m_SliceDifferenceImage->GetDimension() == 2)
59  {
60  m_SliceIndex = imageOperation->GetSliceIndex();
61  m_SliceDimension = imageOperation->GetSliceDimension();
62  switch (m_SliceDimension)
63  {
64  default:
65  case 2:
66  m_Dimension0 = 0;
67  m_Dimension1 = 1;
68  break;
69  case 1:
70  m_Dimension0 = 0;
71  m_Dimension1 = 2;
72  break;
73  case 0:
74  m_Dimension0 = 1;
75  m_Dimension1 = 2;
76  break;
77  }
78 
79  if (m_SliceDifferenceImage->GetDimension() != 2 || (m_Image->GetDimension() < 3 || m_Image->GetDimension() > 4) ||
80  m_SliceDifferenceImage->GetDimension(0) != m_Image->GetDimension(m_Dimension0) ||
81  m_SliceDifferenceImage->GetDimension(1) != m_Image->GetDimension(m_Dimension1) ||
82  m_SliceIndex >= m_Image->GetDimension(m_SliceDimension))
83  {
84  itkExceptionMacro(
85  "Slice and image dimensions differ or slice index is too large. Sorry, cannot work like this.");
86  return;
87  }
88 
89  if (m_Image->GetDimension() == 4)
90  {
92  timeSelector->SetInput(m_Image);
93  timeSelector->SetTimeNr(m_TimeStep);
94  timeSelector->UpdateLargestPossibleRegion();
95  image3D = timeSelector->GetOutput();
96  }
97 
98  // this will do a long long if/else to find out both pixel types
100 
101  if (m_Factor == 1 || m_Factor == -1)
102  {
103  if (m_Factor == -1)
104  {
105  // multiply diff pixels by factor and then send this diff slice
107  }
108 
109  // just send the diff to SegmentationInterpolationController
112  if (interpolator)
113  {
114  interpolator->BlockModified(true);
116  }
117 
118  m_Image->Modified();
119 
120  if (interpolator)
121  {
122  interpolator->BlockModified(false);
123  }
124 
125  if (m_Factor == -1) // return to normal values
126  {
128  }
129  }
130  else // no trivial case, too lazy to do something else
131  {
132  m_Image->Modified(); // check if interpolation is called. prefer to send diff directly
133  }
134 
136  }
137  else if (m_SliceDifferenceImage->GetDimension() == 3)
138  {
139  // ...
140  if (m_SliceDifferenceImage->GetDimension(0) != m_Image->GetDimension(0) ||
141  m_SliceDifferenceImage->GetDimension(1) != m_Image->GetDimension(1) ||
142  m_SliceDifferenceImage->GetDimension(2) != m_Image->GetDimension(2) || m_TimeStep >= m_Image->GetDimension(3))
143  {
144  itkExceptionMacro("Diff image size differs from original image size. Sorry, cannot work like this.");
145  return;
146  }
147 
148  if (m_Image->GetDimension() == 4)
149  {
151  timeSelector->SetInput(m_Image);
152  timeSelector->SetTimeNr(m_TimeStep);
153  timeSelector->UpdateLargestPossibleRegion();
154  image3D = timeSelector->GetOutput();
155  }
156 
157  // this will do a long long if/else to find out both pixel types
159 
160  if (m_Factor == 1 || m_Factor == -1)
161  {
162  if (m_Factor == -1)
163  {
164  // multiply diff pixels by factor and then send this diff slice
166  }
167 
168  // just send the diff to SegmentationInterpolationController
171  if (interpolator)
172  {
173  interpolator->BlockModified(true);
175  }
176 
177  m_Image->Modified();
178 
179  if (interpolator)
180  {
181  interpolator->BlockModified(false);
182  }
183 
184  if (m_Factor == -1) // return to normal values
185  {
187  }
188  }
189  else // no trivial case, too lazy to do something else
190  {
191  m_Image->Modified(); // check if interpolation is called. prefer to send diff directly
192  }
193 
195  }
196  else
197  {
198  itkExceptionMacro("Diff image must be 2D or 3D. Sorry, cannot work like this.");
199  return;
200  }
201  }
202 
203  m_Image = nullptr;
204  m_SliceDifferenceImage = nullptr;
205 }
206 
208 {
209  static DiffImageApplier::Pointer s_Instance = DiffImageApplier::New();
210 
211  return s_Instance;
212 }
213 
214 // basically copied from mitk/Core/Algorithms/mitkImageAccessByItk.h
215 #define myMITKDiffImageApplierFilterAccessByItk(mitkImage, itkImageTypeFunction, pixeltype, dimension, itkimage2) \
216  if (typeId == MapPixelComponentType<pixeltype>::value) \
217  \
218 { \
219  typedef itk::Image<pixeltype, dimension> ImageType; \
220  typedef mitk::ImageToItk<ImageType> ImageToItkType; \
221  itk::SmartPointer<ImageToItkType> imagetoitk = ImageToItkType::New(); \
222  const mitk::Image *constImage = mitkImage; \
223  mitk::Image *nonConstImage = const_cast<mitk::Image *>(constImage); \
224  nonConstImage->Update(); \
225  imagetoitk->SetInput(nonConstImage); \
226  imagetoitk->Update(); \
227  itkImageTypeFunction(imagetoitk->GetOutput(), itkimage2); \
228  \
229 }
230 
231 #define myMITKDiffImageApplierFilterAccessAllTypesByItk(mitkImage, itkImageTypeFunction, dimension, itkimage2) \
232  \
233 { \
234  myMITKDiffImageApplierFilterAccessByItk(mitkImage, itkImageTypeFunction, double, dimension, itkimage2) else myMITKDiffImageApplierFilterAccessByItk( \
235  mitkImage, \
236  itkImageTypeFunction, \
237  float, \
238  dimension, \
239  itkimage2) else myMITKDiffImageApplierFilterAccessByItk(mitkImage, itkImageTypeFunction, int, dimension, itkimage2) else myMITKDiffImageApplierFilterAccessByItk(mitkImage, \
240  itkImageTypeFunction, \
241  unsigned int, \
242  dimension, \
243  itkimage2) else myMITKDiffImageApplierFilterAccessByItk(mitkImage, itkImageTypeFunction, short, dimension, itkimage2) else myMITKDiffImageApplierFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned short, dimension, itkimage2) else myMITKDiffImageApplierFilterAccessByItk(mitkImage, \
244  itkImageTypeFunction, \
245  char, \
246  dimension, \
247  itkimage2) else myMITKDiffImageApplierFilterAccessByItk(mitkImage, \
248  itkImageTypeFunction, \
249  unsigned char, \
250  dimension, \
251  itkimage2) \
252  \
253 }
254 
255 template <typename TPixel, unsigned int VImageDimension>
256 void mitk::DiffImageApplier::ItkImageSwitch2DDiff(itk::Image<TPixel, VImageDimension> *itkImage)
257 {
258  const int typeId = m_SliceDifferenceImage->GetPixelType().GetComponentType();
259 
261 }
262 
263 template <typename TPixel, unsigned int VImageDimension>
264 void mitk::DiffImageApplier::ItkImageSwitch3DDiff(itk::Image<TPixel, VImageDimension> *itkImage)
265 {
266  const int typeId = m_SliceDifferenceImage->GetPixelType().GetComponentType();
267 
269 }
270 
271 template <typename TPixel1, unsigned int VImageDimension1, typename TPixel2, unsigned int VImageDimension2>
272 void mitk::DiffImageApplier::ItkImageProcessing2DDiff(itk::Image<TPixel1, VImageDimension1> *diffImage,
273  itk::Image<TPixel2, VImageDimension2> *outputImage)
274 {
275  typedef itk::Image<TPixel1, VImageDimension1> DiffImageType;
276  typedef itk::Image<TPixel2, VImageDimension2> VolumeImageType;
277 
278  typedef itk::ImageSliceIteratorWithIndex<VolumeImageType> OutputSliceIteratorType;
279  typedef itk::ImageRegionConstIterator<DiffImageType> DiffSliceIteratorType;
280 
281  typename VolumeImageType::RegionType sliceInVolumeRegion;
282 
283  sliceInVolumeRegion = outputImage->GetLargestPossibleRegion();
284  sliceInVolumeRegion.SetSize(m_SliceDimension, 1); // just one slice
285  sliceInVolumeRegion.SetIndex(m_SliceDimension, m_SliceIndex); // exactly this slice, please
286 
287  OutputSliceIteratorType outputIterator(outputImage, sliceInVolumeRegion);
288  outputIterator.SetFirstDirection(m_Dimension0);
289  outputIterator.SetSecondDirection(m_Dimension1);
290 
291  DiffSliceIteratorType diffIterator(diffImage, diffImage->GetLargestPossibleRegion());
292 
293  // iterate over output slice (and over input slice simultaneously)
294  outputIterator.GoToBegin();
295  diffIterator.GoToBegin();
296  while (!outputIterator.IsAtEnd())
297  {
298  while (!outputIterator.IsAtEndOfSlice())
299  {
300  while (!outputIterator.IsAtEndOfLine())
301  {
302  TPixel2 newValue = outputIterator.Get() + (TPixel2)((double)diffIterator.Get() * m_Factor);
303  outputIterator.Set(newValue);
304  ++outputIterator;
305  ++diffIterator;
306  }
307  outputIterator.NextLine();
308  }
309  outputIterator.NextSlice();
310  }
311 }
312 
313 template <typename TPixel1, unsigned int VImageDimension1, typename TPixel2, unsigned int VImageDimension2>
314 void mitk::DiffImageApplier::ItkImageProcessing3DDiff(itk::Image<TPixel1, VImageDimension1> *diffImage,
315  itk::Image<TPixel2, VImageDimension2> *outputImage)
316 {
317  typedef itk::Image<TPixel1, VImageDimension1> DiffImageType;
318  typedef itk::Image<TPixel2, VImageDimension2> VolumeImageType;
319 
320  typedef itk::ImageRegionIterator<VolumeImageType> OutputSliceIteratorType;
321  typedef itk::ImageRegionConstIterator<DiffImageType> DiffSliceIteratorType;
322 
323  OutputSliceIteratorType outputIterator(outputImage, outputImage->GetLargestPossibleRegion());
324  DiffSliceIteratorType diffIterator(diffImage, diffImage->GetLargestPossibleRegion());
325 
326  // iterate over output slice (and over input slice simultaneously)
327  outputIterator.GoToBegin();
328  diffIterator.GoToBegin();
329  while (!outputIterator.IsAtEnd())
330  {
331  TPixel2 newValue = outputIterator.Get() + (TPixel2)((double)diffIterator.Get() * m_Factor);
332  outputIterator.Set(newValue);
333  ++outputIterator;
334  ++diffIterator;
335  }
336 }
337 
338 #ifdef _MSC_VER
339 # pragma warning(push)
340 # pragma warning(disable:4146) // unary minus operator applied to unsigned type, result still unsigned
341 #endif
342 
343 template <typename TPixel, unsigned int VImageDimension>
344 void mitk::DiffImageApplier::ItkInvertPixelValues(itk::Image<TPixel, VImageDimension> *itkImage)
345 {
346  typedef itk::ImageRegionIterator<itk::Image<TPixel, VImageDimension>> IteratorType;
347  IteratorType iter(itkImage, itkImage->GetLargestPossibleRegion());
348 
349  iter.GoToBegin();
350  while (!iter.IsAtEnd())
351  {
352  iter.Set(-(iter.Get()));
353  ++iter;
354  }
355 }
356 
357 #ifdef _MSC_VER
358 # pragma warning(pop)
359 #endif
Operation, that holds information about some image difference.
void ItkImageProcessing2DDiff(itk::Image< TPixel1, VImageDimension1 > *itkImage1, itk::Image< TPixel2, VImageDimension2 > *itkImage2)
#define AccessFixedDimensionByItk(mitkImage, itkImageTypeFunction, dimension)
Access a mitk-image with known dimension by an itk-image.
Base class of all Operation-classes.
Definition: mitkOperation.h:29
static Pointer New()
void ItkImageSwitch3DDiff(itk::Image< TPixel, VImageDimension > *image)
void SetChangedSlice(const Image *sliceDiff, unsigned int sliceDimension, unsigned int sliceIndex, unsigned int timeStep)
Update after changing a single slice.
void ItkImageSwitch2DDiff(itk::Image< TPixel, VImageDimension > *image)
Applies difference images to 3D images.
void ItkImageProcessing3DDiff(itk::Image< TPixel1, VImageDimension1 > *itkImage1, itk::Image< TPixel2, VImageDimension2 > *itkImage2)
void BlockModified(bool)
Block reaction to an images Modified() events.
static DiffImageApplier * GetInstanceForUndo()
void SetChangedVolume(const Image *sliceDiff, unsigned int timeStep)
static RenderingManager * GetInstance()
static SegmentationInterpolationController * InterpolatorForImage(const Image *)
Find interpolator for a given image.
void ExecuteOperation(Operation *operation) override
Image::Pointer m_SliceDifferenceImage
#define myMITKDiffImageApplierFilterAccessAllTypesByItk(mitkImage, itkImageTypeFunction, dimension, itkimage2)
void ItkInvertPixelValues(itk::Image< TPixel, VImageDimension > *itkImage)
void RequestUpdateAll(RequestType type=REQUEST_UPDATE_ALL)
static Pointer New()