Skip to content

Commit 5032829

Browse files
authored
Merge pull request #5670 from blowekamp/cast_image_region_performance
PERF: Use tuned ImageRangeRegion copy in CastImageFilter
2 parents 4fcc20a + 2e8c70a commit 5032829

File tree

1 file changed

+20
-18
lines changed

1 file changed

+20
-18
lines changed

Modules/Filtering/ImageFilterBase/include/itkCastImageFilter.hxx

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include "itkProgressReporter.h"
2222
#include "itkImageAlgorithm.h"
23+
#include "itkImageRegionRange.h"
2324

2425
namespace itk
2526
{
@@ -139,29 +140,30 @@ CastImageFilter<TInputImage, TOutputImage>::DynamicThreadedGenerateDataDispatche
139140

140141
this->CallCopyOutputRegionToInputRegion(inputRegionForThread, outputRegionForThread);
141142

142-
const unsigned int componentsPerPixel = outputPtr->GetNumberOfComponentsPerPixel();
143+
ImageRegionRange<const TInputImage> inputRange(*inputPtr, inputRegionForThread);
144+
ImageRegionRange<TOutputImage> outputRange(*outputPtr, outputRegionForThread);
143145

144-
// Define the iterators
145-
ImageScanlineConstIterator inputIt(inputPtr, inputRegionForThread);
146-
ImageScanlineIterator outputIt(outputPtr, outputRegionForThread);
146+
auto inputIt = inputRange.begin();
147+
auto outputIt = outputRange.begin();
148+
const auto inputEnd = inputRange.end();
147149

148-
while (!inputIt.IsAtEnd())
150+
// Note: This loop has been timed for performance with conversions between image of vectors and VectorImages and other
151+
// combinations. The following was evaluated to be the best performance usage of iterators. Important considerations:
152+
// - Usage of NumericTraits::GetLength() is sometimes consant vs virutal method GetNumberOfComponentsPerPixel()
153+
// - The construction of inputPixel and outputPixel for VectorImages both reference the internal buffer and don't
154+
// require memory allocations.
155+
const unsigned int componentsPerPixel = itk::NumericTraits<OutputPixelType>::GetLength(*outputIt);
156+
while (inputIt != inputEnd)
149157
{
150-
while (!inputIt.IsAtEndOfLine())
158+
const InputPixelType & inputPixel = *inputIt;
159+
OutputPixelType outputPixel{ *outputIt };
160+
for (unsigned int k = 0; k < componentsPerPixel; ++k)
151161
{
152-
const InputPixelType & inputPixel = inputIt.Get();
153-
OutputPixelType value{ outputIt.Get() };
154-
for (unsigned int k = 0; k < componentsPerPixel; ++k)
155-
{
156-
value[k] = static_cast<typename OutputPixelType::ValueType>(inputPixel[k]);
157-
}
158-
outputIt.Set(value);
159-
160-
++inputIt;
161-
++outputIt;
162+
outputPixel[k] = static_cast<typename OutputPixelType::ValueType>(inputPixel[k]);
162163
}
163-
inputIt.NextLine();
164-
outputIt.NextLine();
164+
*outputIt = outputPixel;
165+
++inputIt;
166+
++outputIt;
165167
}
166168
}
167169

0 commit comments

Comments
 (0)