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
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,
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 #include "mitkDiffImageApplier.h"
18 
20 #include "mitkImageAccessByItk.h"
21 #include "mitkImageCast.h"
22 #include "mitkImageTimeSelector.h"
23 #include "mitkRenderingManager.h"
25 
26 #include <itkImageRegionConstIterator.h>
27 #include <itkImageSliceIteratorWithIndex.h>
28 
30 {
31 }
32 
34 {
35 }
36 
38 {
39  ApplyDiffImageOperation *imageOperation = dynamic_cast<ApplyDiffImageOperation *>(operation);
40  if (imageOperation // we actually have the kind of operation that we can handle
41  &&
42  imageOperation->IsImageStillValid()) // AND the image is not yet deleted
43  {
44  m_Image = imageOperation->GetImage();
45  Image::Pointer image3D = m_Image; // will be changed later in case of 3D+t
46 
47  m_SliceDifferenceImage = imageOperation->GetDiffImage();
48  m_TimeStep = imageOperation->GetTimeStep();
49 
50  m_Factor = imageOperation->GetFactor();
51 
52  if (m_SliceDifferenceImage->GetDimension() == 2)
53  {
54  m_SliceIndex = imageOperation->GetSliceIndex();
55  m_SliceDimension = imageOperation->GetSliceDimension();
56  switch (m_SliceDimension)
57  {
58  default:
59  case 2:
60  m_Dimension0 = 0;
61  m_Dimension1 = 1;
62  break;
63  case 1:
64  m_Dimension0 = 0;
65  m_Dimension1 = 2;
66  break;
67  case 0:
68  m_Dimension0 = 1;
69  m_Dimension1 = 2;
70  break;
71  }
72 
73  if (m_SliceDifferenceImage->GetDimension() != 2 || (m_Image->GetDimension() < 3 || m_Image->GetDimension() > 4) ||
74  m_SliceDifferenceImage->GetDimension(0) != m_Image->GetDimension(m_Dimension0) ||
75  m_SliceDifferenceImage->GetDimension(1) != m_Image->GetDimension(m_Dimension1) ||
76  m_SliceIndex >= m_Image->GetDimension(m_SliceDimension))
77  {
78  itkExceptionMacro(
79  "Slice and image dimensions differ or slice index is too large. Sorry, cannot work like this.");
80  return;
81  }
82 
83  if (m_Image->GetDimension() == 4)
84  {
86  timeSelector->SetInput(m_Image);
87  timeSelector->SetTimeNr(m_TimeStep);
88  timeSelector->UpdateLargestPossibleRegion();
89  image3D = timeSelector->GetOutput();
90  }
91 
92  // this will do a long long if/else to find out both pixel types
93  AccessFixedDimensionByItk(image3D, ItkImageSwitch2DDiff, 3);
94 
95  if (m_Factor == 1 || m_Factor == -1)
96  {
97  if (m_Factor == -1)
98  {
99  // multiply diff pixels by factor and then send this diff slice
100  AccessFixedDimensionByItk(m_SliceDifferenceImage, ItkInvertPixelValues, 2);
101  }
102 
103  // just send the diff to SegmentationInterpolationController
106  if (interpolator)
107  {
108  interpolator->BlockModified(true);
109  interpolator->SetChangedSlice(m_SliceDifferenceImage, m_SliceDimension, m_SliceIndex, m_TimeStep);
110  }
111 
112  m_Image->Modified();
113 
114  if (interpolator)
115  {
116  interpolator->BlockModified(false);
117  }
118 
119  if (m_Factor == -1) // return to normal values
120  {
121  AccessFixedDimensionByItk(m_SliceDifferenceImage, ItkInvertPixelValues, 2);
122  }
123  }
124  else // no trivial case, too lazy to do something else
125  {
126  m_Image->Modified(); // check if interpolation is called. prefer to send diff directly
127  }
128 
130  }
131  else if (m_SliceDifferenceImage->GetDimension() == 3)
132  {
133  // ...
134  if (m_SliceDifferenceImage->GetDimension(0) != m_Image->GetDimension(0) ||
135  m_SliceDifferenceImage->GetDimension(1) != m_Image->GetDimension(1) ||
136  m_SliceDifferenceImage->GetDimension(2) != m_Image->GetDimension(2) || m_TimeStep >= m_Image->GetDimension(3))
137  {
138  itkExceptionMacro("Diff image size differs from original image size. Sorry, cannot work like this.");
139  return;
140  }
141 
142  if (m_Image->GetDimension() == 4)
143  {
145  timeSelector->SetInput(m_Image);
146  timeSelector->SetTimeNr(m_TimeStep);
147  timeSelector->UpdateLargestPossibleRegion();
148  image3D = timeSelector->GetOutput();
149  }
150 
151  // this will do a long long if/else to find out both pixel types
152  AccessFixedDimensionByItk(image3D, ItkImageSwitch3DDiff, 3);
153 
154  if (m_Factor == 1 || m_Factor == -1)
155  {
156  if (m_Factor == -1)
157  {
158  // multiply diff pixels by factor and then send this diff slice
159  AccessFixedDimensionByItk(m_SliceDifferenceImage, ItkInvertPixelValues, 3);
160  }
161 
162  // just send the diff to SegmentationInterpolationController
165  if (interpolator)
166  {
167  interpolator->BlockModified(true);
168  interpolator->SetChangedVolume(m_SliceDifferenceImage, m_TimeStep);
169  }
170 
171  m_Image->Modified();
172 
173  if (interpolator)
174  {
175  interpolator->BlockModified(false);
176  }
177 
178  if (m_Factor == -1) // return to normal values
179  {
180  AccessFixedDimensionByItk(m_SliceDifferenceImage, ItkInvertPixelValues, 3);
181  }
182  }
183  else // no trivial case, too lazy to do something else
184  {
185  m_Image->Modified(); // check if interpolation is called. prefer to send diff directly
186  }
187 
189  }
190  else
191  {
192  itkExceptionMacro("Diff image must be 2D or 3D. Sorry, cannot work like this.");
193  return;
194  }
195  }
196 
197  m_Image = nullptr;
198  m_SliceDifferenceImage = nullptr;
199 }
200 
202 {
203  static DiffImageApplier::Pointer s_Instance = DiffImageApplier::New();
204 
205  return s_Instance;
206 }
207 
208 // basically copied from mitk/Core/Algorithms/mitkImageAccessByItk.h
209 #define myMITKDiffImageApplierFilterAccessByItk(mitkImage, itkImageTypeFunction, pixeltype, dimension, itkimage2) \
210  if (typeId == MapPixelComponentType<pixeltype>::value) \
211  \
212 { \
213  typedef itk::Image<pixeltype, dimension> ImageType; \
214  typedef mitk::ImageToItk<ImageType> ImageToItkType; \
215  itk::SmartPointer<ImageToItkType> imagetoitk = ImageToItkType::New(); \
216  const mitk::Image *constImage = mitkImage; \
217  mitk::Image *nonConstImage = const_cast<mitk::Image *>(constImage); \
218  nonConstImage->Update(); \
219  imagetoitk->SetInput(nonConstImage); \
220  imagetoitk->Update(); \
221  itkImageTypeFunction(imagetoitk->GetOutput(), itkimage2); \
222  \
223 }
224 
225 #define myMITKDiffImageApplierFilterAccessAllTypesByItk(mitkImage, itkImageTypeFunction, dimension, itkimage2) \
226  \
227 { \
228  myMITKDiffImageApplierFilterAccessByItk(mitkImage, itkImageTypeFunction, double, dimension, itkimage2) else myMITKDiffImageApplierFilterAccessByItk( \
229  mitkImage, \
230  itkImageTypeFunction, \
231  float, \
232  dimension, \
233  itkimage2) else myMITKDiffImageApplierFilterAccessByItk(mitkImage, itkImageTypeFunction, int, dimension, itkimage2) else myMITKDiffImageApplierFilterAccessByItk(mitkImage, \
234  itkImageTypeFunction, \
235  unsigned int, \
236  dimension, \
237  itkimage2) else myMITKDiffImageApplierFilterAccessByItk(mitkImage, itkImageTypeFunction, short, dimension, itkimage2) else myMITKDiffImageApplierFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned short, dimension, itkimage2) else myMITKDiffImageApplierFilterAccessByItk(mitkImage, \
238  itkImageTypeFunction, \
239  char, \
240  dimension, \
241  itkimage2) else myMITKDiffImageApplierFilterAccessByItk(mitkImage, \
242  itkImageTypeFunction, \
243  unsigned char, \
244  dimension, \
245  itkimage2) \
246  \
247 }
248 
249 template <typename TPixel, unsigned int VImageDimension>
250 void mitk::DiffImageApplier::ItkImageSwitch2DDiff(itk::Image<TPixel, VImageDimension> *itkImage)
251 {
252  const int typeId = m_SliceDifferenceImage->GetPixelType().GetComponentType();
253 
254  myMITKDiffImageApplierFilterAccessAllTypesByItk(m_SliceDifferenceImage, ItkImageProcessing2DDiff, 2, itkImage);
255 }
256 
257 template <typename TPixel, unsigned int VImageDimension>
258 void mitk::DiffImageApplier::ItkImageSwitch3DDiff(itk::Image<TPixel, VImageDimension> *itkImage)
259 {
260  const int typeId = m_SliceDifferenceImage->GetPixelType().GetComponentType();
261 
262  myMITKDiffImageApplierFilterAccessAllTypesByItk(m_SliceDifferenceImage, ItkImageProcessing3DDiff, 3, itkImage);
263 }
264 
265 template <typename TPixel1, unsigned int VImageDimension1, typename TPixel2, unsigned int VImageDimension2>
266 void mitk::DiffImageApplier::ItkImageProcessing2DDiff(itk::Image<TPixel1, VImageDimension1> *diffImage,
267  itk::Image<TPixel2, VImageDimension2> *outputImage)
268 {
269  typedef itk::Image<TPixel1, VImageDimension1> DiffImageType;
270  typedef itk::Image<TPixel2, VImageDimension2> VolumeImageType;
271 
272  typedef itk::ImageSliceIteratorWithIndex<VolumeImageType> OutputSliceIteratorType;
273  typedef itk::ImageRegionConstIterator<DiffImageType> DiffSliceIteratorType;
274 
275  typename VolumeImageType::RegionType sliceInVolumeRegion;
276 
277  sliceInVolumeRegion = outputImage->GetLargestPossibleRegion();
278  sliceInVolumeRegion.SetSize(m_SliceDimension, 1); // just one slice
279  sliceInVolumeRegion.SetIndex(m_SliceDimension, m_SliceIndex); // exactly this slice, please
280 
281  OutputSliceIteratorType outputIterator(outputImage, sliceInVolumeRegion);
282  outputIterator.SetFirstDirection(m_Dimension0);
283  outputIterator.SetSecondDirection(m_Dimension1);
284 
285  DiffSliceIteratorType diffIterator(diffImage, diffImage->GetLargestPossibleRegion());
286 
287  // iterate over output slice (and over input slice simultaneously)
288  outputIterator.GoToBegin();
289  diffIterator.GoToBegin();
290  while (!outputIterator.IsAtEnd())
291  {
292  while (!outputIterator.IsAtEndOfSlice())
293  {
294  while (!outputIterator.IsAtEndOfLine())
295  {
296  TPixel2 newValue = outputIterator.Get() + (TPixel2)((double)diffIterator.Get() * m_Factor);
297  outputIterator.Set(newValue);
298  ++outputIterator;
299  ++diffIterator;
300  }
301  outputIterator.NextLine();
302  }
303  outputIterator.NextSlice();
304  }
305 }
306 
307 template <typename TPixel1, unsigned int VImageDimension1, typename TPixel2, unsigned int VImageDimension2>
308 void mitk::DiffImageApplier::ItkImageProcessing3DDiff(itk::Image<TPixel1, VImageDimension1> *diffImage,
309  itk::Image<TPixel2, VImageDimension2> *outputImage)
310 {
311  typedef itk::Image<TPixel1, VImageDimension1> DiffImageType;
312  typedef itk::Image<TPixel2, VImageDimension2> VolumeImageType;
313 
314  typedef itk::ImageRegionIterator<VolumeImageType> OutputSliceIteratorType;
315  typedef itk::ImageRegionConstIterator<DiffImageType> DiffSliceIteratorType;
316 
317  OutputSliceIteratorType outputIterator(outputImage, outputImage->GetLargestPossibleRegion());
318  DiffSliceIteratorType diffIterator(diffImage, diffImage->GetLargestPossibleRegion());
319 
320  // iterate over output slice (and over input slice simultaneously)
321  outputIterator.GoToBegin();
322  diffIterator.GoToBegin();
323  while (!outputIterator.IsAtEnd())
324  {
325  TPixel2 newValue = outputIterator.Get() + (TPixel2)((double)diffIterator.Get() * m_Factor);
326  outputIterator.Set(newValue);
327  ++outputIterator;
328  ++diffIterator;
329  }
330 }
331 
332 template <typename TPixel, unsigned int VImageDimension>
333 void mitk::DiffImageApplier::ItkInvertPixelValues(itk::Image<TPixel, VImageDimension> *itkImage)
334 {
335  typedef itk::ImageRegionIterator<itk::Image<TPixel, VImageDimension>> IteratorType;
336  IteratorType iter(itkImage, itkImage->GetLargestPossibleRegion());
337 
338  iter.GoToBegin();
339  while (!iter.IsAtEnd())
340  {
341  iter.Set(-(iter.Get()));
342  ++iter;
343  }
344 }
Operation, that holds information about some image difference.
void ItkImageProcessing2DDiff(itk::Image< TPixel1, VImageDimension1 > *itkImage1, itk::Image< TPixel2, VImageDimension2 > *itkImage2)
itk::SmartPointer< Self > Pointer
#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:33
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.
virtual void ExecuteOperation(Operation *operation) override
#define myMITKDiffImageApplierFilterAccessAllTypesByItk(mitkImage, itkImageTypeFunction, dimension, itkimage2)
void ItkInvertPixelValues(itk::Image< TPixel, VImageDimension > *itkImage)
void RequestUpdateAll(RequestType type=REQUEST_UPDATE_ALL)
static Pointer New()