|
21 | 21 | #include "itkOutputImage.h" |
22 | 22 | #include "itkSupportInputImageTypes.h" |
23 | 23 |
|
| 24 | +#include "itkContinuousIndex.h" |
24 | 25 | #include "itkDiscreteGaussianImageFilter.h" |
25 | 26 | #include "itkLinearInterpolateImageFunction.h" |
26 | 27 | #include "itkResampleImageFilter.h" |
@@ -94,21 +95,24 @@ DownsampleScalarImage(itk::wasm::Pipeline & pipeline, const TImage * inputImage) |
94 | 95 | gaussianFilter->SetSigmaArray(sigmaArray); |
95 | 96 | gaussianFilter->SetUseImageSpacingOff(); |
96 | 97 |
|
97 | | - const auto inputOrigin = inputImage->GetOrigin(); |
98 | 98 | const auto inputSpacing = inputImage->GetSpacing(); |
99 | 99 | const auto inputSize = inputImage->GetLargestPossibleRegion().GetSize(); |
| 100 | + const auto inputStartIndex = inputImage->GetLargestPossibleRegion().GetIndex(); |
100 | 101 |
|
101 | | - typename ImageType::PointType outputOrigin; |
102 | | - typename ImageType::SpacingType outputSpacing; |
103 | | - typename ImageType::SizeType outputSize; |
| 102 | + typename ImageType::PointType outputOrigin; |
| 103 | + typename ImageType::SpacingType outputSpacing; |
| 104 | + typename ImageType::SizeType outputSize; |
| 105 | + itk::ContinuousIndex<double, ImageDimension> outputOriginIndex; |
104 | 106 | for (unsigned int i = 0; i < ImageDimension; ++i) |
105 | 107 | { |
106 | 108 | const double cropRadiusValue = cropRadius.size() ? cropRadius[i] : 0.0; |
107 | 109 |
|
108 | | - outputOrigin[i] = inputOrigin[i] + cropRadiusValue * inputSpacing[i]; |
| 110 | + // Origin lands at the center of the first bin, matching itk::BinShrinkImageFilter |
| 111 | + outputOriginIndex[i] = inputStartIndex[i] + cropRadiusValue + (shrinkFactors[i] - 1.0) / 2.0; |
109 | 112 | outputSpacing[i] = inputSpacing[i] * shrinkFactors[i]; |
110 | 113 | outputSize[i] = std::max<itk::SizeValueType>(0, (inputSize[i] - 2 * cropRadiusValue) / shrinkFactors[i]); |
111 | 114 | } |
| 115 | + inputImage->TransformContinuousIndexToPhysicalPoint(outputOriginIndex, outputOrigin); |
112 | 116 |
|
113 | 117 | using InterpolatorType = itk::LinearInterpolateImageFunction<ImageType, double>; |
114 | 118 | auto interpolator = InterpolatorType::New(); |
@@ -187,21 +191,24 @@ class PipelineFunctor<itk::VectorImage<TPixel, VDimension>> |
187 | 191 |
|
188 | 192 | auto sigmaValues = downsampleSigma(shrinkFactors); |
189 | 193 |
|
190 | | - const auto inputOrigin = inputImage.Get()->GetOrigin(); |
191 | 194 | const auto inputSpacing = inputImage.Get()->GetSpacing(); |
192 | 195 | const auto inputSize = inputImage.Get()->GetLargestPossibleRegion().GetSize(); |
| 196 | + const auto inputStartIndex = inputImage.Get()->GetLargestPossibleRegion().GetIndex(); |
193 | 197 |
|
194 | | - typename VectorImageType::PointType outputOrigin; |
195 | | - typename VectorImageType::SpacingType outputSpacing; |
196 | | - typename VectorImageType::SizeType outputSize; |
| 198 | + typename VectorImageType::PointType outputOrigin; |
| 199 | + typename VectorImageType::SpacingType outputSpacing; |
| 200 | + typename VectorImageType::SizeType outputSize; |
| 201 | + itk::ContinuousIndex<double, Dimension> outputOriginIndex; |
197 | 202 | for (unsigned int i = 0; i < Dimension; ++i) |
198 | 203 | { |
199 | 204 | const double cropRadiusValue = cropRadius.size() ? cropRadius[i] : 0.0; |
200 | 205 |
|
201 | | - outputOrigin[i] = inputOrigin[i] + cropRadiusValue * inputSpacing[i]; |
| 206 | + // Origin lands at the center of the first bin, matching itk::BinShrinkImageFilter |
| 207 | + outputOriginIndex[i] = inputStartIndex[i] + cropRadiusValue + (shrinkFactors[i] - 1.0) / 2.0; |
202 | 208 | outputSpacing[i] = inputSpacing[i] * shrinkFactors[i]; |
203 | 209 | outputSize[i] = std::max<itk::SizeValueType>(0, (inputSize[i] - 2 * cropRadiusValue) / shrinkFactors[i]); |
204 | 210 | } |
| 211 | + inputImage.Get()->TransformContinuousIndexToPhysicalPoint(outputOriginIndex, outputOrigin); |
205 | 212 |
|
206 | 213 | auto composeFilter = ComposeFilterType::New(); |
207 | 214 |
|
|
0 commit comments