From d3e1571101011ca7487894fede3deec2e6ccc6cb Mon Sep 17 00:00:00 2001 From: Romulo Pinho Date: Fri, 16 Sep 2011 11:23:42 +0200 Subject: [PATCH] Bug/issue 704 - Made clitkPadImage generic (no support for 4D images for the moment). --- tools/CMakeLists.txt | 2 +- tools/clitkPadImage.cxx | 194 +++++++++++++-------------- tools/clitkPadImage.ggo | 4 +- tools/clitkPadImageGenericFilter.cxx | 191 ++++++++++++++++++++++++++ tools/clitkPadImageGenericFilter.h | 77 +++++++++++ 5 files changed, 367 insertions(+), 101 deletions(-) create mode 100644 tools/clitkPadImageGenericFilter.cxx create mode 100644 tools/clitkPadImageGenericFilter.h diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 45a06ac..f5a62b4 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -325,7 +325,7 @@ IF (CLITK_BUILD_TOOLS) SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkJacobianImage) WRAP_GGO(clitkPadImage_GGO_C clitkPadImage.ggo) - ADD_EXECUTABLE(clitkPadImage clitkPadImage.cxx ${clitkPadImage_GGO_C}) + ADD_EXECUTABLE(clitkPadImage clitkPadImage.cxx clitkPadImageGenericFilter.cxx ${clitkPadImage_GGO_C}) TARGET_LINK_LIBRARIES(clitkPadImage clitkCommon ${ITK_LIBRARIES}) SET(TOOLS_INSTALL ${TOOLS_INSTALL} clitkPadImage) diff --git a/tools/clitkPadImage.cxx b/tools/clitkPadImage.cxx index ad93eaa..94d8ab6 100644 --- a/tools/clitkPadImage.cxx +++ b/tools/clitkPadImage.cxx @@ -1,116 +1,114 @@ -#include "itkImage.h" -#include "itkImageFileReader.h" -#include "itkImageFileWriter.h" -#include "itkConstantPadImageFilter.h" #include "clitkCommon.h" #include "clitkPadImage_ggo.h" -#include -#include "itkMath.h" +#include "clitkPadImageGenericFilter.h" -enum -{ - ERR_SUCCESS = 0, - ERR_NOT_SAME_SPACING = -1, - ERR_NOT_LIKE_LARGER = -2 -}; - -typedef unsigned int DimType; - -template -int pad_like(typename ImageType::Pointer input, const std::string& likeFile, PadBoundType* padLower, PadBoundType* padUpper) -{ - typedef typename ImageType::SpacingType SpacingType; - typedef typename ImageType::RegionType RegionType; - typedef typename ImageType::SizeType SizeType; - typedef typename ImageType::IndexType IndexType; - typedef typename ImageType::PointType PointType; - typedef typename ImageType::PointValueType PointValueType; - - typedef itk::ImageFileReader ImageReaderType; - typename ImageReaderType::Pointer reader = ImageReaderType::New(); - reader->SetFileName(likeFile); - reader->Update(); - - typename ImageType::Pointer like_image = reader->GetOutput(); - - SpacingType spacing = input->GetSpacing(), like_spacing = like_image->GetSpacing(); - if (spacing != like_spacing) { - std::cerr << "Like-image must have same spacing as input: " << spacing << " " << like_spacing << std::endl; - return ERR_NOT_SAME_SPACING; - } - - SizeType size = input->GetLargestPossibleRegion().GetSize(), like_size = like_image->GetLargestPossibleRegion().GetSize(); - PointType origin = input->GetOrigin(), like_origin = like_image->GetOrigin(); - - PointType lower_bound, like_lower_bound; - PointType upper_bound, like_upper_bound; - PointValueType auxl = 0, auxu = 0; - for (DimType i = 0; i < dim; i++) { - lower_bound[i] = origin[i]; - like_lower_bound[i] = like_origin[i]; - auxl = itk::Math::Round(((lower_bound[i] - like_lower_bound[i])/spacing[i])); - - upper_bound[i] = (lower_bound[i] + size[i]*spacing[i]); - like_upper_bound[i] = (like_lower_bound[i] + like_size[i]*spacing[i]); - auxu = itk::Math::Round(((like_upper_bound[i] - upper_bound[i])/spacing[i])); - - if (auxl < 0 || auxu < 0) { - std::cerr << "Like-image's bounding box must be larger than input's" << std::endl; - return ERR_NOT_LIKE_LARGER; - } - - padLower[i] = (PadBoundType)auxl; - padUpper[i] = (PadBoundType)auxu; - } - - return ERR_SUCCESS; -} +// template +// int pad_like(typename ImageType::Pointer input, const std::string& likeFile, PadBoundType* padLower, PadBoundType* padUpper) +// { +// typedef typename ImageType::SpacingType SpacingType; +// typedef typename ImageType::RegionType RegionType; +// typedef typename ImageType::SizeType SizeType; +// typedef typename ImageType::IndexType IndexType; +// typedef typename ImageType::PointType PointType; +// typedef typename ImageType::PointValueType PointValueType; +// +// typedef itk::ImageFileReader ImageReaderType; +// typename ImageReaderType::Pointer reader = ImageReaderType::New(); +// reader->SetFileName(likeFile); +// reader->Update(); +// +// typename ImageType::Pointer like_image = reader->GetOutput(); +// +// SpacingType spacing = input->GetSpacing(), like_spacing = like_image->GetSpacing(); +// if (spacing != like_spacing) { +// std::cerr << "Like-image must have same spacing as input: " << spacing << " " << like_spacing << std::endl; +// return ERR_NOT_SAME_SPACING; +// } +// +// SizeType size = input->GetLargestPossibleRegion().GetSize(), like_size = like_image->GetLargestPossibleRegion().GetSize(); +// PointType origin = input->GetOrigin(), like_origin = like_image->GetOrigin(); +// +// PointType lower_bound, like_lower_bound; +// PointType upper_bound, like_upper_bound; +// PointValueType auxl = 0, auxu = 0; +// for (unsigned int i = 0; i < dim; i++) { +// lower_bound[i] = origin[i]; +// like_lower_bound[i] = like_origin[i]; +// auxl = itk::Math::Round(((lower_bound[i] - like_lower_bound[i])/spacing[i])); +// +// upper_bound[i] = (lower_bound[i] + size[i]*spacing[i]); +// like_upper_bound[i] = (like_lower_bound[i] + like_size[i]*spacing[i]); +// auxu = itk::Math::Round(((like_upper_bound[i] - upper_bound[i])/spacing[i])); +// +// if (auxl < 0 || auxu < 0) { +// std::cerr << "Like-image's bounding box must be larger than input's" << std::endl; +// return ERR_NOT_LIKE_LARGER; +// } +// +// padLower[i] = (PadBoundType)auxl; +// padUpper[i] = (PadBoundType)auxu; +// } +// +// return ERR_SUCCESS; +// } int main(int argc, char** argv) { - const DimType dim = 3; +/* const DimType dim = 3; typedef short PixelType; typedef itk::Image ImageType; typedef itk::ImageFileReader ImageReaderType; typedef itk::ImageFileWriter ImageWriterType; typedef itk::ConstantPadImageFilter PadFilterType; - typedef PadFilterType::SizeValueType PadBoundType; + typedef PadFilterType::SizeValueType PadBoundType;*/ GGO(clitkPadImage, args_info); - - ImageReaderType::Pointer reader = ImageReaderType::New(); - reader->SetFileName(args_info.input_arg); - reader->Update(); - - PadBoundType pad_lower[dim], pad_upper[dim]; - ImageType::Pointer input = reader->GetOutput(); - if (args_info.like_given) { - int err = pad_like(input, args_info.like_arg, pad_lower, pad_upper); - if (err) { - std::cerr << "Error processing like image." << std::endl; - return err; - } - } - else { - for (DimType i = 0; i < dim; i++) { - pad_lower[i] = args_info.lower_arg[i]; - pad_upper[i] = args_info.upper_arg[i]; - } + + // Filter + typedef clitk::PadImageGenericFilter FilterType; + FilterType::Pointer filter = FilterType::New(); + + filter->SetArgsInfo(args_info); + + try { + filter->Update(); + } catch(std::runtime_error e) { + std::cout << e.what() << std::endl; } - PadFilterType::Pointer filter = PadFilterType::New(); - filter->SetPadLowerBound(pad_lower); - filter->SetPadUpperBound(pad_upper); - filter->SetInput(input); - filter->SetConstant(args_info.value_arg); - filter->Update(); - - ImageType::Pointer output = filter->GetOutput(); - ImageWriterType::Pointer writer = ImageWriterType::New(); - writer->SetInput(output); - writer->SetFileName(args_info.output_arg); - writer->Update(); +// ImageReaderType::Pointer reader = ImageReaderType::New(); +// reader->SetFileName(args_info.input_arg); +// reader->Update(); +// +// PadBoundType pad_lower[dim], pad_upper[dim]; +// ImageType::Pointer input = reader->GetOutput(); +// if (args_info.like_given) { +// int err = pad_like(input, args_info.like_arg, pad_lower, pad_upper); +// if (err) { +// std::cerr << "Error processing like image." << std::endl; +// return err; +// } +// } +// else { +// for (DimType i = 0; i < dim; i++) { +// pad_lower[i] = args_info.lower_arg[i]; +// pad_upper[i] = args_info.upper_arg[i]; +// } +// } +// +// PadFilterType::Pointer filter = PadFilterType::New(); +// filter->SetPadLowerBound(pad_lower); +// filter->SetPadUpperBound(pad_upper); +// filter->SetInput(input); +// filter->SetConstant(args_info.value_arg); +// filter->Update(); +// +// ImageType::Pointer output = filter->GetOutput(); +// ImageWriterType::Pointer writer = ImageWriterType::New(); +// writer->SetInput(output); +// writer->SetFileName(args_info.output_arg); +// writer->Update(); - return ERR_SUCCESS; + return EXIT_SUCCESS; } diff --git a/tools/clitkPadImage.ggo b/tools/clitkPadImage.ggo index 6f21563..c83dfff 100644 --- a/tools/clitkPadImage.ggo +++ b/tools/clitkPadImage.ggo @@ -1,5 +1,5 @@ -#File clitkCropImage.ggo -package "clitkCropImage" +#File clitkPadImage.ggo +package "clitkPadImage" version "1.0" purpose "Pad an image according to a given extends or like another image" diff --git a/tools/clitkPadImageGenericFilter.cxx b/tools/clitkPadImageGenericFilter.cxx new file mode 100644 index 0000000..49d4075 --- /dev/null +++ b/tools/clitkPadImageGenericFilter.cxx @@ -0,0 +1,191 @@ +/*========================================================================= + Program: vv http://www.creatis.insa-lyon.fr/rio/vv + + Authors belong to: + - University of LYON http://www.universite-lyon.fr/ + - Léon Bérard cancer center http://www.centreleonberard.fr + - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the copyright notices for more information. + + It is distributed under dual licence + + - BSD See included LICENSE.txt file + - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html +===========================================================================**/ +#ifndef clitkPadImageGenericFilter_cxx +#define clitkPadImageGenericFilter_cxx + +/* ================================================= + * @file clitkPadImageGenericFilter.cxx + * @author + * @date + * + * @brief + * + ===================================================*/ + +#include "clitkPadImageGenericFilter.h" + +// itk +#include + + +namespace clitk +{ + + + //----------------------------------------------------------- + // Constructor + //----------------------------------------------------------- + PadImageGenericFilter::PadImageGenericFilter(): + ImageToImageGenericFilter("PadImage") + { + cmdline_parser_clitkPadImage_init(&mArgsInfo); + InitializeImageType<2>(); + InitializeImageType<3>(); + //InitializeImageType<4>(); + } + + //-------------------------------------------------------------------- + template + void PadImageGenericFilter::InitializeImageType() + { + ADD_DEFAULT_IMAGE_TYPES(Dim); + //ADD_IMAGE_TYPE(Dim, uchar); + //ADD_IMAGE_TYPE(Dim, short); + // ADD_IMAGE_TYPE(Dim, uint); + // ADD_IMAGE_TYPE(Dim, ulong); + // ADD_IMAGE_TYPE(Dim, int); + // ADD_IMAGE_TYPE(Dim, float); + } + //-------------------------------------------------------------------- + + //-------------------------------------------------------------------- + void PadImageGenericFilter::SetArgsInfo(const args_info_type& a) + { + mArgsInfo=a; + SetIOVerbose(mArgsInfo.verbose_flag); + if (mArgsInfo.input_given) AddInputFilename(mArgsInfo.input_arg); + if (mArgsInfo.output_given) AddOutputFilename(mArgsInfo.output_arg); + } + //-------------------------------------------------------------------- + + //-------------------------------------------------------------------- + // Update with the number of dimensions and the pixeltype + //-------------------------------------------------------------------- + template + void PadImageGenericFilter::UpdateWithInputImageType() + { + typedef itk::ConstantPadImageFilter PadFilterType; + typedef typename PadFilterType::SizeValueType PadBoundType; + + // Reading input + typename ImageType::Pointer input = this->template GetInput(0); + + const unsigned int dim = ImageType::ImageDimension; + PadBoundType pad_lower[dim], pad_upper[dim]; + if (mArgsInfo.like_given) { + int err = PadLike(input, pad_lower, pad_upper); + if (err) { + std::cerr << "Error processing like image." << std::endl; + return; + } + } + else { + if (mArgsInfo.lower_given != dim || mArgsInfo.upper_given != dim) + { + std::cerr << "The number of lower and upper padding parameters must be equal to the image dimension." << std::endl; + return; + } + + for (unsigned int i = 0; i < dim; i++) { + pad_lower[i] = mArgsInfo.lower_arg[i]; + pad_upper[i] = mArgsInfo.upper_arg[i]; + } + } + + typename PadFilterType::Pointer filter = PadFilterType::New(); + filter->SetPadLowerBound(pad_lower); + filter->SetPadUpperBound(pad_upper); + filter->SetInput(input); + filter->SetConstant(mArgsInfo.value_arg); + filter->Update(); + + // Prepare output + typename ImageType::Pointer output; + output = filter->GetOutput(); + + // Write/Save results + this->template SetNextOutput(output); + } + //-------------------------------------------------------------------- + + //-------------------------------------------------------------------- + // Update with the number of dimensions and the pixeltype + //-------------------------------------------------------------------- + template + int PadImageGenericFilter::PadLike(typename ImageType::Pointer input, PadBoundType* padLower, PadBoundType* padUpper) + { + if (mArgsInfo.verbose_flag) + std::cout << "PadLike - IN" << std::endl; + + typedef typename ImageType::SpacingType SpacingType; + typedef typename ImageType::RegionType RegionType; + typedef typename ImageType::SizeType SizeType; + typedef typename ImageType::IndexType IndexType; + typedef typename ImageType::PointType PointType; + typedef typename ImageType::PointValueType PointValueType; + + if (mArgsInfo.verbose_flag) + std::cout << "Reading like image: " << mArgsInfo.like_arg << ::endl; + + typedef itk::ImageFileReader ImageReaderType; + typename ImageReaderType::Pointer reader = ImageReaderType::New(); + reader->SetFileName(mArgsInfo.like_arg); + reader->Update(); + + typename ImageType::Pointer like_image = reader->GetOutput(); + + if (mArgsInfo.verbose_flag) + std::cout << "Calculating padding." << std::endl; + + SpacingType spacing = input->GetSpacing(), like_spacing = like_image->GetSpacing(); + if (spacing != like_spacing) { + std::cerr << "Like-image must have same spacing as input: " << spacing << " " << like_spacing << std::endl; + return ERR_NOT_SAME_SPACING; + } + + SizeType size = input->GetLargestPossibleRegion().GetSize(), like_size = like_image->GetLargestPossibleRegion().GetSize(); + PointType origin = input->GetOrigin(), like_origin = like_image->GetOrigin(); + + PointType lower_bound, like_lower_bound; + PointType upper_bound, like_upper_bound; + PointValueType auxl = 0, auxu = 0; + for (unsigned int i = 0; i < dim; i++) { + lower_bound[i] = origin[i]; + like_lower_bound[i] = like_origin[i]; + auxl = itk::Math::Round(((lower_bound[i] - like_lower_bound[i])/spacing[i])); + + upper_bound[i] = (lower_bound[i] + size[i]*spacing[i]); + like_upper_bound[i] = (like_lower_bound[i] + like_size[i]*spacing[i]); + auxu = itk::Math::Round(((like_upper_bound[i] - upper_bound[i])/spacing[i])); + + if (auxl < 0 || auxu < 0) { + std::cerr << "Like-image's bounding box must be larger than input's" << std::endl; + return ERR_NOT_LIKE_LARGER; + } + + padLower[i] = (PadBoundType)auxl; + padUpper[i] = (PadBoundType)auxu; + } + + if (mArgsInfo.verbose_flag) + std::cout << "PadLike - OUT" << std::endl; + return ERR_SUCCESS; + } +} //end clitk + +#endif //#define clitkPadImageGenericFilter_cxx diff --git a/tools/clitkPadImageGenericFilter.h b/tools/clitkPadImageGenericFilter.h new file mode 100644 index 0000000..3aa9318 --- /dev/null +++ b/tools/clitkPadImageGenericFilter.h @@ -0,0 +1,77 @@ +/*========================================================================= + Program: vv http://www.creatis.insa-lyon.fr/rio/vv + + Authors belong to: + - University of LYON http://www.universite-lyon.fr/ + - Léon Bérard cancer center http://www.centreleonberard.fr + - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the copyright notices for more information. + + It is distributed under dual licence + + - BSD See included LICENSE.txt file + - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html +===========================================================================**/ + +#ifndef CLITKPADIMAGEGENERICFILTER_H +#define CLITKPADIMAGEGENERICFILTER_H + +// clitk +#include "clitkIO.h" +#include "clitkImageToImageGenericFilter.h" +#include "clitkPadImage_ggo.h" + + +//-------------------------------------------------------------------- +namespace clitk +{ + + class ITK_EXPORT PadImageGenericFilter: + public ImageToImageGenericFilter + { + public: + enum + { + ERR_SUCCESS = 0, + ERR_NOT_SAME_SPACING = -1, + ERR_NOT_LIKE_LARGER = -2 + }; + + //-------------------------------------------------------------------- + PadImageGenericFilter(); + + //-------------------------------------------------------------------- + typedef PadImageGenericFilter Self; + typedef ImageToImageGenericFilter Superclass; + typedef itk::SmartPointer Pointer; + typedef itk::SmartPointer ConstPointer; + typedef args_info_clitkPadImage args_info_type; + + //-------------------------------------------------------------------- + itkNewMacro(Self); + itkTypeMacro( PadImageGenericFilter, LightObject ); + + //-------------------------------------------------------------------- + void SetArgsInfo(const args_info_type& a); + + //-------------------------------------------------------------------- + // Main function called each time the filter is updated + template + void UpdateWithInputImageType(); + + protected: + template void InitializeImageType(); + + template + int PadLike(typename ImageType::Pointer input, PadBoundType* padLower, PadBoundType* padUpper); + + args_info_type mArgsInfo; + + };// end class + //-------------------------------------------------------------------- +} // end namespace clitk + +#endif // #define CLITKPADIMAGEGENERICFILTER_H -- 2.45.1