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