diff --git a/Modules/Core/Common/include/itkMetaProgrammingLibrary.h b/Modules/Core/Common/include/itkMetaProgrammingLibrary.h index e09e41da721..a0aa76bb8e2 100644 --- a/Modules/Core/Common/include/itkMetaProgrammingLibrary.h +++ b/Modules/Core/Common/include/itkMetaProgrammingLibrary.h @@ -210,6 +210,23 @@ struct Not : NotC using Type = typename NotC::Type; }; +/** MPL type trait to check if type is a SmartPointer. + */ +template +struct IsSmartPointer : FalseType +{}; + + +/// \cond SPECIALIZATION_IMPLEMENTATION +template +struct IsSmartPointer> : TrueType +{}; + +template +struct IsSmartPointer> : TrueType +{}; +/// \endcond + /** MPL relational type trait to check if a static_cast conversion * exists. * diff --git a/Modules/IO/ImageBase/ITKKWStyleOverwrite.txt b/Modules/IO/ImageBase/ITKKWStyleOverwrite.txt index dd8d28f1d38..755ab52cd8d 100644 --- a/Modules/IO/ImageBase/ITKKWStyleOverwrite.txt +++ b/Modules/IO/ImageBase/ITKKWStyleOverwrite.txt @@ -1 +1,2 @@ itkConvertPixelBuffer\.hxx Namespace Disable +test/itkWriteImageFunctionGTest.cxx Namespace Disable diff --git a/Modules/IO/ImageBase/include/itkImageFileWriter.h b/Modules/IO/ImageBase/include/itkImageFileWriter.h index 074527a2d7f..95b4dc28235 100644 --- a/Modules/IO/ImageBase/include/itkImageFileWriter.h +++ b/Modules/IO/ImageBase/include/itkImageFileWriter.h @@ -22,6 +22,7 @@ #include "itkProcessObject.h" #include "itkImageIOBase.h" #include "itkMacro.h" +#include "itkMetaProgrammingLibrary.h" namespace itk { @@ -237,61 +238,27 @@ class ITK_TEMPLATE_EXPORT ImageFileWriter : public ProcessObject }; -/** Convenience function for writing an image. */ -template +/** Convenience function for writing an image. + * + * The image parameter may be a either SmartPointer or a raw pointer and const or non-const. + * */ +template ITK_TEMPLATE_EXPORT void -WriteImage(const TImage * image, const char * filename, bool compress = false) +WriteImage(TImagePointer && image, const std::string & filename, bool compress = false) { - using WriterType = ImageFileWriter; - typename WriterType::Pointer writer = WriterType::New(); + using NonReferenceImagePointer = typename std::remove_reference::type; + static_assert(std::is_pointer::value || + mpl::IsSmartPointer::Value, + "WriteImage requires a raw pointer or SmartPointer."); + + using ImageType = typename std::remove_const::type>::type; + auto writer = ImageFileWriter::New(); writer->SetInput(image); writer->SetFileName(filename); writer->SetUseCompression(compress); writer->Update(); } -template -ITK_TEMPLATE_EXPORT void -WriteImage(const SmartPointer image, const char * filename, bool compress = false) -{ - WriteImage(image.GetPointer(), filename, compress); -} -template -ITK_TEMPLATE_EXPORT void -WriteImage(TImage * image, const char * filename, bool compress = false) -{ - const TImage * constImage = image; - WriteImage(constImage, filename, compress); -} -template -ITK_TEMPLATE_EXPORT void -WriteImage(SmartPointer image, const char * filename, bool compress = false) -{ - WriteImage(image.GetPointer(), filename, compress); -} -template -ITK_TEMPLATE_EXPORT void -WriteImage(const TImage * image, const std::string & filename, bool compress = false) -{ - WriteImage(image, filename.c_str(), compress); -} -template -ITK_TEMPLATE_EXPORT void -WriteImage(const SmartPointer image, const std::string & filename, bool compress = false) -{ - WriteImage(image, filename.c_str(), compress); -} -template -ITK_TEMPLATE_EXPORT void -WriteImage(TImage * image, const std::string & filename, bool compress = false) -{ - WriteImage(image, filename.c_str(), compress); -} -template -ITK_TEMPLATE_EXPORT void -WriteImage(SmartPointer image, const std::string & filename, bool compress = false) -{ - WriteImage(image, filename.c_str(), compress); -} + } // end namespace itk #ifndef ITK_MANUAL_INSTANTIATION diff --git a/Modules/IO/ImageBase/test/CMakeLists.txt b/Modules/IO/ImageBase/test/CMakeLists.txt index ed4dbe3210c..409ebed394d 100644 --- a/Modules/IO/ImageBase/test/CMakeLists.txt +++ b/Modules/IO/ImageBase/test/CMakeLists.txt @@ -355,3 +355,11 @@ itk_add_test(NAME itkVectorImageReadWriteTest2 add_executable(itkUnicodeIOTest itkUnicodeIOTest.cxx) itk_module_target_label(itkUnicodeIOTest) itk_add_test(NAME itkUnicodeIOTest COMMAND itkUnicodeIOTest) + + +set(ITKIOImageBaseGTests + itkWriteImageFunctionGTest.cxx + ) +CreateGoogleTestDriver(ITKIOImageBase "${ITKIOImageBase-Test_LIBRARIES}" "${ITKIOImageBaseGTests}") + +target_compile_definitions(ITKIOImageBaseGTestDriver PRIVATE "-DITK_TEST_OUTPUT_DIR=${ITK_TEST_OUTPUT_DIR}") diff --git a/Modules/IO/ImageBase/test/itkWriteImageFunctionGTest.cxx b/Modules/IO/ImageBase/test/itkWriteImageFunctionGTest.cxx new file mode 100644 index 00000000000..c93092c4df6 --- /dev/null +++ b/Modules/IO/ImageBase/test/itkWriteImageFunctionGTest.cxx @@ -0,0 +1,77 @@ +/*========================================================================= + * + * Copyright NumFOCUS + * + * 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 "itkImageFileWriter.h" +#include "itkImage.h" + +#include "itkGTest.h" +#include "itksys/SystemTools.hxx" +#include "itkTestDriverIncludeRequiredIOFactories.h" + +#define STRING(s) #s + +namespace +{ + +struct ITKWriteImageFunctionTest : public ::testing::Test +{ + void + SetUp() override + { + RegisterRequiredFactories(); + itksys::SystemTools::ChangeDirectory(STRING(ITK_TEST_OUTPUT_DIR_STR)); + } + using ImageType = itk::Image; + + ImageType::Pointer + MakeImage() + { + auto image = ImageType::New(); + + ImageType::RegionType region({ 3, 2 }); + + image->SetRegions(region); + + image->Allocate(true); + return image; + } +}; + + +} // namespace + +TEST_F(ITKWriteImageFunctionTest, ImageTypes) +{ + ImageType::Pointer image_ptr = MakeImage(); + itk::WriteImage(image_ptr, "test1.mha"); + itk::WriteImage(std::move(image_ptr), "test1.mha"); + + ImageType::ConstPointer image_cptr = MakeImage(); + itk::WriteImage(image_cptr, "test1.mha"); + itk::WriteImage(std::move(image_cptr), "test1.mha"); + + const ImageType::ConstPointer image_ccptr = MakeImage(); + itk::WriteImage(image_ccptr, "test1.mha"); + itk::WriteImage(std::move(image_ccptr), "test1.mha"); + + image_ptr = MakeImage(); + ImageType * image_rptr = image_ptr.GetPointer(); + itk::WriteImage(image_rptr, "test1.mha"); + + const ImageType * image_crptr = image_ptr.GetPointer(); + itk::WriteImage(image_crptr, "test1.mha"); +}