1 /*============================================================================
3 The Medical Imaging Interaction Toolkit (MITK)
5 Copyright (c) German Cancer Research Center (DKFZ)
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
11 ============================================================================*/
13 #ifndef MITKBOUNDINGOBJECTCUTTER_TXX
14 #define MITKBOUNDINGOBJECTCUTTER_TXX
16 #include "itkImageRegionIteratorWithIndex.h"
17 #include "mitkImageToItk.h"
18 #include "mitkStatusBar.h"
22 template <typename TPixel, unsigned int VImageDimension, typename TOutputPixel>
23 void CutImageWithOutputTypeSelect(itk::Image<TPixel, VImageDimension> *inputItkImage,
24 mitk::BoundingObjectCutter *cutter,
26 TOutputPixel * /* dummy */)
28 typedef itk::Image<TPixel, VImageDimension> ItkInputImageType;
29 typedef itk::Image<TOutputPixel, VImageDimension> ItkOutputImageType;
30 typedef typename itk::ImageBase<VImageDimension>::RegionType ItkRegionType;
31 typedef itk::ImageRegionIteratorWithIndex<ItkInputImageType> ItkInputImageIteratorType;
32 typedef itk::ImageRegionIteratorWithIndex<ItkOutputImageType> ItkOutputImageIteratorType;
34 if (cutter->m_BoundingObject.IsNull())
37 if (inputItkImage == nullptr)
39 mitk::StatusBar::GetInstance()->DisplayErrorText(
40 "An internal error occurred. Can't convert Image. Please report to bugs@mitk.org");
41 std::cout << " image is NULL...returning" << std::endl;
45 // PART 1: convert m_InputRequestedReg ion (type mitk::SlicedData::RegionType)
46 // into ITK-image-region (ItkImageType::RegionType)
47 // unfortunately, we cannot use input->GetRequestedRegion(), because it
48 // has been destroyed by the mitk::CastToItkImage call of PART 1
49 // (which sets the m_RequestedRegion to the LargestPossibleRegion).
50 // Thus, use our own member m_InputRequestedRegion insead.
52 // first convert the index
53 typename ItkRegionType::IndexType::IndexValueType tmpIndex[3];
54 itk2vtk(cutter->m_InputRequestedRegion.GetIndex(), tmpIndex);
55 typename ItkRegionType::IndexType index;
56 index.SetIndex(tmpIndex);
58 // then convert the size
59 typename ItkRegionType::SizeType::SizeValueType tmpSize[3];
60 itk2vtk(cutter->m_InputRequestedRegion.GetSize(), tmpSize);
61 typename ItkRegionType::SizeType size;
62 size.SetSize(tmpSize);
64 // create the ITK-image-region out of index and size
65 ItkRegionType inputRegionOfInterest(index, size);
67 // PART 2: get access to the MITK output image via an ITK image
68 typename mitk::ImageToItk<ItkOutputImageType>::Pointer outputimagetoitk =
69 mitk::ImageToItk<ItkOutputImageType>::New();
70 outputimagetoitk->SetInput(cutter->m_OutputTimeSelector->GetOutput());
71 outputimagetoitk->Update();
72 typename ItkOutputImageType::Pointer outputItkImage = outputimagetoitk->GetOutput();
74 // PART 3: iterate over input and output using ITK iterators
76 // create the iterators
77 ItkInputImageIteratorType inputIt(inputItkImage, inputRegionOfInterest);
78 ItkOutputImageIteratorType outputIt(outputItkImage, outputItkImage->GetLargestPossibleRegion());
80 // Cut the boundingbox out of the image by iterating through
81 // all pixels and checking if they are inside using IsInside()
82 cutter->m_OutsidePixelCount = 0;
83 cutter->m_InsidePixelCount = 0;
85 mitk::BaseGeometry *inputGeometry = cutter->GetInput()->GetGeometry();
87 TOutputPixel outsideValue;
88 if (cutter->m_AutoOutsideValue)
90 outsideValue = itk::NumericTraits<TOutputPixel>::min();
94 outsideValue = (TOutputPixel)cutter->m_OutsideValue;
96 // shall we use a fixed value for each inside pixel?
97 if (cutter->GetUseInsideValue())
99 TOutputPixel insideValue = (TOutputPixel)cutter->m_InsideValue;
100 // yes, use a fixed value for each inside pixel (create a binary mask of the bounding object)
101 for (inputIt.GoToBegin(), outputIt.GoToBegin(); !inputIt.IsAtEnd(); ++inputIt, ++outputIt)
103 vtk2itk(inputIt.GetIndex(), p);
104 inputGeometry->IndexToWorld(p, p);
105 if (cutter->m_BoundingObject->IsInside(p))
107 outputIt.Set(insideValue);
108 ++cutter->m_InsidePixelCount;
112 outputIt.Set(outsideValue);
113 ++cutter->m_OutsidePixelCount;
119 // no, use the pixel value of the original image (normal cutting)
120 for (inputIt.GoToBegin(), outputIt.GoToBegin(); !inputIt.IsAtEnd(); ++inputIt, ++outputIt)
122 vtk2itk(inputIt.GetIndex(), p);
123 inputGeometry->IndexToWorld(p, p);
124 if (cutter->m_BoundingObject->IsInside(p))
126 outputIt.Set((TOutputPixel)inputIt.Value());
127 ++cutter->m_InsidePixelCount;
131 outputIt.Set(outsideValue);
132 ++cutter->m_OutsidePixelCount;
138 template <typename TPixel, unsigned int VImageDimension, typename TOutputPixel>
139 void CutImageWithOutputTypeSelect(itk::VectorImage<TPixel, VImageDimension> *inputItkImage,
140 mitk::BoundingObjectCutter *cutter,
141 int /* boTimeStep */,
142 TOutputPixel * /* dummy */)
144 typedef itk::VectorImage<TPixel, VImageDimension> ItkInputImageType;
145 typedef itk::VectorImage<TOutputPixel, VImageDimension> ItkOutputImageType;
146 typedef typename itk::ImageBase<VImageDimension>::RegionType ItkRegionType;
147 typedef itk::ImageRegionIteratorWithIndex<ItkInputImageType> ItkInputImageIteratorType;
148 typedef itk::ImageRegionIteratorWithIndex<ItkOutputImageType> ItkOutputImageIteratorType;
150 if (cutter->m_BoundingObject.IsNull())
153 if (inputItkImage == nullptr)
155 mitk::StatusBar::GetInstance()->DisplayErrorText(
156 "An internal error occurred. Can't convert Image. Please report to bugs@mitk.org");
157 std::cout << " image is NULL...returning" << std::endl;
161 // PART 1: convert m_InputRequestedReg ion (type mitk::SlicedData::RegionType)
162 // into ITK-image-region (ItkImageType::RegionType)
163 // unfortunately, we cannot use input->GetRequestedRegion(), because it
164 // has been destroyed by the mitk::CastToItkImage call of PART 1
165 // (which sets the m_RequestedRegion to the LargestPossibleRegion).
166 // Thus, use our own member m_InputRequestedRegion insead.
168 // first convert the index
169 typename ItkRegionType::IndexType::IndexValueType tmpIndex[3];
170 itk2vtk(cutter->m_InputRequestedRegion.GetIndex(), tmpIndex);
171 typename ItkRegionType::IndexType index;
172 index.SetIndex(tmpIndex);
174 // then convert the size
175 typename ItkRegionType::SizeType::SizeValueType tmpSize[3];
176 itk2vtk(cutter->m_InputRequestedRegion.GetSize(), tmpSize);
177 typename ItkRegionType::SizeType size;
178 size.SetSize(tmpSize);
180 // create the ITK-image-region out of index and size
181 ItkRegionType inputRegionOfInterest(index, size);
183 // PART 2: get access to the MITK output image via an ITK image
184 typename mitk::ImageToItk<ItkOutputImageType>::Pointer outputimagetoitk =
185 mitk::ImageToItk<ItkOutputImageType>::New();
186 outputimagetoitk->SetInput(cutter->m_OutputTimeSelector->GetOutput());
187 outputimagetoitk->Update();
188 typename ItkOutputImageType::Pointer outputItkImage = outputimagetoitk->GetOutput();
190 // PART 3: iterate over input and output using ITK iterators
192 // create the iterators
193 ItkInputImageIteratorType inputIt(inputItkImage, inputRegionOfInterest);
194 ItkOutputImageIteratorType outputIt(outputItkImage, outputItkImage->GetLargestPossibleRegion());
196 // Cut the boundingbox out of the image by iterating through
197 // all pixels and checking if they are inside using IsInside()
198 cutter->m_OutsidePixelCount = 0;
199 cutter->m_InsidePixelCount = 0;
201 mitk::BaseGeometry *inputGeometry = cutter->GetInput()->GetGeometry();
203 typename ItkOutputImageType::PixelType outsideValue;
204 outsideValue.SetSize(outputItkImage->GetVectorLength());
205 if (cutter->m_AutoOutsideValue)
207 outsideValue.Fill(itk::NumericTraits<TOutputPixel>::min());
211 outsideValue.Fill(cutter->m_OutsideValue);
213 // shall we use a fixed value for each inside pixel?
214 if (cutter->GetUseInsideValue())
216 typename ItkOutputImageType::PixelType insideValue;
217 insideValue.Fill(cutter->m_InsideValue);
218 // yes, use a fixed value for each inside pixel (create a binary mask of the bounding object)
219 for (inputIt.GoToBegin(), outputIt.GoToBegin(); !inputIt.IsAtEnd(); ++inputIt, ++outputIt)
221 vtk2itk(inputIt.GetIndex(), p);
222 inputGeometry->IndexToWorld(p, p);
223 if (cutter->m_BoundingObject->IsInside(p))
225 outputIt.Set(insideValue);
226 ++cutter->m_InsidePixelCount;
230 outputIt.Set(outsideValue);
231 ++cutter->m_OutsidePixelCount;
237 // no, use the pixel value of the original image (normal cutting)
238 for (inputIt.GoToBegin(), outputIt.GoToBegin(); !inputIt.IsAtEnd(); ++inputIt, ++outputIt)
240 vtk2itk(inputIt.GetIndex(), p);
241 inputGeometry->IndexToWorld(p, p);
242 if (cutter->m_BoundingObject->IsInside(p))
244 outputIt.Set(inputIt.Get());
245 ++cutter->m_InsidePixelCount;
249 outputIt.Set(outsideValue);
250 ++cutter->m_OutsidePixelCount;
256 template <typename TPixel, unsigned int VImageDimension>
257 void CutImage(itk::Image<TPixel, VImageDimension> *inputItkImage, mitk::BoundingObjectCutter *cutter, int boTimeStep)
259 TPixel *dummy = nullptr;
260 CutImageWithOutputTypeSelect<TPixel, VImageDimension, TPixel>(inputItkImage, cutter, boTimeStep, dummy);
263 template <typename TPixel, unsigned int VImageDimension>
264 void CutImage(itk::VectorImage<TPixel, VImageDimension> *inputItkImage,
265 mitk::BoundingObjectCutter *cutter,
268 TPixel *dummy = nullptr;
269 CutImageWithOutputTypeSelect<TPixel, VImageDimension, TPixel>(inputItkImage, cutter, boTimeStep, dummy);
272 } // of namespace mitk
274 #include "mitkImageCast.h"
276 #endif // of MITKBOUNDINGOBJECTCUTTER_TXX