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
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