diff --git a/Modules/Core/ImageAdaptors/include/itkImageAdaptor.h b/Modules/Core/ImageAdaptors/include/itkImageAdaptor.h index 0c737652538..c36efee3a8e 100644 --- a/Modules/Core/ImageAdaptors/include/itkImageAdaptor.h +++ b/Modules/Core/ImageAdaptors/include/itkImageAdaptor.h @@ -238,6 +238,13 @@ class ITK_TEMPLATE_EXPORT ImageAdaptor : public ImageBaseComputeOffset(index); + } + /** PixelContainer type alias support Used to construct a container for * the pixel data. */ using PixelContainer = typename TImage::PixelContainer; diff --git a/Modules/Core/ImageAdaptors/test/itkImageAdaptorGTest.cxx b/Modules/Core/ImageAdaptors/test/itkImageAdaptorGTest.cxx index a7114aafe1c..fbd92d7ddc8 100644 --- a/Modules/Core/ImageAdaptors/test/itkImageAdaptorGTest.cxx +++ b/Modules/Core/ImageAdaptors/test/itkImageAdaptorGTest.cxx @@ -22,6 +22,8 @@ #include "itkCovariantVector.h" #include "itkImage.h" #include "itkImageAdaptor.h" +#include "itkImageRegionIterator.h" +#include "itkIndexRange.h" #include "itkVector.h" #include @@ -185,3 +187,68 @@ TEST(ImageAdapter, TransformMemberFunctionsReturnSameAsForImage) const auto image3D = itk::Image::New(); Expect_Transform_member_functions_return_the_same_for_an_ImageAdapter_as_for_its_image(*image3D); } + + +// Tests that ComputeOffset(index) returns the same value for an adaptor as for its internal image. +TEST(ImageAdaptor, ComputeOffset) +{ + constexpr unsigned int dimension{ 2 }; + using PixelType = int; + using ImageType = itk::Image; + + const auto image = ImageType::New(); + const auto adaptor = itk::ImageAdaptor>::New(); + + // Use a very small image region, to speed up the unit test. + const itk::ImageRegion imageRegion{ itk::Index::Filled(1), itk::Size::Filled(2) }; + + adaptor->SetImage(image); + adaptor->SetRegions(imageRegion); + adaptor->AllocateInitialized(); + + for (const auto & index : itk::MakeIndexRange(imageRegion)) + { + EXPECT_EQ(adaptor->ComputeOffset(index), image->ComputeOffset(index)); + } +} + + +// Tests that ImageAdaptor supports iteration by means of ImageRegionIterator. +TEST(ImageAdaptor, SupportsRegionIterator) +{ + constexpr unsigned int dimension{ 2 }; + using PixelType = int; + using ImageType = itk::Image; + + const auto image = ImageType::New(); + const auto adaptor = itk::ImageAdaptor>::New(); + + adaptor->SetImage(image); + adaptor->SetRegions(itk::Size::Filled(4)); + adaptor->AllocateInitialized(); + + constexpr auto regionIndex = itk::Index::Filled(1); + constexpr auto regionSize = itk::Size::Filled(2); + const itk::ImageRegion region{ regionIndex, regionSize }; + + // Set the pixel values by means of the adaptor, for the specified region. + PixelType pixelValue{}; + constexpr PixelType maxPixelValue{ regionSize.CalculateProductOfElements() }; + + for (itk::ImageRegionIterator iterator(adaptor, region); !iterator.IsAtEnd(); ++iterator) + { + ++pixelValue; + ASSERT_LE(pixelValue, maxPixelValue); + iterator.Set(pixelValue); + EXPECT_EQ(iterator.Get(), pixelValue); + } + + // Now check if the intenal image has got the expected pixel values, in the specified region. + PixelType expectedPixelValue{}; + + for (itk::ImageRegionConstIterator iterator(image, region); !iterator.IsAtEnd(); ++iterator) + { + ++expectedPixelValue; + EXPECT_EQ(iterator.Get(), expectedPixelValue); + } +}