Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkOverwriteSliceImageFilter.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 
19 #include "mitkDiffImageApplier.h"
20 #include "mitkImageAccessByItk.h"
21 #include "mitkImageCast.h"
22 #include "mitkImageTimeSelector.h"
23 #include "mitkInteractionConst.h"
24 #include "mitkOperationEvent.h"
26 #include "mitkUndoController.h"
27 
28 #include <itkImageRegionIterator.h>
29 #include <itkImageSliceIteratorWithIndex.h>
30 
32  : m_SliceIndex(0),
33  m_SliceDimension(0),
34  m_TimeStep(0),
35  m_Dimension0(0),
36  m_Dimension1(1),
37  m_CreateUndoInformation(false)
38 {
39  MITK_WARN << "Class is deprecated! Use mitkVtkImageOverwrite instead.";
40 }
41 
43 {
44 }
45 
47 {
48  //
49  // this is the place to implement the major part of undo functionality (bug #491)
50  // here we have to create undo/do operations
51  //
52  // WHO is the operation actor? This object may not be destroyed ever (design of undo stack)!
53  // -> some singleton method of this filter?
54  //
55  // neccessary additional objects:
56  // - something that executes the operations
57  // - the operation class (must hold a binary diff or something)
58  // - observer commands to know when the image is deleted (no further action then, perhaps even remove the operations
59  // from the undo stack)
60  //
63 
64  Image::ConstPointer slice = m_SliceImage;
65 
66  if (input.IsNull() || slice.IsNull())
67  return;
68 
69  switch (m_SliceDimension)
70  {
71  default:
72  case 2:
73  m_Dimension0 = 0;
74  m_Dimension1 = 1;
75  break;
76  case 1:
77  m_Dimension0 = 0;
78  m_Dimension1 = 2;
79  break;
80  case 0:
81  m_Dimension0 = 1;
82  m_Dimension1 = 2;
83  break;
84  }
85 
86  if (slice->GetDimension() < 2 || input->GetDimension() > 4 ||
87  slice->GetDimension(0) != input->GetDimension(m_Dimension0) ||
88  slice->GetDimension(1) != input->GetDimension(m_Dimension1) ||
89  m_SliceIndex >= input->GetDimension(m_SliceDimension))
90  {
91  itkExceptionMacro("Slice and image dimensions differ or slice index is too large. Sorry, cannot work like this.");
92  return;
93  }
94 
95  if (input->GetDimension() == 4)
96  {
98  timeSelector->SetInput(input);
99  timeSelector->SetTimeNr(m_TimeStep);
100  timeSelector->UpdateLargestPossibleRegion();
101  input3D = timeSelector->GetOutput();
102  }
103 
104  if (m_SliceDifferenceImage.IsNull() || m_SliceDifferenceImage->GetDimension(0) != m_SliceImage->GetDimension(0) ||
105  m_SliceDifferenceImage->GetDimension(1) != m_SliceImage->GetDimension(1))
106  {
107  m_SliceDifferenceImage = mitk::Image::New();
108  mitk::PixelType pixelType(mitk::MakeScalarPixelType<short signed int>());
109  m_SliceDifferenceImage->Initialize(pixelType, 2, m_SliceImage->GetDimensions());
110  }
111 
112  // MITK_INFO << "Overwriting slice " << m_SliceIndex << " in dimension " << m_SliceDimension << " at time step " <<
113  // m_TimeStep << std::endl;
114  // this will do a long long if/else to find out both pixel types
115  AccessFixedDimensionByItk(input3D, ItkImageSwitch, 3);
116 
118  if (interpolator)
119  {
120  interpolator->BlockModified(true);
121  interpolator->SetChangedSlice(m_SliceDifferenceImage, m_SliceDimension, m_SliceIndex, m_TimeStep);
122  }
123 
124  if (m_CreateUndoInformation)
125  {
126  // create do/undo operations (we don't execute the doOp here, because it has already been executed during
127  // calculation of the diff image
128  auto doOp = new ApplyDiffImageOperation(OpTEST,
129  const_cast<Image *>(input.GetPointer()),
130  m_SliceDifferenceImage,
131  m_TimeStep,
132  m_SliceDimension,
133  m_SliceIndex);
134  auto undoOp = new ApplyDiffImageOperation(OpTEST,
135  const_cast<Image *>(input.GetPointer()),
136  m_SliceDifferenceImage,
137  m_TimeStep,
138  m_SliceDimension,
139  m_SliceIndex);
140  undoOp->SetFactor(-1.0);
141  OperationEvent *undoStackItem =
143  doOp,
144  undoOp,
145  this->EventDescription(m_SliceDimension, m_SliceIndex, m_TimeStep));
148  }
149 
150  // this image is modified (good to know for the renderer)
151  input->Modified();
152 
153  if (interpolator)
154  {
155  interpolator->BlockModified(false);
156  }
157 }
158 
159 // basically copied from mitk/Core/Algorithms/mitkImageAccessByItk.h
160 #define myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, pixeltype, dimension, itkimage2) \
161  if (typeId == MapPixelComponentType<pixeltype>::value) \
162  \
163 { \
164  typedef itk::Image<pixeltype, dimension> ImageType; \
165  typedef mitk::ImageToItk<ImageType> ImageToItkType; \
166  itk::SmartPointer<ImageToItkType> imagetoitk = ImageToItkType::New(); \
167  const mitk::Image *constImage = mitkImage; \
168  mitk::Image *nonConstImage = const_cast<mitk::Image *>(constImage); \
169  nonConstImage->Update(); \
170  imagetoitk->SetInput(nonConstImage); \
171  imagetoitk->Update(); \
172  itkImageTypeFunction(imagetoitk->GetOutput(), itkimage2); \
173  \
174 }
175 
176 #define myMITKOverwriteSliceImageFilterAccessAllTypesByItk(mitkImage, itkImageTypeFunction, dimension, itkimage2) \
177  \
178 { \
179  myMITKOverwriteSliceImageFilterAccessByItk( \
180  mitkImage, \
181  itkImageTypeFunction, \
182  double, \
183  dimension, \
184  itkimage2) else myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, \
185  itkImageTypeFunction, \
186  float, \
187  dimension, \
188  itkimage2) else myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, int, dimension, itkimage2) else myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned int, dimension, itkimage2) else myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, \
189  itkImageTypeFunction, \
190  short, \
191  dimension, \
192  itkimage2) else myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned short, dimension, itkimage2) else myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, \
193  itkImageTypeFunction, \
194  char, \
195  dimension, \
196  itkimage2) else myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, \
197  itkImageTypeFunction, \
198  unsigned char, \
199  dimension, \
200  itkimage2) \
201  \
202 }
203 
204 template <typename TPixel, unsigned int VImageDimension>
205 void mitk::OverwriteSliceImageFilter::ItkImageSwitch(itk::Image<TPixel, VImageDimension> *itkImage)
206 {
207  const int typeId = m_SliceImage->GetPixelType().GetComponentType();
208 
209  myMITKOverwriteSliceImageFilterAccessAllTypesByItk(m_SliceImage, ItkImageProcessing, 2, itkImage);
210 }
211 
212 template <typename TPixel1, unsigned int VImageDimension1, typename TPixel2, unsigned int VImageDimension2>
213 void mitk::OverwriteSliceImageFilter::ItkImageProcessing(const itk::Image<TPixel1, VImageDimension1> *inputImage,
214  itk::Image<TPixel2, VImageDimension2> *outputImage)
215 {
216  typedef itk::Image<TPixel1, VImageDimension1> SliceImageType;
217  typedef itk::Image<short signed int, VImageDimension1> DiffImageType;
218  typedef itk::Image<TPixel2, VImageDimension2> VolumeImageType;
219 
220  typedef itk::ImageSliceIteratorWithIndex<VolumeImageType> OutputSliceIteratorType;
221  typedef itk::ImageRegionConstIterator<SliceImageType> InputSliceIteratorType;
222  typedef itk::ImageRegionIterator<DiffImageType> DiffSliceIteratorType;
223 
224  typename VolumeImageType::RegionType sliceInVolumeRegion;
225 
226  sliceInVolumeRegion = outputImage->GetLargestPossibleRegion();
227  sliceInVolumeRegion.SetSize(m_SliceDimension, 1); // just one slice
228  sliceInVolumeRegion.SetIndex(m_SliceDimension, m_SliceIndex); // exactly this slice, please
229 
230  OutputSliceIteratorType outputIterator(outputImage, sliceInVolumeRegion);
231  outputIterator.SetFirstDirection(m_Dimension0);
232  outputIterator.SetSecondDirection(m_Dimension1);
233 
234  InputSliceIteratorType inputIterator(inputImage, inputImage->GetLargestPossibleRegion());
235 
236  typename DiffImageType::Pointer diffImage;
237  CastToItkImage(m_SliceDifferenceImage, diffImage);
238  DiffSliceIteratorType diffIterator(diffImage, diffImage->GetLargestPossibleRegion());
239 
240  // iterate over output slice (and over input slice simultaneously)
241  outputIterator.GoToBegin();
242  inputIterator.GoToBegin();
243  diffIterator.GoToBegin();
244  while (!outputIterator.IsAtEnd())
245  {
246  while (!outputIterator.IsAtEndOfSlice())
247  {
248  while (!outputIterator.IsAtEndOfLine())
249  {
250  diffIterator.Set(static_cast<short signed int>(inputIterator.Get() -
251  outputIterator.Get())); // oh oh, not good for bigger values
252  outputIterator.Set((TPixel2)inputIterator.Get());
253  ++outputIterator;
254  ++inputIterator;
255  ++diffIterator;
256  }
257  outputIterator.NextLine();
258  }
259  outputIterator.NextSlice();
260  }
261 }
262 
263 std::string mitk::OverwriteSliceImageFilter::EventDescription(unsigned int sliceDimension,
264  unsigned int sliceIndex,
265  unsigned int timeStep)
266 {
267  std::stringstream s;
268 
269  s << "Changed slice (";
270 
271  switch (sliceDimension)
272  {
273  default:
274  case 2:
275  s << "T";
276  break;
277  case 1:
278  s << "C";
279  break;
280  case 0:
281  s << "S";
282  break;
283  }
284 
285  s << " " << sliceIndex << " " << timeStep << ")";
286 
287  return s.str();
288 }
void ItkImageProcessing(const itk::Image< TPixel1, VImageDimension1 > *itkImage1, itk::Image< TPixel2, VImageDimension2 > *itkImage2)
Operation, that holds information about some image difference.
itk::SmartPointer< Self > Pointer
#define AccessFixedDimensionByItk(mitkImage, itkImageTypeFunction, dimension)
Access a mitk-image with known dimension by an itk-image.
void SetChangedSlice(const Image *sliceDiff, unsigned int sliceDimension, unsigned int sliceIndex, unsigned int timeStep)
Update after changing a single slice.
Constants for most interaction classes, due to the generic StateMachines.
void BlockModified(bool)
Block reaction to an images Modified() events.
#define myMITKOverwriteSliceImageFilterAccessAllTypesByItk(mitkImage, itkImageTypeFunction, dimension, itkimage2)
static DiffImageApplier * GetInstanceForUndo()
#define MITK_WARN
Definition: mitkLogMacros.h:23
std::string EventDescription(unsigned int sliceDimension, unsigned int sliceIndex, unsigned int timeStep)
virtual void GenerateData() override
A version of GenerateData() specific for image processing filters.
static SegmentationInterpolationController * InterpolatorForImage(const Image *)
Find interpolator for a given image.
static Pointer New()
InputImageType * GetInput(void)
void MITKCORE_EXPORT CastToItkImage(const mitk::Image *mitkImage, itk::SmartPointer< ItkOutputImageType > &itkOutputImage)
Cast an mitk::Image to an itk::Image with a specific type.
virtual bool SetOperationEvent(UndoStackItem *stackItem)=0
static UndoModel * GetCurrentUndoModel()
gives access to the currently used UndoModel Introduced to access special functions of more specific ...
static void IncCurrObjectEventId()
Increases the current ObjectEventId For example if a button click generates operations the ObjectEven...
void ItkImageSwitch(itk::Image< TPixel, VImageDimension > *image)
Represents a pair of operations: undo and the according redo.
static Pointer New()
Class for defining the data type of pixels.
Definition: mitkPixelType.h:55