21 #ifndef otbGridResampleImageFilter_hxx
22 #define otbGridResampleImageFilter_hxx
29 #include "itkNumericTraits.h"
30 #include "itkProgressReporter.h"
31 #include "itkImageScanlineIterator.h"
32 #include "itkContinuousIndex.h"
37 template <
typename TInputImage,
typename TOutputImage,
typename TInterpolatorPrecision>
39 : m_OutputStartIndex(),
44 m_InterpolationMargin(0.0),
45 m_CheckOutputBounds(true),
47 m_ReachableOutputRegion()
64 template <
typename TInputImage,
typename TOutputImage,
typename TInterpolatorPrecision>
67 this->SetOutputOrigin(image->GetOrigin());
69 this->SetOutputStartIndex(image->GetLargestPossibleRegion().GetIndex());
70 this->SetOutputSize(image->GetLargestPossibleRegion().GetSize());
74 template <
typename TInputImage,
typename TOutputImage,
typename TInterpolatorPrecision>
78 Superclass::GenerateOutputInformation();
88 typename TOutputImage::RegionType outputLargestPossibleRegion;
89 outputLargestPossibleRegion.SetSize(m_OutputSize);
90 outputLargestPossibleRegion.SetIndex(m_OutputStartIndex);
92 outputPtr->SetLargestPossibleRegion(outputLargestPossibleRegion);
93 outputPtr->SetSignedSpacing(m_OutputSpacing);
94 outputPtr->SetOrigin(m_OutputOrigin);
99 template <
typename TInputImage,
typename TOutputImage,
typename TInterpolatorPrecision>
103 Superclass::GenerateInputRequestedRegion();
106 if (!this->GetInput())
112 typename TInputImage::Pointer inputPtr =
const_cast<TInputImage*
>(this->GetInput());
121 typename TOutputImage::RegionType outputRequestedRegion = outputPtr->GetRequestedRegion();
125 typedef itk::ContinuousIndex<double, TInputImage::ImageDimension> ContinuousIndexType;
127 ContinuousIndexType inULCIndex, inLRCIndex;
130 outULIndex = outputRequestedRegion.GetIndex();
131 outLRIndex = outULIndex + outputRequestedRegion.GetSize();
137 outputPtr->TransformIndexToPhysicalPoint(outULIndex, outULPoint);
138 outputPtr->TransformIndexToPhysicalPoint(outLRIndex, outLRPoint);
141 inputPtr->TransformPhysicalPointToContinuousIndex(outULPoint, inULCIndex);
142 inputPtr->TransformPhysicalPointToContinuousIndex(outLRPoint, inLRCIndex);
148 for (
unsigned int dim = 0; dim < ImageDimension; ++dim)
150 if (inULCIndex[dim] > inLRCIndex[dim])
153 typename ContinuousIndexType::ValueType tmp(inULCIndex[dim]);
154 inULCIndex[dim] = inLRCIndex[dim];
155 inLRCIndex[dim] = tmp;
160 inULIndex[dim] = std::floor(inULCIndex[dim]);
161 inLRIndex[dim] = std::ceil(inLRCIndex[dim]);
163 inSize[dim] =
static_cast<typename SizeType::SizeValueType
>(inLRIndex[dim] - inULIndex[dim]) + 1;
167 typename TInputImage::RegionType inputRequestedRegion;
168 inputRequestedRegion.SetIndex(inULIndex);
169 inputRequestedRegion.SetSize(inSize);
173 inputRequestedRegion.PadByRadius(interpolatorRadius);
176 if (inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()))
178 inputPtr->SetRequestedRegion(inputRequestedRegion);
184 inputPtr->SetRequestedRegion(inputRequestedRegion);
187 itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
188 e.SetLocation(ITK_LOCATION);
189 e.SetDescription(
"Requested region is (at least partially) outside the largest possible region.");
190 e.SetDataObject(inputPtr);
196 template <
typename TInputImage,
typename TOutputImage,
typename TInterpolatorPrecision>
201 itkExceptionMacro(<<
"Interpolator not set");
205 m_Interpolator->SetInputImage(this->GetInput());
210 if (nComponents == 0)
216 nComponents = this->GetInput()->GetNumberOfComponentsPerPixel();
218 itk::NumericTraits<OutputPixelType>::SetLength(m_EdgePaddingValue, nComponents);
219 for (
unsigned int n = 0; n < nComponents; n++)
221 OutputPixelConvertType::SetNthComponent(n, m_EdgePaddingValue, zeroComponent);
232 IndexType inUL = this->GetInput()->GetBufferedRegion().GetIndex();
233 IndexType inLR = this->GetInput()->GetBufferedRegion().GetIndex() + this->GetInput()->GetBufferedRegion().GetSize();
247 this->GetInput()->TransformIndexToPhysicalPoint(inUL, inULp);
248 this->GetInput()->TransformIndexToPhysicalPoint(inLR, inLRp);
250 inULp -= (0.5 - m_InterpolationMargin) * this->GetInput()->GetSignedSpacing();
251 inLRp += (0.5 - m_InterpolationMargin) * this->GetInput()->GetSignedSpacing();
255 this->GetOutput()->TransformPhysicalPointToContinuousIndex(inULp, outUL);
256 this->GetOutput()->TransformPhysicalPointToContinuousIndex(inLRp, outLR);
260 outputIndex[0] = std::ceil(std::min(outUL[0], outLR[0]));
261 outputIndex[1] = std::ceil(std::min(outUL[1], outLR[1]));
264 outputSize[0] = std::floor(std::max(outUL[0], outLR[0])) - outputIndex[0] + 1;
265 outputSize[1] = std::floor(std::max(outUL[1], outLR[1])) - outputIndex[1] + 1;
267 m_ReachableOutputRegion.SetIndex(outputIndex);
268 m_ReachableOutputRegion.SetSize(outputSize);
270 otbMsgDevMacro(<<
"ReachableOutputRegion: " << m_ReachableOutputRegion);
273 template <
typename TInputImage,
typename TOutputImage,
typename TInterpolatorPrecision>
275 itk::ThreadIdType threadId)
293 bool cropSucceed = regionToCompute.Crop(m_ReachableOutputRegion);
296 itk::ImageScanlineIterator<OutputImageType> outItFull(outputPtr, outputRegionForThread);
297 outItFull.GoToBegin();
298 while (!outItFull.IsAtEnd())
300 while (!outItFull.IsAtEndOfLine())
302 outItFull.Set(m_EdgePaddingValue);
305 outItFull.NextLine();
311 itk::ImageScanlineIterator<OutputImageType> outIt(outputPtr, regionToCompute);
314 itk::ProgressReporter progress(
this, threadId, regionToCompute.GetSize()[1]);
323 assert(outputPtr->GetSignedSpacing()[0] != 0 &&
"Null spacing will cause division by zero.");
324 const double delta = outputPtr->GetSignedSpacing()[0] / inputPtr->GetSignedSpacing()[0];
329 while (!outIt.IsAtEnd())
332 outputPtr->TransformIndexToPhysicalPoint(outIt.GetIndex(), outPoint);
333 inputPtr->TransformPhysicalPointToContinuousIndex(outPoint, inCIndex);
335 while (!outIt.IsAtEndOfLine())
338 interpolatorValue = m_Interpolator->EvaluateAtContinuousIndex(inCIndex);
341 this->CastPixelWithBoundsChecking(interpolatorValue, minOutputValue, maxOutputValue, outputValue);
344 outIt.Set(outputValue);
350 inCIndex[0] += delta;
354 progress.CompletedPixel();
361 template <
typename TInputImage,
typename TOutputImage,
typename TInterpolatorPrecision>
365 m_Interpolator->SetInputImage(
nullptr);
369 template <
typename TInputImage,
typename TOutputImage,
typename TInterpolatorPrecision>
372 itk::ModifiedTimeType latestTime = itk::Object::GetMTime();
376 if (latestTime < m_Interpolator->GetMTime())
378 latestTime = m_Interpolator->GetMTime();
386 template <
typename TInputImage,
typename TOutputImage,
typename TInterpolatorPrecision>
389 Superclass::PrintSelf(os, indent);
391 os << indent <<
"EdgePaddingValue: " <<
static_cast<typename itk::NumericTraits<OutputPixelType>::PrintType
>(m_EdgePaddingValue) << std::endl;
392 os << indent <<
"OutputStartIndex: " << m_OutputStartIndex << std::endl;
393 os << indent <<
"OutputSize: " << m_OutputSize << std::endl;
394 os << indent <<
"OutputOrigin: " << m_OutputOrigin << std::endl;
395 os << indent <<
"OutputSpacing: " << m_OutputSpacing << std::endl;
396 os << indent <<
"Interpolator: " << m_Interpolator.GetPointer() << std::endl;
397 os << indent <<
"CheckOutputBounds: " << (m_CheckOutputBounds ?
"On" :
"Off") << std::endl;