Skip to content

Commit b819ed6

Browse files
author
Simon Rit
committed
BUG: Fix CastImageFilter for VariableLengthVector
The `Get` function of `VectorImage` iterators calls the `VariableLengthVector` constructor parameterized by a const pointer and a vector length (see `DefaultVectorPixelAccessor::Get`). The `m_Data` pointer of the constructed VariableLengthVector which is returned is pointing to the returned pixel data. This was a problem in CastImageFitler. A `CastImageFilter` test has been added to reproduce the issue: when a `VectorImage` was casted to an `Image< Vector <`, the first pixel of the region was taking the value of the last pixel of the region. The test illustrated this by creating an image filled with 0 except the first pixel. The casted image was completely full of 0 before bug correction.
1 parent a8dd05b commit b819ed6

File tree

2 files changed

+46
-1
lines changed

2 files changed

+46
-1
lines changed

Modules/Filtering/ImageFilterBase/include/itkCastImageFilter.hxx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ CastImageFilter<TInputImage, TOutputImage>::DynamicThreadedGenerateDataDispatche
145145
ImageScanlineConstIterator inputIt(inputPtr, inputRegionForThread);
146146
ImageScanlineIterator outputIt(outputPtr, outputRegionForThread);
147147

148-
OutputPixelType value{ outputIt.Get() };
148+
itk::NumericTraits<typename OutputPixelType::ValueType> value[componentsPerPixel];
149149
while (!inputIt.IsAtEnd())
150150
{
151151
while (!inputIt.IsAtEndOfLine())

Modules/Filtering/ImageFilterBase/test/itkCastImageFilterTest.cxx

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,50 @@ TestVectorImageCast2()
400400
}
401401

402402

403+
bool
404+
TestVectorImageCast3()
405+
{
406+
// This function casts an Image<Vector<float, 3>, 3>
407+
// to a VectorImage<float, 3>
408+
std::cout << "Casting from an Image<Vector<float,3>, 3> to VectorImage<float, 3> ... ";
409+
410+
using VectorFloatImageType = itk::Image<itk::Vector<float, 3>, 3>;
411+
using FloatVectorImageType = itk::VectorImage<float, 3>;
412+
413+
// Create a 1x3 image of 2D vectors
414+
auto image = VectorFloatImageType::New();
415+
416+
constexpr itk::Size<3> size{ { 1, 1, 4 } };
417+
const itk::ImageRegion<3> region{ size };
418+
image->SetRegions(region);
419+
image->AllocateInitialized();
420+
VectorFloatImageType::PixelType vec{ { 1.3, 5.3, 6.4 } };
421+
// Only the first pixel will be the vector (1.3, 5.3, 6.4)
422+
image->SetPixel(itk::Index<3>(), vec);
423+
424+
using CastImageFilterType = itk::CastImageFilter<VectorFloatImageType, FloatVectorImageType>;
425+
auto castImageFilter = CastImageFilterType::New();
426+
castImageFilter->SetInput(image);
427+
castImageFilter->SetNumberOfWorkUnits(1);
428+
castImageFilter->Update();
429+
430+
bool success = true;
431+
if (std::memcmp(castImageFilter->GetOutput()->GetBufferPointer(),
432+
image->GetBufferPointer(),
433+
sizeof(float) * size.CalculateProductOfElements()) == 0)
434+
{
435+
std::cout << "[PASSED]" << std::endl;
436+
}
437+
else
438+
{
439+
std::cout << "[FAILED]" << std::endl;
440+
success = false;
441+
}
442+
443+
return success;
444+
}
445+
446+
403447
int
404448
itkCastImageFilterTest(int, char *[])
405449
{
@@ -431,6 +475,7 @@ itkCastImageFilterTest(int, char *[])
431475
success &= TestCastFrom<double>();
432476
success &= TestVectorImageCast1();
433477
success &= TestVectorImageCast2();
478+
success &= TestVectorImageCast3();
434479

435480
std::cout << std::endl;
436481
if (!success)

0 commit comments

Comments
 (0)