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 &region)
+  { 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