From f1908566cf3af73f5dc931941b6f3269b9d4c0f7 Mon Sep 17 00:00:00 2001
From: Gregoire Mercier <gregoire.mercier@telecom-bretagne.eu>
Date: Mon, 13 Apr 2009 14:36:22 +0200
Subject: [PATCH] ADD: directional subsampling in
 otbSubsampledImageRegionConstIterator

---
 Code/BasicFilters/otbSubsampleImageFilter.h   | 18 +++++--
 Code/BasicFilters/otbSubsampleImageFilter.txx | 47 +++++++++++++------
 .../otbSubsampledImageRegionConstIterator.h   | 44 ++++++++++-------
 .../otbSubsampledImageRegionConstIterator.txx | 12 +++--
 Code/IO/otbImageSeriesFileReader.h            |  6 ++-
 Code/MultiScale/otbStationaryFilterBank.h     |  3 ++
 6 files changed, 88 insertions(+), 42 deletions(-)

diff --git a/Code/BasicFilters/otbSubsampleImageFilter.h b/Code/BasicFilters/otbSubsampleImageFilter.h
index 4e2e7a4dd9..d733edb289 100644
--- a/Code/BasicFilters/otbSubsampleImageFilter.h
+++ b/Code/BasicFilters/otbSubsampleImageFilter.h
@@ -75,6 +75,7 @@ public:
   typedef TInputImage InputImageType;
   typedef typename InputImageType::RegionType InputImageRegionType;
   typedef typename InputImageType::IndexType InputImageIndexType;
+  typedef typename InputImageIndexType::IndexValueType InputImageIndexValueType;
 
   typedef TOutputImage OutputImageType;
   typedef typename OutputImageType::RegionType OutputImageRegionType;
@@ -83,16 +84,25 @@ public:
   typedef typename OutputImageType::PixelType OutputPixelType;
 
   /** Set/Get the SubsampleFactor */
-  itkGetMacro(SubsampleFactor,unsigned int);
-  itkSetMacro(SubsampleFactor,unsigned int);
+  itkGetMacro(SubsampleFactor,const InputImageIndexType &);
+  itkSetMacro(SubsampleFactor,InputImageIndexType &);
+  void SetSubSampleFactor( InputImageIndexValueType factor )
+  {
+    InputImageIndexType indexFactor;
+    indexFactor.Fill( factor );
+    SetSubSampleFactor( indexFactor );
+  }
 
 protected:
   SubsampleImageFilter ()
   {
-    m_SubsampleFactor = 1;
+    m_SubsampleFactor.Fill( 1 );
   }
   virtual ~SubsampleImageFilter() {}
 
+  /** Internal test function to check if there is any direction to subsample */
+  bool IsSubsampleFactorOne () const;
+
   /** Since input and output image are very likely to be of different size. 
    * Region estimation functions has to be reimplemented
    */
@@ -116,7 +126,7 @@ private:
   SubsampleImageFilter ( const Self & ); // purposely not implemented
   void operator= ( const Self & ); // purposely not implemented
 
-  unsigned int m_SubsampleFactor;
+  InputImageIndexType m_SubsampleFactor;
 }; // end of class 
 
 } // end of namespace otb
diff --git a/Code/BasicFilters/otbSubsampleImageFilter.txx b/Code/BasicFilters/otbSubsampleImageFilter.txx
index 01eba921ee..1c6259c91e 100644
--- a/Code/BasicFilters/otbSubsampleImageFilter.txx
+++ b/Code/BasicFilters/otbSubsampleImageFilter.txx
@@ -40,7 +40,27 @@ SubsampleImageFilter< TInputImage, TOutputImage, TDirectionOfTransformation >
 ::PrintSelf( std::ostream & os, itk::Indent indent ) const
 {
   Superclass::PrintSelf( os, indent );
-  os << indent << "SubsampleFactor = " << m_SubsampleFactor << "\n";
+  os << indent << "SubsampleFactor = [" << m_SubsampleFactor[0];
+  for ( unsigned int i = 1; i < InputImageDimension; i++ )
+  {
+    os << ", " << m_SubsampleFactor[i];
+  }
+  os << "]\n";
+}
+
+template < class TInputImage, class TOutputImage,
+            InverseOrForwardTransformationEnum TDirectionOfTransformation >
+bool
+SubsampleImageFilter< TInputImage, TOutputImage, TDirectionOfTransformation >
+::IsSubsampleFactorOne () const
+{
+  for ( unsigned int i = 0; i < InputImageDimension; i++ )
+  {
+    if ( m_SubsampleFactor[i] != 1 )
+      return false;
+  }
+
+  return true;
 }
 
 template < class TInputImage, class TOutputImage,
@@ -51,7 +71,7 @@ SubsampleImageFilter< TInputImage, TOutputImage, TDirectionOfTransformation >
 {
   Superclass::GenerateOutputInformation();
 
-  if ( GetSubsampleFactor() > 1 )
+  if ( !IsSubsampleFactorOne() )
   {
     OutputImageRegionType newRegion;
     this->CallCopyInputRegionToOutputRegion( newRegion, this->GetInput()->GetLargestPossibleRegion() );
@@ -78,8 +98,8 @@ SubsampleImageFilter< TInputImage, TOutputImage, TDirectionOfTransformation >
 
     for ( unsigned int i = 0; i < InputImageDimension; i++ )
     {
-      destIndex[i] = srcIndex[i] / GetSubsampleFactor();
-      destSize[i] = ( srcSize[i] - 1 ) / GetSubsampleFactor() + 1;
+      destIndex[i] = srcIndex[i] / m_SubsampleFactor[i];
+      destSize[i] = ( srcSize[i] - 1 ) / m_SubsampleFactor[i] + 1;
     }
 
     destRegion.SetIndex( destIndex );
@@ -106,8 +126,8 @@ SubsampleImageFilter< TInputImage, TOutputImage, TDirectionOfTransformation >
 
     for ( unsigned int i = 0; i < InputImageDimension; i++ )
     {
-      destIndex[i] = srcIndex[i] * GetSubsampleFactor();
-      destSize[i] = ( srcSize[i] - 1 ) * GetSubsampleFactor() + 1;
+      destIndex[i] = srcIndex[i] * m_SubsampleFactor[i];
+      destSize[i] = ( srcSize[i] - 1 ) * m_SubsampleFactor[i] + 1;
     }
 
     destRegion.SetIndex( destIndex );
@@ -122,19 +142,16 @@ SubsampleImageFilter< TInputImage, TOutputImage, TDirectionOfTransformation >
 ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
                        int threadId)
 {
+  SubsampledImageRegionIterator< OutputImageType > outputIter
+    ( this->GetOutput(), outputRegionForThread );
+  outputIter.SetSubsampleFactor(1);
+  outputIter.GoToBegin();
+
   InputImageRegionType inputRegionForThread;
 	this->CallCopyOutputRegionToInputRegion( inputRegionForThread, outputRegionForThread );
 
   SubsampledImageRegionConstIterator< InputImageType > inputIter 
     ( this->GetInput(), inputRegionForThread );
-  inputIter.SetSubsampleFactor( static_cast<int>( DirectionOfTransformation ) == FORWARD ?
-    GetSubsampleFactor() : 1 );
-  inputIter.GoToBegin();
-
-  SubsampledImageRegionIterator< OutputImageType > outputIter
-    ( this->GetOutput(), outputRegionForThread );
-  outputIter.SetSubsampleFactor(1);
-  outputIter.GoToBegin();
 
   switch ( DirectionOfTransformation )
   {
@@ -164,7 +181,7 @@ SubsampleImageFilter< TInputImage, TOutputImage, TDirectionOfTransformation >
         OutputImageIndexType outputIndex;
         for ( unsigned int i = 0; i < OutputImageDimension; i++ )
         {
-          outputIndex[i] = inputIndex[i] * GetSubsampleFactor();
+          outputIndex[i] = inputIndex[i] * m_SubsampleFactor[i];
         }
         outputIter.SetLocation( outputIndex );
         outputIter.Set( static_cast< OutputPixelType >( inputIter.Get() ) );
diff --git a/Code/Common/otbSubsampledImageRegionConstIterator.h b/Code/Common/otbSubsampledImageRegionConstIterator.h
index c1bfa8cf68..cf33939be5 100644
--- a/Code/Common/otbSubsampledImageRegionConstIterator.h
+++ b/Code/Common/otbSubsampledImageRegionConstIterator.h
@@ -32,6 +32,8 @@ namespace otb {
  * scan over an image. It runs one pixel over X (in row, line, slice... dimensions), 
  * if X is the (integer) value of the SubsampleFactor.
  *
+ * Specific value of the subsample factor may be given for each dimension.
+ *
  * \ingroup ImageIterator
  * \sa StationaryFilterBank
  */
@@ -97,7 +99,7 @@ public:
   /** Default constructor. Needed since we provide a cast constructor. */
   SubsampledImageRegionConstIterator() : itk::ImageRegionConstIterator<TImage> ()
   {
-    m_SubsampleFactor = 1;
+    m_SubsampleFactor.Fill(1);
     m_SubSampledEndOffset = this->m_EndOffset;
 
     const IndexType& startIndex = this->m_Region.GetIndex();
@@ -115,7 +117,7 @@ public:
                                         const RegionType &region)
     : itk::ImageRegionConstIterator< TImage > ( ptr, region )
   {
-    m_SubsampleFactor = 1;
+    m_SubsampleFactor.Fill( 1 );
     m_SubSampledEndOffset = this->m_EndOffset;
 
     const IndexType& startIndex = this->m_Region.GetIndex();
@@ -136,7 +138,7 @@ public:
   SubsampledImageRegionConstIterator( const itk::ImageIterator<TImage> &it )
     : itk::ImageRegionConstIterator< TImage >( it )
   {
-    m_SubsampleFactor = 1;
+    m_SubsampleFactor.Fill( 1 );
     m_SubSampledEndOffset = this->m_EndOffset;
 
     const IndexType& startIndex = this->m_Region.GetIndex();
@@ -157,7 +159,7 @@ public:
   SubsampledImageRegionConstIterator( const itk::ImageConstIterator<TImage> &it)
     : itk::ImageRegionConstIterator< TImage >( it )
   {
-    m_SubsampleFactor = 1;
+    m_SubsampleFactor.Fill( 1 );
 
     const IndexType& startIndex = this->m_Region.GetIndex();
     const SizeType& size = this->m_Region.GetSize();
@@ -170,8 +172,16 @@ public:
     m_SubSampledEndOffset = this->m_Image->ComputeOffset( m_LastUsableIndex ) + 1;
   }
 
+  /** Set an isotropic subsampling factor */
+  void SetSubsampleFactor ( typename IndexType::IndexValueType factor )
+  {
+    IndexType index;
+    index.Fill( factor );
+    SetSubsampleFactor( index );
+  }
+
   /** Set / Get the subsample factor */
-  void SetSubsampleFactor ( unsigned int factor )
+  void SetSubsampleFactor ( const IndexType & factor )
   {
     this->m_SubsampleFactor = factor;
 
@@ -182,13 +192,13 @@ public:
     for ( unsigned int i = 0; i < ImageIteratorDimension; i++ )
     {
       m_LastUsableIndex[i] = startIndex[i]
-        + static_cast<IndexValueType>( m_SubsampleFactor * ( (size[i]-1) / m_SubsampleFactor ) );
+        + static_cast<IndexValueType>( m_SubsampleFactor[i] * ( (size[i]-1) / m_SubsampleFactor[i] ) );
     }
 
     m_SubSampledEndOffset = this->m_Image->ComputeOffset( m_LastUsableIndex ) + 1;
   }
 
-  unsigned int GetSubsampleFactor () const
+  const IndexType & GetSubsampleFactor () const
   {
     return this->m_SubsampleFactor;
   }
@@ -203,7 +213,7 @@ public:
 
     this->m_SpanBeginOffset = this->m_Offset;
     this->m_SpanEndOffset = this->m_Offset 
-                            + static_cast<IndexValueType>( m_SubsampleFactor * ((size[0]-1) / m_SubsampleFactor) )
+                            + static_cast<IndexValueType>( m_SubsampleFactor[0] * ((size[0]-1) / m_SubsampleFactor[0]) )
                             + 1;
   }
 
@@ -259,14 +269,14 @@ public:
   {
     // On the contrary to itk::ImageRegionConstIterator, m_Offset to
     // not incremented before the test
-    if( this->m_Offset + m_SubsampleFactor >= this->m_SpanEndOffset )
+    if( this->m_Offset + m_SubsampleFactor[0] >= this->m_SpanEndOffset )
     {
       this->Increment();
     }
     else
     {
       // Now, the increment is performed
-      this->m_Offset += m_SubsampleFactor;
+      this->m_Offset += m_SubsampleFactor[0];
     }
     return *this;
   }
@@ -282,14 +292,14 @@ public:
   {
     // On the contrary to itk::ImageRegionConstIterator, m_Offset
     // is not decremented here (it may become negative!)
-    if ( this->m_Offset < this->m_SpanBeginOffset + m_SubsampleFactor ) 
+    if ( this->m_Offset < this->m_SpanBeginOffset + m_SubsampleFactor[0] ) 
     {
       this->Decrement();
     }
     else
     {
       // Now we can
-      this->m_Offset -= m_SubsampleFactor;
+      this->m_Offset -= m_SubsampleFactor[0];
     }
     return *this;
   }
@@ -303,7 +313,7 @@ public:
 
     const SizeType& size = this->m_Region.GetSize();
     this->m_SpanEndOffset = this->m_Offset 
-                            + static_cast<IndexValueType>( m_SubsampleFactor * ((size[0]-1) / m_SubsampleFactor) )
+                            + static_cast<IndexValueType>( m_SubsampleFactor[0] * ((size[0]-1) / m_SubsampleFactor[0]) )
                             + 1;
     this->m_SpanBeginOffset = this->m_Offset;
   }
@@ -314,7 +324,7 @@ public:
 
     const SizeType& size = this->m_Region.GetSize();
     this->m_SpanEndOffset = this->m_Offset 
-                            + static_cast<IndexValueType>( m_SubsampleFactor * ((size[0]-1) / m_SubsampleFactor) )
+                            + static_cast<IndexValueType>( m_SubsampleFactor[0] * ((size[0]-1) / m_SubsampleFactor[0]) )
                             + 1;
     this->m_SpanBeginOffset = this->m_Offset;
   }
@@ -339,9 +349,9 @@ public:
 
     for ( unsigned int i = 0; i < ImageIteratorDimension; i++ )
     {
-      startIndex[i] /= m_SubsampleFactor;
+      startIndex[i] /= m_SubsampleFactor[i];
       --size[i];
-      size[i] /= m_SubsampleFactor;
+      size[i] /= m_SubsampleFactor[i];
       ++size[i];
     }
 
@@ -359,7 +369,7 @@ public:
   }
 
 protected:
-  unsigned int m_SubsampleFactor;
+  IndexType m_SubsampleFactor;
   unsigned long m_SubSampledEndOffset;
   IndexType m_LastUsableIndex;
 
diff --git a/Code/Common/otbSubsampledImageRegionConstIterator.txx b/Code/Common/otbSubsampledImageRegionConstIterator.txx
index 57755008f5..51d1792836 100644
--- a/Code/Common/otbSubsampledImageRegionConstIterator.txx
+++ b/Code/Common/otbSubsampledImageRegionConstIterator.txx
@@ -42,7 +42,7 @@ SubsampledImageRegionConstIterator< TImage >
 
   // Check to see if we are past the last pixel in the region
   // Note that ++ind[0] moves to the next pixel along the row.
-  ind[0] += static_cast<IndexValueType>(m_SubsampleFactor);
+  ind[0] += m_SubsampleFactor[0];
   bool done = (ind[0] > m_LastUsableIndex[0] );
   for (unsigned int i=1; done && i < ImageIteratorDimension; i++)
   {
@@ -58,12 +58,13 @@ SubsampledImageRegionConstIterator< TImage >
       && (ind[dim] > m_LastUsableIndex[dim]) )
     {
       ind[dim] = startIndex[dim];
-      ind[++dim] += static_cast<IndexValueType>(m_SubsampleFactor);
+      dim++;
+      ind[dim] += m_SubsampleFactor[dim];
     }
   }
   this->m_Offset = this->m_Image->ComputeOffset( ind );
   this->m_SpanEndOffset = this->m_Offset 
-                            + static_cast<IndexValueType>( m_SubsampleFactor * ((size[0]-1) / m_SubsampleFactor) )
+                            + static_cast<IndexValueType>( m_SubsampleFactor[0] * ((size[0]-1) / m_SubsampleFactor[0]) )
                             + 1;
   this->m_SpanBeginOffset = this->m_Offset;
 }
@@ -83,7 +84,7 @@ SubsampledImageRegionConstIterator< TImage >
 
   // Check to see if we are past the first pixel in the region
   // Note that --ind[0] moves to the previous pixel along the row.
-  ind[0] -= static_cast< IndexValueType >( m_SubsampleFactor );
+  ind[0] -= m_SubsampleFactor[0];
   done = (ind[0] <= startIndex[0] - 1);
   for (unsigned int i=1; done && i < ImageIteratorDimension; i++)
   {
@@ -99,7 +100,8 @@ SubsampledImageRegionConstIterator< TImage >
             && (ind[dim] < startIndex[dim]) )
     {
       ind[dim] = m_LastUsableIndex[dim];
-      ind[++dim] -= static_cast<IndexValueType>( m_SubsampleFactor );
+      dim++;
+      ind[dim] -= m_SubsampleFactor[dim];
     }
   }
   this->m_Offset = this->m_Image->ComputeOffset( ind );
diff --git a/Code/IO/otbImageSeriesFileReader.h b/Code/IO/otbImageSeriesFileReader.h
index 538c15fb14..7f4ac334f2 100644
--- a/Code/IO/otbImageSeriesFileReader.h
+++ b/Code/IO/otbImageSeriesFileReader.h
@@ -35,7 +35,11 @@ namespace otb {
 
 /**
   * \class ImagerSeriesFileReader
-  * \brief Todo
+  * \brief Reader class dedicated to image series reading
+  *
+  * Actually, this class is mostly dedicated to read ENVI META FILE. Specialisations
+  * of the template are given relatively to the king of image (or vector image) used 
+  * in input and/or output.
   *
   *
   * \see ImageFileReader
diff --git a/Code/MultiScale/otbStationaryFilterBank.h b/Code/MultiScale/otbStationaryFilterBank.h
index 7c28379130..07b4239aec 100644
--- a/Code/MultiScale/otbStationaryFilterBank.h
+++ b/Code/MultiScale/otbStationaryFilterBank.h
@@ -72,6 +72,9 @@ namespace otb {
  * At this step, it would have been interesting to implements a DirectionalInnerProductImageFilter to synchronize
  * the pipeline through a composite filter
  * 
+ * The two choice (FORWARD/INVERSE) yield specific implementation of the templates (header redeclaration
+ * is given at bottom of of otbFilterBank.h
+ *
  * \sa LowPassHaarOperator
  * \sa HighPassHaarOperator
  * \sa LowPassSplineBiOrthogonalOperator
-- 
GitLab