Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
mitkExtractSliceFilter2.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 
14 #include <mitkExceptionMacro.h>
15 #include <mitkImageAccessByItk.h>
16 #include <mitkImageWriteAccessor.h>
17 
18 #include <itkBSplineInterpolateImageFunction.h>
19 #include <itkLinearInterpolateImageFunction.h>
20 #include <itkNearestNeighborInterpolateImageFunction.h>
21 
22 #include <limits>
23 
24 struct mitk::ExtractSliceFilter2::Impl
25 {
26  Impl();
27  ~Impl();
28 
29  PlaneGeometry::Pointer OutputGeometry;
31  itk::Object::Pointer InterpolateImageFunction;
32 };
33 
34 mitk::ExtractSliceFilter2::Impl::Impl()
36 {
37 }
38 
39 mitk::ExtractSliceFilter2::Impl::~Impl()
40 {
41 }
42 
43 namespace
44 {
45  template <class TInputImage>
46  void CreateInterpolateImageFunction(const TInputImage* inputImage, mitk::ExtractSliceFilter2::Interpolator interpolator, itk::Object::Pointer& result)
47  {
48  typename itk::InterpolateImageFunction<TInputImage>::Pointer interpolateImageFunction;
49 
50  switch (interpolator)
51  {
53  interpolateImageFunction = itk::NearestNeighborInterpolateImageFunction<TInputImage>::New().GetPointer();
54  break;
55 
57  interpolateImageFunction = itk::LinearInterpolateImageFunction<TInputImage>::New().GetPointer();
58  break;
59 
61  {
62  auto bSplineInterpolateImageFunction = itk::BSplineInterpolateImageFunction<TInputImage>::New();
63  bSplineInterpolateImageFunction->SetSplineOrder(2);
64  interpolateImageFunction = bSplineInterpolateImageFunction.GetPointer();
65  break;
66  }
67 
68  default:
69  mitkThrow() << "Interplator is unknown.";
70  }
71 
72  interpolateImageFunction->SetInputImage(inputImage);
73 
74  result = interpolateImageFunction.GetPointer();
75  }
76 
77  template <typename TPixel, unsigned int VImageDimension>
78  void GenerateData(const itk::Image<TPixel, VImageDimension>* inputImage, mitk::Image* outputImage, const mitk::ExtractSliceFilter2::OutputImageRegionType& outputRegion, itk::Object* interpolateImageFunction)
79  {
80  typedef itk::Image<TPixel, VImageDimension> TInputImage;
81  typedef itk::InterpolateImageFunction<TInputImage> TInterpolateImageFunction;
82 
83  auto outputGeometry = outputImage->GetSlicedGeometry()->GetPlaneGeometry(0);
84  auto interpolator = static_cast<TInterpolateImageFunction*>(interpolateImageFunction);
85 
86  auto origin = outputGeometry->GetOrigin();
87  auto spacing = outputGeometry->GetSpacing();
88  auto xDirection = outputGeometry->GetAxisVector(0);
89  auto yDirection = outputGeometry->GetAxisVector(1);
90 
91  xDirection.Normalize();
92  yDirection.Normalize();
93 
94  auto spacingAlongXDirection = xDirection * spacing[0];
95  auto spacingAlongYDirection = yDirection * spacing[1];
96 
97  const std::size_t pixelSize = outputImage->GetPixelType().GetSize();
98  const std::size_t width = outputGeometry->GetExtent(0);
99  const std::size_t xBegin = outputRegion.GetIndex(0);
100  const std::size_t yBegin = outputRegion.GetIndex(1);
101  const std::size_t xEnd = xBegin + outputRegion.GetSize(0);
102  const std::size_t yEnd = yBegin + outputRegion.GetSize(1);
103 
104  mitk::ImageWriteAccessor writeAccess(outputImage, nullptr, mitk::ImageAccessorBase::IgnoreLock);
105  auto data = static_cast<char*>(writeAccess.GetData());
106 
107  const TPixel backgroundPixel = std::numeric_limits<TPixel>::lowest();
108  TPixel pixel;
109 
110  itk::ContinuousIndex<mitk::ScalarType, 3> index;
111  mitk::Point3D yPoint;
112  mitk::Point3D point;
113 
114  for (std::size_t y = yBegin; y < yEnd; ++y)
115  {
116  yPoint = origin + spacingAlongYDirection * y;
117 
118  for (std::size_t x = xBegin; x < xEnd; ++x)
119  {
120  point = yPoint + spacingAlongXDirection * x;
121 
122  if (inputImage->TransformPhysicalPointToContinuousIndex(point, index))
123  {
124  pixel = interpolator->EvaluateAtContinuousIndex(index);
125  memcpy(static_cast<void*>(data + pixelSize * (width * y + x)), static_cast<const void*>(&pixel), pixelSize);
126  }
127  else
128  {
129  memcpy(static_cast<void*>(data + pixelSize * (width * y + x)), static_cast<const void*>(&backgroundPixel), pixelSize);
130  }
131  }
132  }
133  }
134 
135  void VerifyInputImage(const mitk::Image* inputImage)
136  {
137  auto dimension = inputImage->GetDimension();
138 
139  if (3 != dimension)
140  mitkThrow() << "Input images with " << dimension << " dimensions are not supported.";
141 
142  if (!inputImage->IsInitialized())
143  mitkThrow() << "Input image is not initialized.";
144 
145  if (!inputImage->IsVolumeSet())
146  mitkThrow() << "Input image volume is not set.";
147 
148  auto geometry = inputImage->GetGeometry();
149 
150  if (nullptr == geometry || !geometry->IsValid())
151  mitkThrow() << "Input image has invalid geometry.";
152 
153  if (!geometry->GetImageGeometry())
154  mitkThrow() << "Geometry of input image is not an image geometry.";
155  }
156 
157  void VerifyOutputGeometry(const mitk::PlaneGeometry* outputGeometry)
158  {
159  if (nullptr == outputGeometry)
160  mitkThrow() << "Output geometry is not set.";
161 
162  if (!outputGeometry->GetImageGeometry())
163  mitkThrow() << "Output geometry is not an image geometry.";
164  }
165 }
166 
167 mitk::ExtractSliceFilter2::ExtractSliceFilter2()
168  : m_Impl(new Impl)
169 {
170 }
171 
172 mitk::ExtractSliceFilter2::~ExtractSliceFilter2()
173 {
174  delete m_Impl;
175 }
176 
177 void mitk::ExtractSliceFilter2::AllocateOutputs()
178 {
179  const auto* inputImage = this->GetInput();
180  const auto* outputGeometry = this->GetOutputGeometry();
181  auto outputImage = this->GetOutput();
182  auto pixelType = inputImage->GetPixelType();
183 
184  outputImage->Initialize(pixelType, 1, *outputGeometry);
185 
186  auto data = new char[static_cast<std::size_t>(pixelType.GetSize() * outputGeometry->GetExtent(0) * outputGeometry->GetExtent(1))];
187 
188  try
189  {
190  if (!outputImage->SetImportVolume(data, 0, 0, mitk::Image::ReferenceMemory))
191  throw;
192  }
193  catch (...)
194  {
195  delete[] data;
196  }
197 }
198 
199 /*void mitk::ExtractSliceFilter2::BeforeThreadedGenerateData()
200 {
201  if (nullptr != m_Impl->InterpolateImageFunction && this->GetInput()->GetMTime() < this->GetMTime())
202  return;
203 
204  const auto* inputImage = this->GetInput();
205  AccessFixedDimensionByItk_2(inputImage, CreateInterpolateImageFunction, 3, this->GetInterpolator(), m_Impl->InterpolateImageFunction);
206 }
207 
208 void mitk::ExtractSliceFilter2::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType)
209 {
210  const auto* inputImage = this->GetInput();
211  AccessFixedDimensionByItk_3(inputImage, ::GenerateData, 3, this->GetOutput(), outputRegionForThread, m_Impl->InterpolateImageFunction);
212 }*/
213 
214 void mitk::ExtractSliceFilter2::GenerateData()
215 {
216  if (nullptr != m_Impl->InterpolateImageFunction && this->GetInput()->GetMTime() < this->GetMTime())
217  return;
218 
219  const auto* inputImage = this->GetInput();
220 
221  AccessFixedDimensionByItk_2(inputImage, CreateInterpolateImageFunction, 3, this->GetInterpolator(), m_Impl->InterpolateImageFunction);
222 
223  this->AllocateOutputs();
224  auto outputRegion = this->GetOutput()->GetLargestPossibleRegion();
225 
226  AccessFixedDimensionByItk_3(inputImage, ::GenerateData, 3, this->GetOutput(), outputRegion, m_Impl->InterpolateImageFunction);
227 }
228 
230 {
231  if (this->GetInput() == image)
232  return;
233 
234  Superclass::SetInput(image);
235  m_Impl->InterpolateImageFunction = nullptr;
236 }
237 
239 {
240  if (0 != index)
241  mitkThrow() << "Input index " << index << " is invalid.";
242 
243  this->SetInput(image);
244 }
245 
247 {
248  return m_Impl->OutputGeometry;
249 }
250 
252 {
253  if (m_Impl->OutputGeometry != outputGeometry)
254  {
255  m_Impl->OutputGeometry = outputGeometry;
256  this->Modified();
257  }
258 }
259 
261 {
262  return m_Impl->Interpolator;
263 }
264 
266 {
267  if (m_Impl->Interpolator != interpolator)
268  {
269  m_Impl->Interpolator = interpolator;
270  m_Impl->InterpolateImageFunction = nullptr;
271  this->Modified();
272  }
273 }
274 
275 void mitk::ExtractSliceFilter2::VerifyInputInformation()
276 {
277  Superclass::VerifyInputInformation();
278 
279  VerifyInputImage(this->GetInput());
280  VerifyOutputGeometry(this->GetOutputGeometry());
281 }
virtual bool GetImageGeometry() const
Is this an ImageGeometry?
virtual void Initialize(const mitk::PixelType &type, unsigned int dimension, const unsigned int *dimensions, unsigned int channels=1)
Definition: mitkImage.cpp:838
const mitk::PixelType GetPixelType(int n=0) const
Returns the PixelType of channel n.
Definition: mitkImage.cpp:101
void SetInterpolator(Interpolator interpolator)
bool IsVolumeSet(int t=0, int n=0) const override
Check whether volume at time t in channel n is set.
Definition: mitkImage.cpp:602
virtual void SetInput(const InputImageType *image)
ScalarType GetExtent(unsigned int direction) const
Set the time bounds (in ms)
SlicedData::RegionType OutputImageRegionType
const PlaneGeometry * GetOutputGeometry() const
#define AccessFixedDimensionByItk_3(mitkImage, itkImageTypeFunction, dimension, arg1, arg2, arg3)
virtual mitk::PlaneGeometry * GetPlaneGeometry(int s) const
Returns the PlaneGeometry of the slice (s).
void SetOutputGeometry(PlaneGeometry::Pointer outputGeometry)
itk::SmartPointer< Self > Pointer
void SetInput(const InputImageType *image) override
unsigned int GetDimension() const
Get dimension of the image.
Definition: mitkImage.cpp:106
#define AccessFixedDimensionByItk_2(mitkImage, itkImageTypeFunction, dimension, arg1, arg2)
#define mitkThrow()
Image class for storing images.
Definition: mitkImage.h:72
virtual bool SetImportVolume(void *data, int t=0, int n=0, ImportMemoryManagementType importMemoryManagement=CopyMemory)
Set data as volume at time t in channel n. It is in the responsibility of the caller to ensure that t...
Definition: mitkImage.cpp:716
SlicedGeometry3D * GetSlicedGeometry(unsigned int t=0) const
Convenience access method for the geometry, which is of type SlicedGeometry3D (or a sub-class of it)...
mitk::Image::Pointer image
const Point3D GetOrigin() const
Get the origin, e.g. the upper-left corner of the plane.
vcl_size_t GetSize() const
Get size of the PixelType in bytes.
InputImageType * GetInput(void)
virtual bool IsInitialized() const
Check whether the data has been initialized, i.e., at least the Geometry and other header data has be...
virtual void AllocateOutputs()
The GenerateData method normally allocates the buffers for all of the outputs of a filter...
OutputType * GetOutput()
Get the output data of this image source object.
ImageWriteAccessor class to get locked write-access for a particular image part.
Describes a two-dimensional, rectangular plane.
mitk::BaseGeometry * GetGeometry(int t=0) const
Return the geometry, which is a TimeGeometry, of the data as non-const pointer.
Definition: mitkBaseData.h:138
static itk::InterpolateImageFunction< TInputImage >::Pointer CreateInterpolateImageFunction(InterpolateImageFunction::Enum interpolator)