From 46551e76446bdf4ca8a28897be31816fb90e1d27 Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Thu, 18 Jul 2024 23:36:54 -0400 Subject: [PATCH] feat(cxx): add bufferedRegion to ImageJSON --- include/itkImageJSON.h | 27 +++++++++++++- include/itkImportVectorImageFilter.h | 37 +++++++++++++++---- include/itkImportVectorImageFilter.hxx | 4 +- include/itkWasmImage.h | 8 ++-- include/itkWasmImageToImageFilter.h | 4 +- include/itkWasmImageToImageFilter.hxx | 17 +++++---- ...asmImageInterfaceWithNegativeIndexTest.cxx | 2 +- 7 files changed, 73 insertions(+), 26 deletions(-) diff --git a/include/itkImageJSON.h b/include/itkImageJSON.h index e8797bc29..b16cc1e2d 100644 --- a/include/itkImageJSON.h +++ b/include/itkImageJSON.h @@ -30,6 +30,8 @@ #include "glaze/glaze.hpp" +#include + namespace itk { /** \class ImageTypeJSON @@ -46,6 +48,18 @@ namespace itk unsigned int components { 1 }; }; + /** \class ImageRegionJSON + * + * \brief Image region JSON representation data structure. + * + * \ingroup WebAssemblyInterface + */ + struct ImageRegionJSON + { + std::vector index {}; + std::vector size {}; + }; + /** \class ImageJSON * * \brief Image JSON representation data structure. @@ -61,7 +75,8 @@ namespace itk std::vector origin { 0.0, 0.0 }; std::vector spacing { 1.0, 1.0 }; std::string direction; - std::vector size { 0, 0 }; + std::vector size { 0, 0 }; + ImageRegionJSON bufferedRegion{}; std::string data; @@ -93,6 +108,7 @@ auto imageToImageJSON(const TImage * image, const WasmImage * wasmImage, using PointType = typename ImageType::PointType; PointType imageOrigin; + // largest region index is implicitly zeros image->TransformIndexToPhysicalPoint(largestRegion.GetIndex(), imageOrigin); imageJSON.origin.clear(); for (unsigned int ii = 0; ii < ImageType::ImageDimension; ++ii) @@ -120,10 +136,17 @@ auto imageToImageJSON(const TImage * image, const WasmImage * wasmImage, imageJSON.direction = "data:application/vnd.itk.path,data/direction.raw"; } + imageJSON.bufferedRegion.index.clear(); + imageJSON.bufferedRegion.size.clear(); imageJSON.size.clear(); - const auto imageSize = image->GetBufferedRegion().GetSize(); + // largest region index is implicitly zeros + const auto bufferedRegionIndex = image->GetBufferedRegion().GetIndex() - largestRegion.GetIndex(); + const auto bufferedRegionSize = image->GetBufferedRegion().GetSize(); + const auto imageSize = image->GetLargestPossibleRegion().GetSize(); for (unsigned int ii = 0; ii < ImageType::ImageDimension; ++ii) { + imageJSON.bufferedRegion.index.push_back(bufferedRegionIndex[ii]); + imageJSON.bufferedRegion.size.push_back(bufferedRegionSize[ii]); imageJSON.size.push_back(imageSize[ii]); } diff --git a/include/itkImportVectorImageFilter.h b/include/itkImportVectorImageFilter.h index bd8e677fe..fb73b541a 100644 --- a/include/itkImportVectorImageFilter.h +++ b/include/itkImportVectorImageFilter.h @@ -99,27 +99,47 @@ class ITK_TEMPLATE_EXPORT ImportVectorImageFilter : public ImageSourceModified(); } } /** Get the region object that defines the size and starting index - * for the imported image. This will serve as the LargestPossibleRegion, + * for the imported image. This will serve as the * the BufferedRegion, and the RequestedRegion. * \sa ImageRegion */ const RegionType & - GetRegion() const + GetBufferedRegion() const { - return m_Region; + return m_BufferedRegion; + } + + /** Set the LargestPossibleRegion + * \sa ImageRegion */ + void + SetLargestPossibleRegion(const RegionType & region) + { + if (m_LargestPossibleRegion != region) + { + m_LargestPossibleRegion = region; + this->Modified(); + } + } + + /** Get the LargestPossibleRegion, + * \sa ImageRegion */ + const RegionType & + GetLargestPossibleRegion() const + { + return m_LargestPossibleRegion; } /** Set the spacing (size of a pixel) of the image. @@ -173,7 +193,8 @@ class ITK_TEMPLATE_EXPORT ImportVectorImageFilter : public ImageSource::EnlargeOutputRequestedRegion(DataObject * // set the requested region to the largest possible region (in this case // the amount of data that we have) - outputPtr->SetRequestedRegion(outputPtr->GetLargestPossibleRegion()); + outputPtr->SetRequestedRegion(m_BufferedRegion); } template @@ -136,7 +136,7 @@ ImportVectorImageFilter::GenerateOutputInformation() outputPtr->SetSpacing(m_Spacing); outputPtr->SetOrigin(m_Origin); outputPtr->SetDirection(m_Direction); - outputPtr->SetLargestPossibleRegion(m_Region); + outputPtr->SetLargestPossibleRegion(m_LargestPossibleRegion); if (outputPtr->GetNameOfClass() == "VectorImage") { diff --git a/include/itkWasmImage.h b/include/itkWasmImage.h index 18cf793a6..ab99c4eaf 100644 --- a/include/itkWasmImage.h +++ b/include/itkWasmImage.h @@ -27,14 +27,14 @@ namespace itk * \brief JSON representation for an itk::ImageBase * * JSON representation for an itk::ImageBase for interfacing across programming languages and runtimes. - * + * * Pixel and Direction binary array buffer's are stored as strings with memory addresses or paths on disks or a virtual filesystem. - * + * * Arrays: - * + * * - 0: Pixel buffer `data` * - 1: Orientation `direction` - * + * * \ingroup WebAssemblyInterface */ template diff --git a/include/itkWasmImageToImageFilter.h b/include/itkWasmImageToImageFilter.h index baf14f465..d07b552a7 100644 --- a/include/itkWasmImageToImageFilter.h +++ b/include/itkWasmImageToImageFilter.h @@ -26,9 +26,9 @@ namespace itk /** *\class WasmImageToImageFilter * \brief Convert an WasmImage to an Image object. - * + * * TImage must match the type stored in the JSON representation or an exception will be shown. - * + * * \ingroup WebAssemblyInterface */ template diff --git a/include/itkWasmImageToImageFilter.hxx b/include/itkWasmImageToImageFilter.hxx index 3b5d339ba..db86f6513 100644 --- a/include/itkWasmImageToImageFilter.hxx +++ b/include/itkWasmImageToImageFilter.hxx @@ -202,18 +202,21 @@ WasmImageToImageFilter const DirectionType direction(vnlMatrix); filter->SetDirection(direction); + using RegionType = typename ImageType::RegionType; + RegionType bufferedRegion; + RegionType largestRegion; using SizeType = typename ImageType::SizeType; - SizeType size; + SizeType largestSize; SizeValueType totalSize = 1; for (unsigned int i = 0; i < Dimension; ++i) { - size[i] = imageJSON.size[i]; - totalSize *= size[i]; + bufferedRegion.SetIndex(i, imageJSON.bufferedRegion.index[i]); + bufferedRegion.SetSize(i, imageJSON.bufferedRegion.size[i]); + largestRegion.SetSize(i, imageJSON.size[i]); + totalSize *= largestSize[i]; } - using RegionType = typename ImageType::RegionType; - RegionType region; - region.SetSize( size ); - filter->SetRegion( region ); + filter->SetBufferedRegion(bufferedRegion); + filter->SetLargestPossibleRegion(largestRegion); const std::string dataString = imageJSON.data; IOPixelType * dataPtr = reinterpret_cast< IOPixelType * >( std::strtoull(dataString.substr(35).c_str(), nullptr, 10) ); diff --git a/test/itkWasmImageInterfaceWithNegativeIndexTest.cxx b/test/itkWasmImageInterfaceWithNegativeIndexTest.cxx index f0be6cbc0..b94010f39 100644 --- a/test/itkWasmImageInterfaceWithNegativeIndexTest.cxx +++ b/test/itkWasmImageInterfaceWithNegativeIndexTest.cxx @@ -60,7 +60,7 @@ itkWasmImageInterfaceWithNegativeIndexTest(int argc, char * argv[]) using ImageToWasmImageFilterType = itk::ImageToWasmImageFilter; auto imageToJSON = ImageToWasmImageFilterType::New(); imageToJSON->SetInput(constantPad->GetOutput()); - imageToJSON->Update(); + imageToJSON->UpdateLargestPossibleRegion(); auto imageJSON = imageToJSON->GetOutput(); std::cout << "Image JSON: " << imageJSON->GetJSON() << std::endl;