diff --git a/Modules/Core/Common/include/itkImageAlgorithm.h b/Modules/Core/Common/include/itkImageAlgorithm.h index c678f041361..42a57315eff 100644 --- a/Modules/Core/Common/include/itkImageAlgorithm.h +++ b/Modules/Core/Common/include/itkImageAlgorithm.h @@ -138,9 +138,10 @@ struct ImageAlgorithm * the physical space covered by the input * region of the input image */ - template + template static typename OutputImageType::RegionType EnlargeRegionOverBox(const typename InputImageType::RegionType & inputRegion, + const TransformType* transformPtr, const InputImageType* inputImage, const OutputImageType* outputImage); diff --git a/Modules/Core/Common/include/itkImageAlgorithm.hxx b/Modules/Core/Common/include/itkImageAlgorithm.hxx index 1cf1d8ec759..fa81daa9bc1 100644 --- a/Modules/Core/Common/include/itkImageAlgorithm.hxx +++ b/Modules/Core/Common/include/itkImageAlgorithm.hxx @@ -167,9 +167,10 @@ void ImageAlgorithm::DispatchedCopy( const InputImageType *inImage, } } -template +template typename OutputImageType::RegionType ImageAlgorithm::EnlargeRegionOverBox(const typename InputImageType::RegionType & inputRegion, + const TransformType* transformPtr, const InputImageType* inputImage, const OutputImageType* outputImage) { @@ -217,7 +218,14 @@ ImageAlgorithm::EnlargeRegionOverBox(const typename InputImageType::RegionType & typedef Point< SpacePrecisionType, OutputImageType::ImageDimension > PointType; PointType point; - inputImage->TransformContinuousIndexToPhysicalPoint(currentCornerIndex, point); + if ( transformPtr == ITK_NULLPTR) + { + inputImage->TransformContinuousIndexToPhysicalPoint(currentCornerIndex, point); + } + else + { + point = transformPtr->TransformPoint(currentCornerIndex); + } outputImage->TransformPhysicalPointToContinuousIndex(point, corners[count]); } diff --git a/Modules/Core/Common/test/itkImageTest.cxx b/Modules/Core/Common/test/itkImageTest.cxx index 4551a3965c6..6f46b1a1e5c 100644 --- a/Modules/Core/Common/test/itkImageTest.cxx +++ b/Modules/Core/Common/test/itkImageTest.cxx @@ -20,6 +20,7 @@ #include "itkImage.h" #include "itkFixedArray.h" #include "itkImageAlgorithm.h" +#include "itkTransform.h" int itkImageTest(int, char* [] ) { @@ -121,7 +122,10 @@ int itkImageTest(int, char* [] ) regionRef.SetSize(sizeRef); imageRef->SetRegions(regionRef); + typedef itk::Transform< double, Image::ImageDimension, Image::ImageDimension > TransformType; + Image::RegionType boxRegion = itk::ImageAlgorithm::EnlargeRegionOverBox(image->GetLargestPossibleRegion(), + static_cast< TransformType *>(ITK_NULLPTR), image.GetPointer(), imageRef.GetPointer()); Image::IndexType correctIndex; correctIndex.Fill(0); diff --git a/Modules/Filtering/ImageGrid/include/itkResampleImageFilter.hxx b/Modules/Filtering/ImageGrid/include/itkResampleImageFilter.hxx index f678a1cbfdd..6016d08519a 100644 --- a/Modules/Filtering/ImageGrid/include/itkResampleImageFilter.hxx +++ b/Modules/Filtering/ImageGrid/include/itkResampleImageFilter.hxx @@ -26,6 +26,7 @@ #include "itkImageScanlineIterator.h" #include "itkSpecialCoordinatesImage.h" #include "itkDefaultConvertPixelTraits.h" +#include "itkImageAlgorithm.h" namespace itk { @@ -492,10 +493,39 @@ ResampleImageFilter< TInputImage, TOutputImage, TInterpolatorPrecisionType, TTra } // Get pointers to the input and output - InputImagePointer inputPtr = - const_cast< TInputImage * >( this->GetInput() ); + InputImageType * inputPtr = + const_cast< InputImageType * >( this->GetInput() ); - // Determining the actual input region is non-trivial, especially + + // Check whether the input or the output is a + // SpecialCoordinatesImage. If either are, then we cannot use the + // fast path since index mapping will definitely not be linear. + typedef SpecialCoordinatesImage< PixelType, ImageDimension > OutputSpecialCoordinatesImageType; + typedef SpecialCoordinatesImage< InputPixelType, InputImageDimension > InputSpecialCoordinatesImageType; + + const bool isSpecialCoordinatesImage = ( dynamic_cast< const InputSpecialCoordinatesImageType * >( this->GetInput() ) + || dynamic_cast< const OutputSpecialCoordinatesImageType * >( this->GetOutput() ) ); + + const OutputImageType *outputPtr = this->GetOutput(); + // Get the input transform + const TransformType *transformPtr = this->GetTransform(); + + // Check whether we can use upstream streaming for resampling. Upstream streaming + // can be used if the transformation is linear. Transform respond + // to the IsLinear() call. + if ( !isSpecialCoordinatesImage && transformPtr->GetTransformCategory() == TransformType::Linear ) + { + typename TInputImage::RegionType inputRequestedRegion; + inputRequestedRegion = ImageAlgorithm::EnlargeRegionOverBox(outputPtr->GetRequestedRegion(), + transformPtr, + outputPtr, + inputPtr); + + inputPtr->SetRequestedRegion( inputRequestedRegion ); + return; + } + + // Otherwise, determining the actual input region is non-trivial, especially // when we cannot assume anything about the transform being used. // So we do the easy thing and request the entire input image. // diff --git a/Modules/Filtering/ImageGrid/include/itkWarpImageFilter.hxx b/Modules/Filtering/ImageGrid/include/itkWarpImageFilter.hxx index 192dce7de98..9052fc435da 100644 --- a/Modules/Filtering/ImageGrid/include/itkWarpImageFilter.hxx +++ b/Modules/Filtering/ImageGrid/include/itkWarpImageFilter.hxx @@ -27,6 +27,8 @@ #include "itkProgressReporter.h" #include "itkContinuousIndex.h" #include "itkMath.h" +#include "itkTransform.h" + namespace itk { /** @@ -438,8 +440,10 @@ WarpImageFilter< TInputImage, TOutputImage, TDisplacementField > else { typedef typename TDisplacementField::RegionType DisplacementRegionType; + typedef itk::Transform< SpacePrecisionType, OutputImageType::ImageDimension, OutputImageType::ImageDimension > TransformType; DisplacementRegionType fieldRequestedRegion = ImageAlgorithm::EnlargeRegionOverBox(outputPtr->GetRequestedRegion(), + static_cast< TransformType *>(ITK_NULLPTR), outputPtr, fieldPtr); fieldPtr->SetRequestedRegion( fieldRequestedRegion ); diff --git a/Modules/Filtering/ImageGrid/test/Baseline/ResampleImageTest2.mha.sha512 b/Modules/Filtering/ImageGrid/test/Baseline/ResampleImageTest2.mha.sha512 new file mode 100644 index 00000000000..3d8c0b91c51 --- /dev/null +++ b/Modules/Filtering/ImageGrid/test/Baseline/ResampleImageTest2.mha.sha512 @@ -0,0 +1 @@ +6dcda44ce36e39fb6a792e26c8cd93830bab8edbe9f33385dc59b24bd6b40c99bbadf9b6ada967b1d1b6624e986f1161960d86db63b2d6b71da58eec0a2b911c diff --git a/Modules/Filtering/ImageGrid/test/Baseline/ResampleImageTest2NearestExtrapolate.mha.sha512 b/Modules/Filtering/ImageGrid/test/Baseline/ResampleImageTest2NearestExtrapolate.mha.sha512 new file mode 100644 index 00000000000..b4c87795633 --- /dev/null +++ b/Modules/Filtering/ImageGrid/test/Baseline/ResampleImageTest2NearestExtrapolate.mha.sha512 @@ -0,0 +1 @@ +bbc1a32a82e88334df11c79f54ba4260ea291f8316c882d6360e7546739eb92109a169cc07abe32250a4e12e49a4bb8bad22c45580ccb78c4ee482fa68675e4f diff --git a/Modules/Filtering/ImageGrid/test/CMakeLists.txt b/Modules/Filtering/ImageGrid/test/CMakeLists.txt index bd7bd4bfea2..e0754b605f2 100644 --- a/Modules/Filtering/ImageGrid/test/CMakeLists.txt +++ b/Modules/Filtering/ImageGrid/test/CMakeLists.txt @@ -45,10 +45,12 @@ itkWrapPadImageTest.cxx itkMirrorPadImageTest.cxx itkResampleImageTest.cxx itkResampleImageTest2.cxx +itkResampleImageTest2s.cxx itkResampleImageTest3.cxx itkResampleImageTest4.cxx itkResampleImageTest5.cxx itkResampleImageTest6.cxx +itkResampleImageTest7.cxx itkResamplePhasedArray3DSpecialCoordinatesImageTest.cxx itkPushPopTileImageFilterTest.cxx itkShrinkImageStreamingTest.cxx @@ -223,6 +225,22 @@ itk_add_test(NAME itkResampleImageTest2 ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2b.png ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2c.png ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2d.png) +itk_add_test(NAME itkResampleImageTest2s + COMMAND ITKImageGridTestDriver + --compare DATA{Baseline/ResampleImageTest2.mha} + ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2a.mha + --compare DATA{Baseline/ResampleImageTest2.mha} + ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2b.mha + --compare DATA{Baseline/ResampleImageTest2NearestExtrapolate.mha} + ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2c.mha + --compare DATA{Baseline/ResampleImageTest2NearestExtrapolate.mha} + ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2d.mha + itkResampleImageTest2s DATA{${ITK_DATA_ROOT}/Input/cthead1.png} + DATA{${ITK_DATA_ROOT}/Input/circle.png} + ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2a.mha + ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2b.mha + ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2c.mha + ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2d.mha) itk_add_test(NAME itkResampleImageTest3 COMMAND ITKImageGridTestDriver --compare DATA{Baseline/ResampleImageTest3.png} @@ -241,6 +259,8 @@ itk_add_test(NAME itkResampleImageTest6 --compare DATA{Baseline/ResampleImageTest6.png} ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest6.png itkResampleImageTest6 10 ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest6.png) +itk_add_test(NAME itkResampleImageTest7 + COMMAND ITKImageGridTestDriver itkResampleImageTest7) itk_add_test(NAME itkResamplePhasedArray3DSpecialCoordinatesImageTest COMMAND ITKImageGridTestDriver itkResamplePhasedArray3DSpecialCoordinatesImageTest) itk_add_test(NAME itkPushPopTileImageFilterTest diff --git a/Modules/Filtering/ImageGrid/test/itkResampleImageTest2s.cxx b/Modules/Filtering/ImageGrid/test/itkResampleImageTest2s.cxx new file mode 100644 index 00000000000..f4ce5734bd7 --- /dev/null +++ b/Modules/Filtering/ImageGrid/test/itkResampleImageTest2s.cxx @@ -0,0 +1,267 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#include + +#include "itkAffineTransform.h" +#include "itkImageFileReader.h" +#include "itkImageFileWriter.h" +#include "itkResampleImageFilter.h" +#include "itkNearestNeighborExtrapolateImageFunction.h" +#include "itkPipelineMonitorImageFilter.h" +#include "itkTestingMacros.h" + +/* Further testing of itkResampleImageFilter + * Output is compared with baseline image using the cmake itk_add_test + * '--compare' option. + */ + +namespace { + +template +class NonlinearAffineTransform: + public itk::AffineTransform +{ +public: + /** Standard class typedefs. */ + typedef NonlinearAffineTransform Self; + typedef itk::AffineTransform< TCoordRepType, NDimensions > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + /** New macro for creation of through a smart pointer. */ + itkSimpleNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(NonlinearAffineTransform, AffineTransform); + + /** Override this. See test below. */ + virtual bool IsLinear() const ITK_OVERRIDE { return false; } +}; +} + +int itkResampleImageTest2s(int argc, char * argv [] ) +{ + + if( argc < 5 ) + { + std::cerr << "Missing arguments ! " << std::endl; + std::cerr << "Usage : " << std::endl; + std::cerr << argv[0] << "inputImage referenceImage " + << "resampledImageLinear resampledImageNonLinear " + << "resampledImageLinearNearestExtrapolate" + << "resampledImageNonLinearNearestExtrapolate"; + std::cerr << std::endl; + return EXIT_FAILURE; + } + + const unsigned int NDimensions = 2; + + typedef unsigned char PixelType; + typedef itk::Image ImageType; + typedef double CoordRepType; + + typedef itk::AffineTransform + AffineTransformType; + typedef NonlinearAffineTransform + NonlinearAffineTransformType; + typedef itk::LinearInterpolateImageFunction + InterpolatorType; + typedef itk::NearestNeighborExtrapolateImageFunction + ExtrapolatorType; + + typedef itk::ImageFileReader< ImageType > ReaderType; + typedef itk::ImageFileWriter< ImageType > WriterType; + + ReaderType::Pointer reader1 = ReaderType::New(); + ReaderType::Pointer reader2 = ReaderType::New(); + ReaderType::Pointer reader3 = ReaderType::New(); + ReaderType::Pointer reader4 = ReaderType::New(); + + WriterType::Pointer writer1 = WriterType::New(); + WriterType::Pointer writer2 = WriterType::New(); + WriterType::Pointer writer3 = WriterType::New(); + WriterType::Pointer writer4 = WriterType::New(); + + reader1->SetFileName( argv[1] ); + reader2->SetFileName( argv[2] ); + reader3->SetFileName( argv[3] ); + reader4->SetFileName( argv[4] ); + + writer1->SetFileName( argv[3] ); + writer2->SetFileName( argv[4] ); + writer3->SetFileName( argv[5] ); + writer4->SetFileName( argv[6] ); + + // Create an affine transformation + AffineTransformType::Pointer affineTransform = AffineTransformType::New(); + affineTransform->Scale(2.0); + + // Create a linear interpolation image function + InterpolatorType::Pointer interpolator = InterpolatorType::New(); + + // Create a nearest neighbor extrapolate image function + ExtrapolatorType::Pointer extrapolator = ExtrapolatorType::New(); + + // Create and configure a resampling filter + typedef itk::ResampleImageFilter< ImageType, ImageType > ResampleFilterType; + + ResampleFilterType::Pointer resample = ResampleFilterType::New(); + + typedef itk::PipelineMonitorImageFilter< ImageType > MonitorFilter; + + MonitorFilter::Pointer monitor = MonitorFilter::New(); + + EXERCISE_BASIC_OBJECT_METHODS( resample, ResampleImageFilter, ImageToImageFilter ); + + resample->SetInput( reader1->GetOutput() ); + TEST_SET_GET_VALUE( reader1->GetOutput(), resample->GetInput() ); + + resample->SetReferenceImage( reader2->GetOutput() ); + TEST_SET_GET_VALUE( reader2->GetOutput(), resample->GetReferenceImage() ); + + resample->UseReferenceImageOn(); + TEST_EXPECT_TRUE( resample->GetUseReferenceImage() ); + + resample->SetTransform( affineTransform ); + TEST_SET_GET_VALUE( affineTransform, resample->GetTransform() ); + + resample->SetInterpolator( interpolator ); + TEST_SET_GET_VALUE( interpolator, resample->GetInterpolator() ); + + monitor->SetInput( resample->GetOutput() ); + writer1->SetInput( monitor->GetOutput() ); + + // Check GetReferenceImage + if( resample->GetReferenceImage() != reader2->GetOutput() ) + { + std::cerr << "GetReferenceImage() failed ! " << std::endl; + return EXIT_FAILURE; + } + + // Run the resampling filter with the normal, linear, affine transform. + // This will use ResampleImageFilter::LinearThreadedGenerateData(). + std::cout << "Test with normal AffineTransform." << std::endl; + try + { + writer1->SetNumberOfStreamDivisions(8); //split into 8 pieces for streaming. + writer1->Update(); + } + catch( itk::ExceptionObject & excp ) + { + std::cerr << excp << std::endl; + return EXIT_FAILURE; + } + + // this verifies that the pipeline was executed as expected along + // with correct region propagation and output information + if (!monitor->VerifyAllInputCanStream(8)) + { + std::cout << "Streaming failed to execute as expected!" << std::endl; + std::cout << monitor; + return EXIT_FAILURE; + } + + // Assign an affine transform that returns + // false for IsLinear() instead of true, to force + // the filter to use the NonlinearThreadedGenerateData method + // instead of LinearThreadedGenerateData. This will test that + // we get the same results for both methods. + std::cout << "Test with NonlinearAffineTransform." << std::endl; + NonlinearAffineTransformType::Pointer nonlinearAffineTransform = + NonlinearAffineTransformType::New(); + + nonlinearAffineTransform->Scale(2.0); + resample->SetTransform( nonlinearAffineTransform ); + writer2->SetInput( resample->GetOutput() ); + try + { + writer2->SetNumberOfStreamDivisions(8); //demand splitting into 8 pieces for streaming, but faked non-linearity will disable streaming + writer2->Update(); + } + catch( itk::ExceptionObject & excp ) + { + std::cerr << excp << std::endl; + return EXIT_FAILURE; + } + + // Instead of using the default pixel when sampling outside the input image, + // we use a nearest neighbor extrapolator. + resample->SetTransform( affineTransform ); + resample->SetExtrapolator( extrapolator ); + writer3->SetInput( resample->GetOutput() ); + std::cout << "Test with nearest neighbor extrapolator, affine transform." << std::endl; + try + { + writer3->SetNumberOfStreamDivisions(8); //split into 8 pieces for streaming. + writer3->Update(); + } + catch( itk::ExceptionObject & excp ) + { + std::cerr << excp << std::endl; + return EXIT_FAILURE; + } + + // Instead of using the default pixel when sampling outside the input image, + // we use a nearest neighbor extrapolator. + resample->SetTransform( nonlinearAffineTransform ); + writer4->SetInput( resample->GetOutput() ); + std::cout << "Test with nearest neighbor extrapolator, nonlinear transform." << std::endl; + try + { + writer4->SetNumberOfStreamDivisions(8); //demand splitting into 8 pieces for streaming, but faked non-linearity will disable streaming + writer4->Update(); + } + catch( itk::ExceptionObject & excp ) + { + std::cerr << excp << std::endl; + return EXIT_FAILURE; + } + + // Check UseReferenceImage methods + resample->UseReferenceImageOff(); + if( resample->GetUseReferenceImage() ) + { + std::cerr << "GetUseReferenceImage() or UseReferenceImageOff() failed ! "; + std::cerr << std::endl; + return EXIT_FAILURE; + } + + // Check UseReferenceImage methods + resample->UseReferenceImageOn(); + if( !resample->GetUseReferenceImage() ) + { + std::cerr << "GetUseReferenceImage() or UseReferenceImageOn() failed ! "; + std::cerr << std::endl; + return EXIT_FAILURE; + } + + // Check UseReferenceImage methods + resample->SetUseReferenceImage( false ); + if( resample->GetUseReferenceImage() ) + { + std::cerr << "GetUseReferenceImage() or SetUseReferenceImage() failed ! "; + std::cerr << std::endl; + return EXIT_FAILURE; + } + + + std::cout << "Test passed." << std::endl; + return EXIT_SUCCESS; + +} diff --git a/Modules/Filtering/ImageGrid/test/itkResampleImageTest7.cxx b/Modules/Filtering/ImageGrid/test/itkResampleImageTest7.cxx new file mode 100644 index 00000000000..2f471a88953 --- /dev/null +++ b/Modules/Filtering/ImageGrid/test/itkResampleImageTest7.cxx @@ -0,0 +1,170 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ + +#include + +#include "itkAffineTransform.h" +#include "itkResampleImageFilter.h" +#include "itkPipelineMonitorImageFilter.h" +#include "itkStreamingImageFilter.h" +#include "itkTestingMacros.h" +#include "itkMath.h" + +/* itkResampleImageFilter output compared to streamed output + */ + +int itkResampleImageTest7( int argc, char * argv [] ) +{ + + if (argc > 1) + { + std::cout << "Usage: " << argv[0] + << " noParams" << std::endl; + return EXIT_FAILURE; + } + + const unsigned int NDimensions = 2; + + typedef unsigned char PixelType; + typedef itk::Image ImageType; + typedef ImageType::IndexType ImageIndexType; + typedef ImageType::Pointer ImagePointerType; + typedef ImageType::RegionType ImageRegionType; + typedef ImageType::SizeType ImageSizeType; + typedef double CoordRepType; + + typedef itk::AffineTransform + AffineTransformType; + + // Create and configure an image + ImagePointerType image = ImageType::New(); + ImageIndexType index = {{0, 0}}; + ImageSizeType size = {{64,64}}; + ImageRegionType region; + region.SetSize ( size ); + region.SetIndex( index ); + image->SetLargestPossibleRegion( region ); + image->SetBufferedRegion( region ); + image->Allocate(); + + // Fill image with a ramp + std::cout << "init image..." << std::flush; + itk::ImageRegionIteratorWithIndex iter(image, region); + PixelType value; + for (iter.GoToBegin(); !iter.IsAtEnd(); ++iter) + { + index = iter.GetIndex(); + value = index[0] + index[1]; + iter.Set(value); + } + std::cout << "Done." << std::endl; + + // Create an affine transformation + AffineTransformType::Pointer affineTransform = AffineTransformType::New(); + affineTransform->Scale(2.0); + + // Create and configure a resampling filter + typedef itk::ResampleImageFilter< ImageType, ImageType > ResampleFilterType; + ResampleFilterType::Pointer resample = ResampleFilterType::New(); + + typedef itk::PipelineMonitorImageFilter< ImageType > MonitorFilter; + MonitorFilter::Pointer monitor = MonitorFilter::New(); + + typedef itk::StreamingImageFilter StreamerType; + StreamerType::Pointer streamer = StreamerType::New(); + + std::cout << "Test with normal AffineTransform." << std::endl; + resample->SetInput( image ); + resample->SetTransform( affineTransform ); + monitor->SetInput( resample->GetOutput() ); + streamer->SetInput( monitor->GetOutput() ); + + unsigned char numStreamDiv; + + // Run the resampling filter without streaming, i.e. 1 StreamDivisions + numStreamDiv= 1; // do not split, i.e. do not stream + try + { + streamer->SetNumberOfStreamDivisions(numStreamDiv); + streamer->Update(); + } + catch( itk::ExceptionObject & excp ) + { + std::cerr << excp << std::endl; + return EXIT_FAILURE; + } + + if (!monitor->VerifyAllInputCanStream(numStreamDiv)) + { + std::cout << "Avoiding streaming failed to execute as expected!" << std::endl; + std::cout << monitor; + return EXIT_FAILURE; + } + + ImagePointerType outputNoSDI= streamer->GetOutput(); + outputNoSDI->DisconnectPipeline(); + + // Run the resampling filter with streaming + numStreamDiv= 8; // split into numStream pieces for streaming. + resample->Modified(); + try + { + streamer->SetNumberOfStreamDivisions(numStreamDiv); + streamer->Update(); + } + catch( itk::ExceptionObject & excp ) + { + std::cerr << excp << std::endl; + return EXIT_FAILURE; + } + + if (!monitor->VerifyAllInputCanStream(numStreamDiv)) + { + std::cout << "Streaming failed to execute as expected!" << std::endl; + std::cout << monitor; + return EXIT_FAILURE; + } + + ImagePointerType outputSDI= streamer->GetOutput(); + outputSDI->DisconnectPipeline(); + + itk::ImageRegionIterator + itNoSDI(outputNoSDI, outputNoSDI->GetLargestPossibleRegion()), + itSDI(outputSDI, outputSDI->GetLargestPossibleRegion()); + for(itNoSDI.GoToBegin(), itSDI.GoToBegin(); + !itNoSDI.IsAtEnd() && !itSDI.IsAtEnd(); + ++itNoSDI, ++itSDI) + { + if(itk::Math::NotAlmostEquals( itNoSDI.Value(), itSDI.Value() )) + { + std::cout << "Pixels differ " + << itNoSDI.Value() << " " + << itSDI.Value() << std::endl; + return EXIT_FAILURE; + } + } + if(itNoSDI.IsAtEnd() != itSDI.IsAtEnd()) + { + std::cout << "Iterators don't agree on end of image" << std::endl; + return EXIT_FAILURE; + } + + std::cout << "Test passed." << std::endl; + return EXIT_SUCCESS; + +}