From cd168a5da1379212bffc8d0dbce605d6834c2be5 Mon Sep 17 00:00:00 2001 From: Romain Garrigues <romain.garrigues@c-s.fr> Date: Thu, 20 Dec 2007 10:26:19 +0000 Subject: [PATCH] Adaptation du filtre itk::ImportImageFilter pour que ca puisse fonctionner avec autre chose que des itk::Image => Creation du filtre otb::ImportImageFilter --- Code/BasicFilters/otbImportImageFilter.h | 181 ++++++++++++ Code/BasicFilters/otbImportImageFilter.txx | 272 ++++++++++++++++++ .../DataRepresentation/Image/CMakeLists.txt | 3 + Examples/DataRepresentation/Image/Image5.cxx | 32 ++- 4 files changed, 473 insertions(+), 15 deletions(-) create mode 100644 Code/BasicFilters/otbImportImageFilter.h create mode 100644 Code/BasicFilters/otbImportImageFilter.txx diff --git a/Code/BasicFilters/otbImportImageFilter.h b/Code/BasicFilters/otbImportImageFilter.h new file mode 100644 index 0000000000..7a836e022e --- /dev/null +++ b/Code/BasicFilters/otbImportImageFilter.h @@ -0,0 +1,181 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + Some parts of this code are derived from ITK. See ITKCopyright.txt + for details. + + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef __otbImportImageFilter_h +#define __otbImportImageFilter_h + +#include "itkImageSource.h" + +namespace otb +{ + +/** \class ImportImageFilter + * \brief Import data from a standard C array into an Image Type + * + * ImportImageFilter provides a mechanism for importing data into an Image Type. + * ImportImageFilter is an image source, so it behaves like any other pipeline + * object. + * + * This class is templated over the output Image Type + * + */ + +template <typename TOutputImageType> +class ITK_EXPORT ImportImageFilter: + public itk::ImageSource< TOutputImageType > +{ +public: + /** Typedef for the output image. */ + typedef TOutputImageType OutputImageType; + typedef typename OutputImageType::Pointer OutputImagePointer; + typedef typename OutputImageType::SpacingType SpacingType; + typedef typename OutputImageType::PointType OriginType; + + + /** Standard class typedefs. */ + typedef ImportImageFilter Self; + typedef itk::ImageSource<OutputImageType> Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(ImportImageFilter,itk::ImageSource); + + /** Index typedef support. An index is used to access pixel values. */ + typedef itk::Index<OutputImageType::ImageDimension> IndexType; + + /** Size typedef support. A size is used to define region bounds. */ + typedef itk::Size<OutputImageType::ImageDimension> SizeType; + + /** Region typedef support. A region is used to specify a + * subset of an image. */ + typedef itk::ImageRegion<OutputImageType::ImageDimension> RegionType; + + /** Type of the output image pixel type. */ + typedef typename OutputImageType::PixelType TPixel; + + /** Get the pointer from which the image data is imported. */ + TPixel *GetImportPointer(); + + /** Set the pointer from which the image data is imported. "num" is + * the number of pixels in the block of memory. If + * "LetFilterManageMemory" is false, then the this filter will + * not free the memory in its destructor and the application providing the + * buffer retains the responsibility of freeing the memory for this image + * data. If "LetFilterManageMemory" is true, then this class + * will free the memory when this object is destroyed. */ + void SetImportPointer(TPixel *ptr, unsigned long num, + bool LetFilterManageMemory); + + /** Set the region object that defines the size and starting index + * for the imported image. This will serve as the LargestPossibleRegion, + * the BufferedRegion, and the RequestedRegion. + * \sa ImageRegion */ + void SetRegion(const RegionType ®ion) + { if (m_Region != region) {m_Region = region; this->Modified();} }; + + /** Get the region object that defines the size and starting index + * for the imported image. This will serve as the LargestPossibleRegion, + * the BufferedRegion, and the RequestedRegion. + * \sa ImageRegion */ + const RegionType& GetRegion() const + { return m_Region;}; + + /** Set the spacing (size of a pixel) of the image. + * \sa GetSpacing() */ + itkSetVectorMacro(Spacing, const double, OutputImageType::ImageDimension); + itkSetVectorMacro(Spacing, const float, OutputImageType::ImageDimension); + + /** Get the spacing (size of a pixel) of the image. + * \sa SetSpacing() */ + itkGetVectorMacro(Spacing, const double, OutputImageType::ImageDimension); + void SetSpacing( const SpacingType & spacing ); + + /** Set the origin of the image. + * \sa GetOrigin() */ + itkSetVectorMacro(Origin, const double, OutputImageType::ImageDimension); + itkSetVectorMacro(Origin, const float, OutputImageType::ImageDimension); + void SetOrigin( const OriginType & origin ); + + /** Get the origin of the image. + * \sa SetOrigin() */ + itkGetVectorMacro(Origin, const double, OutputImageType::ImageDimension); + + typedef itk::Matrix<double, OutputImageType::ImageDimension, OutputImageType::ImageDimension> DirectionType; + + /** Set the direction of the image + * \sa GetDirection() */ + virtual void SetDirection( const DirectionType direction ); + /** Get the direction of the image + * \sa SetDirection */ + itkGetConstReferenceMacro(Direction, DirectionType); + +protected: + ImportImageFilter(); + ~ImportImageFilter(); + void PrintSelf(std::ostream& os, itk::Indent indent) const; + + /** This filter does not actually "produce" any data, rather it "wraps" + * the user supplied data into an itk::Image. */ + virtual void GenerateData(); + + /** This is a source, so it must set the spacing, size, and largest possible + * region for the output image that it will produce. + * \sa ProcessObject::GenerateOutputInformation() */ + virtual void GenerateOutputInformation(); + + /** This filter can only produce the amount of data that it is given, + * so we must override ProcessObject::EnlargeOutputRequestedRegion() + * (The default implementation of a source produces the amount of + * data requested. This source, however, can only produce what it is + * given.) + * + * \sa ProcessObject::EnlargeOutputRequestedRegion() */ + virtual void EnlargeOutputRequestedRegion(itk::DataObject *output); + +private: + ImportImageFilter(const ImportImageFilter &); //purposely not implemented + void operator=(const ImportImageFilter&); //purposely not implemented + + RegionType m_Region; + double m_Spacing[OutputImageType::ImageDimension]; + double m_Origin[OutputImageType::ImageDimension]; + DirectionType m_Direction; + + TPixel* m_ImportPointer; + bool m_FilterManageMemory; + unsigned long m_Size; +}; + +} // end namespace otb + +#ifndef ITK_MANUAL_INSTANTIATION +#include "otbImportImageFilter.txx" +#endif + +#endif + + + + diff --git a/Code/BasicFilters/otbImportImageFilter.txx b/Code/BasicFilters/otbImportImageFilter.txx new file mode 100644 index 0000000000..434228306f --- /dev/null +++ b/Code/BasicFilters/otbImportImageFilter.txx @@ -0,0 +1,272 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + Some parts of this code are derived from ITK. See ITKCopyright.txt + for details. + + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef _otbImportImageFilter_txx +#define _otbImportImageFilter_txx + +#include "otbImportImageFilter.h" +#include "itkObjectFactory.h" + +namespace otb +{ + +/** + * + */ +template <class TOutputImage> +ImportImageFilter<TOutputImage> +::ImportImageFilter() +{ + unsigned int idx; + + for (idx = 0; idx < TOutputImage::ImageDimension; ++idx) + { + m_Spacing[idx] = 1.0; + m_Origin[idx] = 0.0; + } + m_Direction.SetIdentity(); + + m_ImportPointer = 0; + m_FilterManageMemory = false; + m_Size = 0; +} + +/** + * + */ +template <class TOutputImage> +ImportImageFilter<TOutputImage> +::~ImportImageFilter() +{ + if (m_ImportPointer && m_FilterManageMemory) + { + delete [] m_ImportPointer; + } +} + + +/** + * + */ +template <class TOutputImage> +void +ImportImageFilter<TOutputImage> +::PrintSelf(std::ostream& os, itk::Indent indent) const +{ + int i; + + Superclass::PrintSelf(os,indent); + + if (m_ImportPointer) + { + os << indent << "Imported pointer: (" << m_ImportPointer << ")" << std::endl; + } + else + { + os << indent << "Imported pointer: (None)" << std::endl; + } + os << indent << "Import buffer size: " << m_Size << std::endl; + os << indent << "Import buffer size: " << m_Size << std::endl; + os << indent << "Filter manages memory: " << (m_FilterManageMemory ? "true" : "false") << std::endl; + + os << indent << "Spacing: ["; + for (i=0; i < static_cast<int>(TOutputImage::ImageDimension) - 1; i++) + { + os << m_Spacing[i] << ", "; + } + os << m_Spacing[i] << "]" << std::endl; + + os << indent << "Origin: ["; + for (i=0; i < static_cast<int>(TOutputImage::ImageDimension) - 1; i++) + { + os << m_Origin[i] << ", "; + } + os << m_Origin[i] << "]" << std::endl; + os << indent << "Direction: " << std::endl << this->GetDirection() << std::endl; +} + + +/** + * + */ +template <class TOutputImage> +void +ImportImageFilter<TOutputImage> +::SetImportPointer(TPixel *ptr, unsigned long num, bool LetFilterManageMemory) +{ + if (ptr != m_ImportPointer) + { + if (m_ImportPointer && m_FilterManageMemory) + { + delete [] m_ImportPointer; + } + m_ImportPointer = ptr; + this->Modified(); + } + m_FilterManageMemory = LetFilterManageMemory; + m_Size = num; +} + + +/** + * + */ +template <class TOutputImage> +typename ImportImageFilter<TOutputImage>::TPixel* +ImportImageFilter<TOutputImage> +::GetImportPointer() +{ + return m_ImportPointer; +} + + +/** + * + */ +template <class TOutputImage> +void +ImportImageFilter<TOutputImage> +::EnlargeOutputRequestedRegion(itk::DataObject *output) +{ + // call the superclass' implementation of this method + Superclass::EnlargeOutputRequestedRegion(output); + + // get pointer to the output + OutputImagePointer outputPtr = this->GetOutput(); + + // set the requested region to the largest possible region (in this case + // the amount of data that we have) + outputPtr->SetRequestedRegion( outputPtr->GetLargestPossibleRegion() ); +} + + +/** + * + */ +template <class TOutputImage> +void +ImportImageFilter<TOutputImage> +::GenerateOutputInformation() +{ + // call the superclass' implementation of this method + Superclass::GenerateOutputInformation(); + + // get pointer to the output + OutputImagePointer outputPtr = this->GetOutput(); + + // we need to compute the output spacing, the output origin, the + // output image size, and the output image start index + outputPtr->SetSpacing( m_Spacing ); + outputPtr->SetOrigin( m_Origin ); + outputPtr->SetDirection( m_Direction ); + outputPtr->SetLargestPossibleRegion( m_Region ); +} + + +/** + * + */ +template <class TOutputImage> +void +ImportImageFilter<TOutputImage> +::GenerateData() +{ + // Normally, GenerateData() allocates memory. However, the application + // provides the memory for this filter via the SetImportPointer() method. + // Therefore, this filter does not call outputPtr->Allocate(). + + // get pointer to the output + OutputImagePointer outputPtr = this->GetOutput(); + + // the output buffer size is set to the size specified by the user via the + // SetRegion() method. + outputPtr->SetBufferedRegion( outputPtr->GetLargestPossibleRegion() ); + + // pass the pointer down to the container during each Update() since + // a call to Initialize() causes the container to forget the + // pointer. Note that we tell the container NOT to manage the + // memory itself. This filter will properly manage the memory (as + // opposed to the container) if the user wants it to. + outputPtr->GetPixelContainer()->SetImportPointer( m_ImportPointer, + m_Size, false ); +} + + +/** + * + */ +template <class TOutputImage> +void +ImportImageFilter<TOutputImage> +::SetSpacing( const SpacingType & spacing ) +{ + double dspacing[TOutputImage::ImageDimension]; + for(unsigned int i=0; i<TOutputImage::ImageDimension; i++) + { + dspacing[i] = spacing[i]; + } + this->SetSpacing( dspacing ); +} + + +/** + * + */ +template <class TOutputImage> +void +ImportImageFilter<TOutputImage> +::SetOrigin( const OriginType & origin ) +{ + double dorigin[TOutputImage::ImageDimension]; + for(unsigned int i=0; i<TOutputImage::ImageDimension; i++) + { + dorigin[i] = origin[i]; + } + this->SetOrigin( dorigin ); +} + +//---------------------------------------------------------------------------- +template <class TOutputImage> +void +ImportImageFilter<TOutputImage> +::SetDirection(const DirectionType direction ) +{ + bool modified = false; + for (unsigned int r = 0; r < TOutputImage::ImageDimension; r++) + { + for (unsigned int c = 0; c < TOutputImage::ImageDimension; c++) + { + if (m_Direction[r][c] != direction[r][c]) + { + m_Direction[r][c] = direction[r][c]; + modified = true; + } + } + } + if (modified) + { + this->Modified(); + } +} + + +} // end namespace otb + +#endif diff --git a/Examples/DataRepresentation/Image/CMakeLists.txt b/Examples/DataRepresentation/Image/CMakeLists.txt index 27de418319..61f64c07bc 100644 --- a/Examples/DataRepresentation/Image/CMakeLists.txt +++ b/Examples/DataRepresentation/Image/CMakeLists.txt @@ -78,6 +78,9 @@ ADD_TEST(ImageAdaptor4Test2 ${EXE_TESTS} # ------- Image5Test---------- ADD_TEST(Image5Test ${EXE_TESTS} + --compare-n-images ${TOL} 1 + ${BASELINE}/Image5.png + ${TEMP}/Image5.png Image5Test ${TEMP}/Image5.png ) diff --git a/Examples/DataRepresentation/Image/Image5.cxx b/Examples/DataRepresentation/Image/Image5.cxx index 51d6f87101..836a664ca6 100644 --- a/Examples/DataRepresentation/Image/Image5.cxx +++ b/Examples/DataRepresentation/Image/Image5.cxx @@ -28,7 +28,7 @@ // class. This is particularly useful for interfacing with other software // systems. Many systems use a contiguous block of memory as a buffer // for image pixel data. The current example assumes this is the case and -// feeds the buffer into an \doxygen{itk}{ImportImageFilter}, thereby producing an +// feeds the buffer into an \doxygen{otb}{ImportImageFilter}, thereby producing an // Image as output. // @@ -37,8 +37,8 @@ // ImportImageFilter. This example is set up so that on execution, the // user must provide the name of an output file as a command-line argument. // -// \index{itk::ImportImageFilter!Instantiation} -// \index{itk::ImportImageFilter!Header} +// \index{otb::ImportImageFilter!Instantiation} +// \index{otb::ImportImageFilter!Header} // // First, the header file of the ImportImageFilter class must be // included. @@ -47,8 +47,9 @@ // Software Guide : BeginCodeSnippet -#include "itkImage.h" -#include "itkImportImageFilter.h" +#include "otbImage.h" +#include "otbImportImageFilter.h" + // Software Guide : EndCodeSnippet #include "otbImageFileWriter.h" @@ -73,7 +74,7 @@ int main(int argc, char * argv[]) // Software Guide : BeginCodeSnippet typedef unsigned char PixelType; const unsigned int Dimension = 2; - typedef itk::Image< PixelType, Dimension > ImageType; + typedef otb::Image< PixelType, Dimension > ImageType; // Software Guide : EndCodeSnippet @@ -82,12 +83,12 @@ int main(int argc, char * argv[]) // The type of the ImportImageFilter is instantiated in the // following line. // - // \index{itk::ImportImageFilter!Instantiation} + // \index{otb::ImportImageFilter!Instantiation} // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet - typedef itk::ImportImageFilter< PixelType, Dimension > ImportFilterType; + typedef otb::ImportImageFilter< ImageType > ImportFilterType; // Software Guide : EndCodeSnippet @@ -96,8 +97,8 @@ int main(int argc, char * argv[]) // A filter object created using the \code{New()} method is then // assigned to a \code{SmartPointer}. // - // \index{itk::ImportImageFilter!Pointer} - // \index{itk::ImportImageFilter!New()} + // \index{otb::ImportImageFilter!Pointer} + // \index{otb::ImportImageFilter!New()} // // Software Guide : EndLatex // @@ -113,9 +114,9 @@ int main(int argc, char * argv[]) // The image size should exactly match the number of pixels available in the // locally allocated buffer. // - // \index{itk::ImportImageFilter!SetRegion()} - // \index{itk::ImportImageFilter!New()} - // \index{itk::ImportImageFilter!New()} + // \index{otb::ImportImageFilter!SetRegion()} + // \index{otb::ImportImageFilter!New()} + // \index{otb::ImportImageFilter!New()} // // Software Guide : EndLatex // @@ -188,10 +189,10 @@ int main(int argc, char * argv[]) // // Here we fill up the buffer with a binary sphere. We use simple // \code{for()} loops here similar to those found in the C or FORTRAN - // programming languages. Note that ITK + // programming languages. Note that otb // does not use \code{for()} loops in its internal code to access // pixels. All pixel access tasks are instead performed using - // \doxygen{itk}{ImageIterator}s that support the management of + // \doxygen{otb}{ImageIterator}s that support the management of // n-dimensional images. // // Software Guide : EndLatex @@ -266,6 +267,7 @@ int main(int argc, char * argv[]) { std::cerr << "Exception caught !" << std::endl; std::cerr << exp << std::endl; + return -1; } -- GitLab