diff --git a/Code/Common/otbSubsampledImageRegionConstIterator.h b/Code/Common/otbSubsampledImageRegionConstIterator.h
new file mode 100644
index 0000000000000000000000000000000000000000..9bb299a360b2f9fe7103cc8f6e192a287cee0d06
--- /dev/null
+++ b/Code/Common/otbSubsampledImageRegionConstIterator.h
@@ -0,0 +1,350 @@
+/*=========================================================================
+
+  Program:   ORFEO Toolbox
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+
+  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+  See OTBCopyright.txt for details.
+
+  Copyright (c) Institut Telecom / Telecom Bretagne. All rights reserved. 
+  See ITCopyright.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 __otbSubsampledImageRegionConstIterator_h
+#define __otbSubsampledImageRegionConstIterator_h
+
+#include "itkImageRegionConstIterator.h"
+
+namespace otb {
+
+/** SubsampledImageRegionConstIterator
+ * \brief Regular subsample iterator over an image
+ *
+ * This iterator is a itk::ImageRegionConstIterator that perform a subsampled
+ * scan over an image. It runs one pixel over X (in row, line, slice... dimensions), 
+ * if X is the (integer) value of the SubsampleFactor.
+ *
+ * \ingroup ImageIterator
+ * \sa StationaryFilterBank
+ */
+template < class TImage >
+class ITK_EXPORT SubsampledImageRegionConstIterator 
+	: public itk::ImageRegionConstIterator< TImage >
+{
+public:
+  /** Standard typedef. */
+  typedef SubsampledImageRegionConstIterator	Self;
+  typedef itk::ImageRegionConstIterator<TImage> Superclass;
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(SubsampledImageRegionConstIterator, ImageRegionConstIterator);
+
+  /** Dimension of the image the iterator walks.  This constant is needed so
+   * functions that are templated over image iterator type (as opposed to
+   * being templated over pixel type and dimension) can have compile time
+   * access to the dimension of the image that the iterator walks. */
+  itkStaticConstMacro(ImageIteratorDimension, unsigned int,
+                      Superclass::ImageIteratorDimension);
+
+  /** Index typedef support. While this was already typdef'ed in the superclass
+   * it needs to be redone here for this subclass to compile properly with gcc. */
+  typedef typename Superclass::IndexType IndexType;
+
+  /** Size typedef support. While this was already typdef'ed in the superclass
+   * it needs to be redone here for this subclass to compile properly with gcc. */
+  typedef typename Superclass::SizeType SizeType;
+
+  /** Region typedef support. */
+  typedef typename Superclass::RegionType   RegionType;
+
+
+  /** Image typedef support. While this was already typdef'ed in the superclass
+   * it needs to be redone here for this subclass to compile properly with gcc. */
+  typedef typename Superclass::ImageType ImageType;
+
+  /** PixelContainer typedef support. Used to refer to the container for
+   * the pixel data. While this was already typdef'ed in the superclass
+   * it needs to be redone here for this subclass to compile properly with gcc. */
+  typedef typename Superclass::PixelContainer         PixelContainer;
+  typedef typename Superclass::PixelContainerPointer  PixelContainerPointer;
+  
+  /** Internal Pixel Type */
+  typedef typename Superclass::InternalPixelType   InternalPixelType;
+
+  /** External Pixel Type */
+  typedef typename Superclass::PixelType   PixelType;
+
+  /**  Accessor type that convert data between internal and external
+   *  representations. */
+  typedef typename Superclass::AccessorType     AccessorType;
+
+  /** Index value used for pixel location */
+  typedef typename Superclass::IndexValueType IndexValueType;
+
+  /** Default constructor. Needed since we provide a cast constructor. */
+  SubsampledImageRegionConstIterator() : itk::ImageRegionConstIterator<TImage> ()
+  {
+    m_SubsampleFactor = 1;
+    m_SubSampledEndOffset = this->m_EndOffset;
+
+    const IndexType& startIndex = this->m_Region.GetIndex();
+    const SizeType& size = this->m_Region.GetSize();
+
+    for ( unsigned int i = 0; i < ImageIteratorDimension; i++ )
+    {
+      m_LastUsableIndex[i] = startIndex[i] 
+        + static_cast<IndexValueType>( m_SubsampleFactor * ((size[i]-1) / m_SubsampleFactor) );
+    }
+  }
+
+  /** Constructor establishes an iterator to walk a particular image and a
+   * particular region of that image. */
+  SubsampledImageRegionConstIterator ( const ImageType *ptr,
+                                        const RegionType &region)
+    : itk::ImageRegionConstIterator< TImage > ( ptr, region )
+  {
+    m_SubsampleFactor = 1;
+    m_SubSampledEndOffset = this->m_EndOffset;
+
+    const IndexType& startIndex = this->m_Region.GetIndex();
+    const SizeType& size = this->m_Region.GetSize();
+
+    for ( unsigned int i = 0; i < ImageIteratorDimension; i++ )
+    {
+      m_LastUsableIndex[i] = startIndex[i] 
+        + static_cast<IndexValueType>( m_SubsampleFactor * ((size[i]-1) / m_SubsampleFactor) );
+    }
+  }
+
+  /** Constructor that can be used to cast from an ImageIterator to an
+   * SubsampledImageRegionConstIterator. Many routines return an ImageIterator
+   * but for a particular task, you may want an SubsampledImageRegionConstIterator.  
+   * Rather than provide overloaded APIs that return different types of Iterators, itk
+   * returns ImageIterators and uses constructors to cast from an
+   * ImageIterator to a SubsampledImageRegionConstIterator. */
+  SubsampledImageRegionConstIterator( const itk::ImageIterator<TImage> &it )
+    : itk::ImageRegionConstIterator< TImage >( it )
+  {
+    m_SubsampleFactor = 1;
+    m_SubSampledEndOffset = this->m_EndOffset;
+
+    const IndexType& startIndex = this->m_Region.GetIndex();
+    const SizeType& size = this->m_Region.GetSize();
+
+    for ( unsigned int i = 0; i < ImageIteratorDimension; i++ )
+    {
+      m_LastUsableIndex[i] = startIndex[i] 
+        + static_cast<IndexValueType>( m_SubsampleFactor * ((size[i]-1) / m_SubsampleFactor) );
+    }
+  }
+
+  /** Constructor that can be used to cast from an ImageConstIterator to an
+   * SubsampledImageRegionConstIterator. Many routines return an ImageIterator 
+   * but for a particular task, you may want an SubsampledImageRegionConstIterator.  
+   * Rather than provide overloaded APIs that return different types of Iterators, itk
+   * returns ImageIterators and uses constructors to cast from an
+   * ImageIterator to a SubsampledImageRegionConstIterator. */
+  SubsampledImageRegionConstIterator( const itk::ImageConstIterator<TImage> &it)
+    : itk::ImageRegionConstIterator< TImage >( it )
+  {
+    m_SubsampleFactor = 1;
+
+    const IndexType& startIndex = this->m_Region.GetIndex();
+    const SizeType& size = this->m_Region.GetSize();
+
+    for ( unsigned int i = 0; i < ImageIteratorDimension; i++ )
+    {
+      m_LastUsableIndex[i] = startIndex[i] 
+        + static_cast<IndexValueType>( m_SubsampleFactor * ((size[i]-1) / m_SubsampleFactor) );
+    }
+
+  }
+
+  /** Set / Get the subsample factor */
+  void SetSubsampleFactor ( unsigned int factor )
+  {
+    this->m_SubsampleFactor = factor;
+
+    // Evaluate the last possible pixel.
+    const IndexType& startIndex = this->m_Region.GetIndex();
+    const SizeType& size = this->m_Region.GetSize();
+
+    for ( unsigned int i = 0; i < ImageIteratorDimension; i++ )
+    {
+      m_LastUsableIndex[i] = startIndex[i]
+        + static_cast<IndexValueType>( m_SubsampleFactor * ( (size[i]-1) / m_SubsampleFactor ) );
+    }
+
+    m_SubSampledEndOffset = this->m_Image->ComputeOffset( m_LastUsableIndex ) + 1;
+
+    otbGenericMsgDebugMacro(<<"m_EndOffset=" << this->m_EndOffset);
+    otbGenericMsgDebugMacro(<<"m_SubSampledEndOffset="<< m_SubSampledEndOffset);
+
+    for ( unsigned int i = 0; i < ImageIteratorDimension; i++ )
+    {
+      otbGenericMsgDebugMacro(<<"m_LastUsableIndex[" << i << "] = " << m_LastUsableIndex[i]);
+    }
+
+}
+
+  unsigned int GetSubsampleFactor () const
+  {
+    return this->m_SubsampleFactor;
+  }
+
+  /** Move an iterator to the beginning of the region. "Begin" is
+  * defined as the first pixel in the region. */
+  void GoToBegin()
+  {
+    Superclass::GoToBegin();
+
+    const SizeType& size = this->m_Region.GetSize();
+
+    this->m_SpanBeginOffset = this->m_Offset;
+    this->m_SpanEndOffset = this->m_Offset 
+                            + static_cast<IndexValueType>( m_SubsampleFactor * ((size[0]-1) / m_SubsampleFactor) )
+                            + 1;
+  }
+
+  /** Move an iterator to the end of the region. "End" is defined as
+  * one pixel past the last pixel of the region. */
+  void GoToEnd()
+  {
+    Superclass::GoToEnd();
+    this->m_Offset = m_SubSampledEndOffset - 1;
+    this->m_SpanEndOffset = this->m_Offset + 1;
+    this->m_SpanBeginOffset = this->m_Offset - m_LastUsableIndex[0];
+  }
+
+  /** Is the iterator at the beginning of the region? 
+   * "Begin" is defined here as before the first pixel 
+   * of the region. 
+   * On the contrary to Superclasses, now you cannot get 
+   * *it even if IsAtBegin() is true!!!
+   */
+  bool IsAtBegin(void) const
+  {
+    return ( this->m_Offset <= this->m_BeginOffset );
+  }
+ 
+  /** Is the iterator at the end of the region? 
+   * "End" is defined as past the last candidate pixel 
+   * of the region (under the subsample point of view).
+   *
+   * For instance, if in 1D, the Size is 10 with a subsample 
+   * factor of 4, the last candidate offset would be 8.
+   */
+  bool IsAtEnd(void) const
+  {
+    return ( this->m_Offset >= m_SubSampledEndOffset );
+  }
+
+  /** Set the index. No bounds checking is performed. This is overridden
+   * from the parent because we have an extra ivar.
+   * \sa GetIndex */
+  void SetIndex(const IndexType &ind)
+  {
+    Superclass::SetIndex( ind );
+  }
+
+  /** Increment (prefix) the fastest moving dimension of the iterator's index.
+   * This operator will constrain the iterator within the region (i.e. the
+   * iterator will automatically wrap from the end of the row of the region
+   * to the beginning of the next row of the region) up until the iterator
+   * tries to moves past the last pixel of the region.  Here, the iterator
+   * will be set to be one pixel past the end of the region.
+   * \sa operator++(int) */
+  Self & operator++()
+  {
+    // On the contrary to itk::ImageRegionConstIterator, m_Offset to
+    // not incremented before the test
+    if( this->m_Offset + m_SubsampleFactor >= this->m_SpanEndOffset )
+    {
+      this->Increment();
+    }
+    else
+    {
+      // Now, the increment is performed
+      this->m_Offset += m_SubsampleFactor;
+    }
+    return *this;
+  }
+
+  /** Decrement (prefix) the fastest moving dimension of the iterator's index.
+   * This operator will constrain the iterator within the region (i.e. the
+   * iterator will automatically wrap from the beginning of the row of the region
+   * to the end of the next row of the region) up until the iterator
+   * tries to moves past the first pixel of the region.  Here, the iterator
+   * will be set to be one pixel past the beginning of the region.
+   * \sa operator--(int) */
+  Self & operator--()
+  {
+    // 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 ) 
+    {
+      this->Decrement();
+    }
+    else
+    {
+      // Now we can
+      this->m_Offset -= m_SubsampleFactor;
+    }
+    return *this;
+  }
+
+  /** In order to help copy into a new Image, give the new region parameters
+   */
+  RegionType GetNewRegion () const
+  {
+    IndexType startIndex = this->m_Region.GetIndex();
+    SizeType size = this->m_Region.GetSize();
+
+    for ( unsigned int i = 0; i < ImageIteratorDimension; i++ )
+    {
+      startIndex[i] /= m_SubsampleFactor;
+      --size[i];
+      size[i] /= m_SubsampleFactor;
+      ++size[i];
+    }
+
+    RegionType newRegion;
+    newRegion.SetIndex( startIndex );
+    newRegion.SetSize( size );
+
+    for ( unsigned int i = 0; i < ImageIteratorDimension; i++ )
+    {
+      otbGenericMsgDebugMacro(<<"NewRegionIndex[" << i << "] = " << startIndex[i]);
+      otbGenericMsgDebugMacro(<<"NewRegionSize [" << i << "] = " << size[i]);
+    }
+
+    return newRegion;
+  }
+
+protected:
+  unsigned int m_SubsampleFactor;
+  unsigned long m_SubSampledEndOffset;
+  IndexType m_LastUsableIndex;
+
+private:
+  void Increment(); // jump in a direction other than the fastest moving
+  void Decrement(); // go back in a direction other than the fastest moving
+};
+
+
+} // end of namespace otb
+
+#ifndef OTB_MANUAL_INSTANTIATION
+#include "otbSubsampledImageRegionConstIterator.txx"
+#endif
+
+#endif
+
diff --git a/Code/Common/otbSubsampledImageRegionConstIterator.txx b/Code/Common/otbSubsampledImageRegionConstIterator.txx
new file mode 100644
index 0000000000000000000000000000000000000000..022e25c3da378cbea0310ff4a9b3ef2adeb32a52
--- /dev/null
+++ b/Code/Common/otbSubsampledImageRegionConstIterator.txx
@@ -0,0 +1,116 @@
+/*=========================================================================
+
+  Program:   ORFEO Toolbox
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+
+  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+  See OTBCopyright.txt for details.
+
+  Copyright (c) Institut Telecom / Telecom Bretagne. All rights reserved. 
+  See ITCopyright.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 __otbSubsampledImageRegionConstIterator_txx
+#define __otbSubsampledImageRegionConstIterator_txx
+
+#include "otbSubsampledImageRegionConstIterator.h"
+
+namespace otb {
+
+template < class TImage >
+void
+SubsampledImageRegionConstIterator< TImage >
+::Increment ()
+{
+  // Get the index of the last pixel on the span (row)
+  IndexType ind = this->m_Image->ComputeIndex( static_cast<typename Superclass::OffsetValueType>(this->m_Offset) );
+
+  const IndexType& startIndex = this->m_Region.GetIndex();
+  const SizeType& size = this->m_Region.GetSize();
+
+  // Increment along a row, then wrap at the end of the region row.
+  unsigned int dim;
+
+  // 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);
+  bool done = (ind[0] > m_LastUsableIndex[0] );
+  for (unsigned int i=1; done && i < ImageIteratorDimension; i++)
+  {
+    done = (ind[i] >= m_LastUsableIndex[i]);
+  }
+  
+  // if the iterator is outside the region (but not past region end) then
+  // we need to wrap around the region
+  dim = 0;
+  if (!done)
+  {
+    while ( ( dim+1 < ImageIteratorDimension )
+      && (ind[dim] > m_LastUsableIndex[dim]) )
+    {
+      ind[dim] = startIndex[dim];
+      ind[++dim] += static_cast<IndexValueType>(m_SubsampleFactor);
+    }
+  }
+  this->m_Offset = this->m_Image->ComputeOffset( ind );
+  this->m_SpanEndOffset = this->m_Offset 
+                            + static_cast<IndexValueType>( m_SubsampleFactor * ((size[0]-1) / m_SubsampleFactor) )
+                            + 1;
+  this->m_SpanBeginOffset = this->m_Offset;
+}
+
+template < class TImage >
+void
+SubsampledImageRegionConstIterator< TImage >
+::Decrement ()
+{
+  // Get the index of the first pixel on the span (row)
+  typename itk::ImageIterator<TImage>::IndexType
+    ind = this->m_Image->ComputeIndex( static_cast<IndexValueType>(this->m_Offset) );
+
+  const typename itk::ImageIterator<TImage>::IndexType&
+    startIndex = this->m_Region.GetIndex();
+
+  // Deccrement along a row, then wrap at the beginning of the region row.
+  bool done;
+  unsigned int dim;
+
+  // 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 );
+  done = (ind[0] <= startIndex[0] - 1);
+  for (unsigned int i=1; done && i < ImageIteratorDimension; i++)
+  {
+    done = (ind[i] <= startIndex[i]);
+  }
+  
+  // if the iterator is outside the region (but not past region begin) then
+  // we need to wrap around the region
+  dim = 0;
+  if (!done)
+  {
+    while ( (dim < ImageIteratorDimension - 1)
+            && (ind[dim] < startIndex[dim]) )
+    {
+      ind[dim] = m_LastUsableIndex[dim];
+      ind[++dim] -= static_cast<IndexValueType>( m_SubsampleFactor );
+    }
+  }
+  this->m_Offset = this->m_Image->ComputeOffset( ind );
+  this->m_SpanEndOffset = this->m_Offset + 1;
+  this->m_SpanBeginOffset = this->m_Offset - m_LastUsableIndex[0];
+}
+
+} // end of namespace otb
+
+
+#endif
+
diff --git a/Code/MultiScale/otbHaarOperator.h b/Code/MultiScale/otbHaarOperator.h
index cd96cf0c4e3f5af03b1b3d52c3b6c44946b7f302..31377b73fcfdffebb8e4694ba2b97f41b185aa5b 100644
--- a/Code/MultiScale/otbHaarOperator.h
+++ b/Code/MultiScale/otbHaarOperator.h
@@ -43,7 +43,8 @@ namespace otb {
  * 
  * \ingroup Operators
  */
-template<class TPixel, unsigned int VDimension,
+template < InverseOrForwardTransformationEnum TDirectionOfTransformation,
+  class TPixel, unsigned int VDimension,
   class TAllocator = itk::NeighborhoodAllocator< TPixel > >
 class ITK_EXPORT LowPassHaarOperator
   : public WaveletOperator<TPixel, VDimension, TAllocator>
@@ -55,16 +56,20 @@ public:
 
   itkTypeMacro(LowPassHaarOperator, WaveletOperator);
   
+  typedef InverseOrForwardTransformationEnum DirectionOfTransformationEnumType;
+  itkStaticConstMacro(DirectionOfTransformation,DirectionOfTransformationEnumType,TDirectionOfTransformation);
+
   LowPassHaarOperator() 
-        {
+  {
     this->SetRadius(1);
-                this->CreateToRadius(1);
+    this->CreateToRadius(1);
+    this->SetWavelet( "Haar" );
   }
 
   LowPassHaarOperator(const Self& other)
     : WaveletOperator<TPixel, VDimension, TAllocator>(other) 
   {
-    /* ... */
+    this->SetWavelet( "Haar" );
   }
 
   /**
@@ -105,6 +110,17 @@ protected:
     // stands for z^1
     coeff.push_back(0.0);  
 
+#if 0
+  std::cerr << "Coeff H(" << this->GetWavelet();
+  if ( (int) DirectionOfTransformation == (int) FORWARD )
+    std::cerr << " Forward ) = ";
+  else
+    std::cerr << " Inverse ) = ";
+  for ( typename CoefficientVector::const_iterator iter = coeff.begin(); iter < coeff.end(); ++iter )
+    std::cerr << *iter << " ";
+  std::cerr << "\n";
+#endif
+
     return Superclass::UpSamplingCoefficients( coeff );
   }
 
@@ -134,7 +150,8 @@ protected:
  * 
  * \ingroup Operators
  */
-template<class TPixel, unsigned int VDimension,
+template< InverseOrForwardTransformationEnum TDirectionOfTransformation,
+  class TPixel, unsigned int VDimension,
   class TAllocator = itk::NeighborhoodAllocator< TPixel > >
 class ITK_EXPORT HighPassHaarOperator
   : public WaveletOperator<TPixel, VDimension, TAllocator>
@@ -146,16 +163,20 @@ public:
 
   itkTypeMacro(HighPassHaarOperator, WaveletOperator);
   
+  typedef InverseOrForwardTransformationEnum DirectionOfTransformationEnumType;
+  itkStaticConstMacro(DirectionOfTransformation,DirectionOfTransformationEnumType,TDirectionOfTransformation);
+
   HighPassHaarOperator() 
-        {
+  {
     this->SetRadius(1);
-                this->CreateToRadius(1);
+    this->CreateToRadius(1);
+    this->SetWavelet( "Haar" );
   }
 
   HighPassHaarOperator(const Self& other)
     : WaveletOperator<TPixel, VDimension, TAllocator>(other) 
   {
-    /* ... */
+    this->SetWavelet( "Haar" );
   }
 
   /**
@@ -185,13 +206,49 @@ protected:
 
   /**
    * Set operator coefficients.
+   * Due to the number of template parameter, we cannot specialized it with regard
+   * to the TDirectionOfTransformation value...
    */
   CoefficientVector GenerateCoefficients()
   {
     CoefficientVector coeff;
-    coeff.push_back(-0.5);  
-    coeff.push_back(0.5);  
-    coeff.push_back(0.0);  
+
+    typedef LowPassHaarOperator< FORWARD, TPixel, VDimension, TAllocator >
+      LowPassOperatorType;
+    LowPassOperatorType lowPassOperator;
+    lowPassOperator.SetDirection(0);
+    lowPassOperator.CreateDirectional();
+
+    CoefficientVector lowPassCoeff;
+    lowPassCoeff.resize( lowPassOperator.GetSize()[0] );
+
+    for ( typename LowPassOperatorType::ConstIterator iter = lowPassOperator.Begin();
+        iter != lowPassOperator.End(); ++iter )
+      lowPassCoeff.push_back( *iter );
+        
+    switch ( DirectionOfTransformation )
+    {
+      case FORWARD:
+        coeff = this->GetHighPassFilterFromLowPassFilter( lowPassCoeff );
+        break;
+      case INVERSE:
+        coeff = this->GetInverseHighPassFilterFromForwardLowPassFilter( lowPassCoeff );
+        break;
+      default:
+        itkExceptionMacro(<<"Wavelet operator has to be INVERSE or FORWARD only!!");
+        break;
+    }
+
+#if 1
+    std::cerr << "Coeff G(" << this->GetWavelet();
+    if ( (int) DirectionOfTransformation == (int) FORWARD )
+      std::cerr << " Forward ) = ";
+    else
+      std::cerr << " Inverse ) = ";
+    for ( typename CoefficientVector::const_iterator iter = coeff.begin(); iter < coeff.end(); ++iter )
+      std::cerr << *iter << " ";
+    std::cerr << "\n";
+#endif
 
     return Superclass::UpSamplingCoefficients( coeff );
   }
@@ -203,7 +260,6 @@ protected:
   }
 };
 
-
 } // end of namespace otb
 
 #endif
diff --git a/Code/MultiScale/otbSplineBiOrthogonalOperator.h b/Code/MultiScale/otbSplineBiOrthogonalOperator.h
new file mode 100644
index 0000000000000000000000000000000000000000..99dc9d354cb0202c64af48c459a0561c0dac1b32
--- /dev/null
+++ b/Code/MultiScale/otbSplineBiOrthogonalOperator.h
@@ -0,0 +1,178 @@
+/*=========================================================================
+
+  Program:   ORFEO Toolbox
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+
+  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+  See OTBCopyright.txt for details.
+
+  Copyright (c) Institut Telecom / Telecom Bretagne. All rights reserved. 
+  See ITCopyright.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 __otbSplieBiOrthogonalOperator_h
+#define __otbSplieBiOrthogonalOperator_h
+
+#include "itkMacro.h"
+#include "itkExceptionObject.h"
+
+#include "otbWaveletOperator.h"
+
+namespace otb {
+
+/**
+ * \class LowPassSplineBiOrthogonalOperator
+ *
+ * \brief A NeighborhoodOperator for performing a Spline Bi-Orthogonal-based filtering
+ * at a pixel location.
+ *
+ * It may be configure with many filter orders. AT present time, so-called "9/7" filter is 
+ * implemented. It may be fixed with SetWavelet method
+ * 
+ * The LowPassSplineBiOrthogonalOperator is a NeighborhoodOperator that should be applied a 
+ * NeighborhoodIterator using the NeighborhoodInnerProduct method. 
+ * The 9/7 Operator is defiend in 1D as 
+ * \f$ H(z) = 0.026748757411 z^{-4} -0.016864118443 z^{-3} -0.078223266529 z^{-2}
+ *           + 0.266864118443 z^{-1} + 0.602949018236 + 0.266864118443 z
+ *           -0.078223266529 z^2 -0.016864118443 z^3 + 0.026748757411 z^4 \f$.
+ *
+ * In N dimensions, the operator is directional
+ *
+ * \sa WaveletOperator
+ * \sa NeighborhoodOperator
+ * \sa Neighborhood
+ * \sa ForwardDifferenceOperator
+ * \sa BackwardDifferenceOperator
+ * 
+ * \ingroup Operators
+ */
+template < InverseOrForwardTransformationEnum TDirectionOfTransformation,
+  class TPixel, unsigned int VDimension,
+  class TAllocator = itk::NeighborhoodAllocator< TPixel > >
+class ITK_EXPORT LowPassSplineBiOrthogonalOperator
+  : public WaveletOperator<TPixel, VDimension, TAllocator>
+{
+public:
+  /** Standard typedefs */
+  typedef LowPassSplineBiOrthogonalOperator Self;
+  typedef WaveletOperator<TPixel, VDimension, TAllocator>  Superclass;
+
+  itkTypeMacro(LowPassSplineBiOrthogonalOperator, WaveletOperator);
+
+  typedef InverseOrForwardTransformationEnum DirectionOfTransformationEnumType;
+  itkStaticConstMacro(DirectionOfTransformation,DirectionOfTransformationEnumType,TDirectionOfTransformation);
+
+  LowPassSplineBiOrthogonalOperator() ;
+  LowPassSplineBiOrthogonalOperator(const Self& other);
+
+  /**
+   * Assignment operator
+   */
+  Self &operator=(const Self& other);
+
+  /**
+   * Prints some debugging information
+   */
+  virtual void PrintSelf(std::ostream &os, itk::Indent i) const ; 
+
+protected:
+  /**
+   * Typedef support for coefficient vector type.  Necessary to
+   * work around compiler bug on VC++.
+   */
+  typedef typename Superclass::CoefficientVector CoefficientVector;
+  typedef typename Superclass::PixelType PixelType;
+
+  /**
+   * Set operator coefficients.
+   */
+  CoefficientVector GenerateCoefficients();
+
+  /** Arranges coefficients spatially in the memory buffer. */
+  void Fill(const CoefficientVector& coeff);
+};
+
+/**
+ * \class HighPassSplineBiOrthogonalOperator
+ *
+ * \brief A NeighborhoodOperator for performing a Spline Bi-Orthogonal-based filtering
+ * at a pixel location.
+ * 
+ * HighPassSplineBiOrthogonalOperator is a NeighborhoodOperator that should be applied a 
+ * NeighborhoodIterator using the NeighborhoodInnerProduct method. 
+ * The 9/7 Operator is defiend in 1D as 
+ * \f$ H(z) = 0.045635881557 z^{-3} -0.028771763114 z^{-2} -0.295635881557 z^{-1}
+ *            + 0.557543526229  - 0.295635881557 z -0.028771763114 z^2 + 0.045635881557 z^3 \f$.
+ *
+ * In N dimensions, the operator is directional
+ *
+ * \sa WaveletOperator
+ * \sa NeighborhoodOperator
+ * \sa Neighborhood
+ * \sa ForwardDifferenceOperator
+ * \sa BackwardDifferenceOperator
+ * 
+ * \ingroup Operators
+ */
+template < InverseOrForwardTransformationEnum TDirectionOfTransformation,
+class TPixel, unsigned int VDimension,
+  class TAllocator = itk::NeighborhoodAllocator< TPixel > >
+class ITK_EXPORT HighPassSplineBiOrthogonalOperator
+  : public WaveletOperator<TPixel, VDimension, TAllocator>
+{
+public:
+  /** Standard typedefs */
+  typedef HighPassSplineBiOrthogonalOperator Self;
+  typedef WaveletOperator<TPixel, VDimension, TAllocator>  Superclass;
+
+  itkTypeMacro(HighPassSplineBiOrthogonalOperator, WaveletOperator);
+  
+  typedef InverseOrForwardTransformationEnum DirectionOfTransformationEnumType;
+  itkStaticConstMacro(DirectionOfTransformation,DirectionOfTransformationEnumType,TDirectionOfTransformation);
+
+  HighPassSplineBiOrthogonalOperator () ;
+  HighPassSplineBiOrthogonalOperator(const Self& other);
+
+  /**
+   * Assignment operator
+   */
+  Self &operator=(const Self& other);
+
+  /**
+   * Prints some debugging information
+   */
+  virtual void PrintSelf(std::ostream &os, itk::Indent i) const ;
+
+protected:
+  /**
+   * Typedef support for coefficient vector type.  Necessary to
+   * work around compiler bug on VC++.
+   */
+  typedef typename Superclass::CoefficientVector CoefficientVector;
+  typedef typename Superclass::PixelType PixelType;
+
+  /**
+   * Set operator coefficients.
+   */
+  CoefficientVector GenerateCoefficients();
+
+  /** Arranges coefficients spatially in the memory buffer. */
+  void Fill(const CoefficientVector& coeff);
+};
+
+} // end of namespace otb
+
+#ifndef OTB_MANUAL_INSTANTIATION
+#include "otbSplineBiOrthogonalOperator.txx"
+#endif
+
+
+#endif
+
diff --git a/Code/MultiScale/otbStationaryFilterBank.h b/Code/MultiScale/otbStationaryFilterBank.h
index a45ed5b9b775d4ee4e0c31abfcc5c2e7b560f1bd..ac7141b235e213f2adf2165ae39bea200614c59d 100644
--- a/Code/MultiScale/otbStationaryFilterBank.h
+++ b/Code/MultiScale/otbStationaryFilterBank.h
@@ -38,7 +38,8 @@ namespace otb {
  * (ie. convolution-like operation).
  *
  * the inner operator are supposed to be defined through 1D filters. Then, the
- * transformation yields \f$ 2^Dim \f$ output images.
+ * forward transformation yields \f$ 2^{\test{Dim}} \f$ output images, while the inverse 
+ * transformation requires \f$ 2^{\text{Dim}} \f$ input image for one output.
  *
  * In case of 1D, GetOutput(0) -> LowPass
  *
@@ -63,7 +64,12 @@ namespace otb {
  *
  *  ->  x_(n-1)     x_(n-2)     x_(n-3)           x_1    x_0
  *    
+ * And conversely in the inverse transformation.
  *
+ * TODO: At present version, there is not consideration on meta data information that can be transmited
+ * from the input(s) to the output(s)...
+ *
+ * TODO: In the case of multiresolution decomposition, take care of the size of outputRegionForThread...
  *
  * \sa LowPassHaarOperator
  * \sa HighPassHaarOperator
@@ -72,7 +78,9 @@ namespace otb {
  *
  * \ingroup Streamed
  */
-template < class TInputImage, class TOutputImage, class TLowPassOperator, class THighPassOperator >
+template < class TInputImage, class TOutputImage, 
+            class TLowPassOperator, class THighPassOperator, 
+            InverseOrForwardTransformationEnum TDirectionOfTransformation >
 class ITK_EXPORT StationaryFilterBank
   : public itk::ImageToImageFilter< TInputImage, TOutputImage >
 {
@@ -81,68 +89,113 @@ public:
   typedef StationaryFilterBank Self;
   typedef itk::ImageToImageFilter< TInputImage, TOutputImage > Superclass;
   typedef itk::SmartPointer<Self> Pointer;
-        typedef itk::SmartPointer<const Self> ConstPointer;
+  typedef itk::SmartPointer<const Self> ConstPointer;
 
-        /** Type macro */
-        itkNewMacro(Self);
+  /** Type macro */
+  itkNewMacro(Self);
 
-        /** Creation through object factory macro */
-        itkTypeMacro(StationaryFilterBank,ImageToImageFilter);
+  /** Creation through object factory macro */
+  itkTypeMacro(StationaryFilterBank,ImageToImageFilter);
 
   /** Template parameters typedefs */
   typedef TInputImage InputImageType;
-        typedef typename InputImageType::Pointer InputImagePointerType;
-        typedef typename InputImageType::RegionType InputImageRegionType;
-        typedef typename InputImageType::SizeType InputSizeType;
-        typedef typename InputImageType::IndexType InputIndexType;
-        typedef typename InputImageType::PixelType InputPixelType;
+  typedef typename InputImageType::Pointer InputImagePointerType;
+  typedef typename InputImageType::RegionType InputImageRegionType;
+  typedef typename InputImageType::SizeType InputSizeType;
+  typedef typename InputImageType::IndexType InputIndexType;
+  typedef typename InputImageType::PixelType InputPixelType;
 
   typedef TOutputImage OutputImageType;
-        typedef typename OutputImageType::Pointer OutputImagePointerType;
+  typedef typename OutputImageType::Pointer OutputImagePointerType;
   typedef typename OutputImageType::RegionType OutputImageRegionType;
   typedef typename OutputImageType::SizeType OutputSizeType;
   typedef typename OutputImageType::IndexType OutputIndexType;
-        typedef typename OutputImageType::PixelType OutputPixelType;
+  typedef typename OutputImageType::PixelType OutputPixelType;
 
   typedef TLowPassOperator LowPassOperatorType;
   typedef THighPassOperator HighPassOperatorType;
 
+  typedef InverseOrForwardTransformationEnum DirectionOfTransformationEnumType;
+  itkStaticConstMacro(DirectionOfTransformation,DirectionOfTransformationEnumType,TDirectionOfTransformation);
+
   /** Inner product iterators */
-  typedef itk::ConstNeighborhoodIterator< OutputImageType > NeighborhoodIteratorType;
-  typedef itk::NeighborhoodInnerProduct< OutputImageType > InnerProductType;
-  typedef itk::ImageRegionIterator< OutputImageType > IteratorType;
+  typedef itk::ConstNeighborhoodIterator< InputImageType > NeighborhoodIteratorType;
+  typedef itk::NeighborhoodInnerProduct< InputImageType > InnerProductType;
+  typedef itk::ImageRegionIterator< InputImageType > IteratorType;
   typedef typename itk::NeighborhoodAlgorithm  
-    ::ImageBoundaryFacesCalculator< OutputImageType > FaceCalculatorType;
+    ::ImageBoundaryFacesCalculator< InputImageType > FaceCalculatorType;
   typedef typename FaceCalculatorType::FaceListType FaceListType;
   typedef typename FaceListType::iterator FaceListIterator;
 
   /** Dimension */
-        itkStaticConstMacro(InputImageDimension, unsigned int, TInputImage::ImageDimension);
-        itkStaticConstMacro(OutputImageDimension, unsigned int, TOutputImage::ImageDimension);
+  itkStaticConstMacro(InputImageDimension, unsigned int, TInputImage::ImageDimension);
+  itkStaticConstMacro(OutputImageDimension, unsigned int, TOutputImage::ImageDimension);
 
   /**
-   * Set/Get the level of up sampling of the filter used in the A-trou algorithm
+   * Set/Get the level of up sampling of the filter used in the A-trou algorithm.
    */
-  itkGetMacro(UpSampleFactor,unsigned int);
-  itkSetMacro(UpSampleFactor,unsigned int);
+  itkGetMacro(UpSampleFilterFactor,unsigned int);
+  itkSetMacro(UpSampleFilterFactor,unsigned int);
+
+  /**
+   * Set/Get the level of down sampling of the image used in forward algorithm. 
+   * (or upsampling in the inverse case)
+   *
+   * In this implementation, we are dealing with M-band decomposition then m_SubSampleImageFactor
+   * is most likely to be 1 or 2... but in any case integer and not real...
+   */
+  itkGetMacro(SubSampleImageFactor,unsigned int);
+  itkSetMacro(SubSampleImageFactor,unsigned int);
+
 
 protected:
   StationaryFilterBank();
   virtual ~StationaryFilterBank() { }
 
+  /** GenerateOutputInformation 
+	 * Set the size of the output image depending on the decimation factor
+	 * Copy informations from the input image if existing.
+	 **/
+	virtual void GenerateOutputInformation();
+
+  /** BeforeThreadedGenerateData
+   * If SubSampleImageFactor neq 1, it is necessary to up sample input images in the INVERSE mode
+   */
+  virtual void BeforeThreadedGenerateData ();
+
+  /** AfterThreadedGenerateData
+   * If SubSampleImageFactor neq 1, it is necessary to down sample output images in the FORWARD mode
+   */
+  virtual void AfterThreadedGenerateData ();
+
   /** Generate data redefinition */
   virtual void ThreadedGenerateData ( const OutputImageRegionType& outputRegionForThread, int threadId );
 
-  /** Specific case applied on the input image */
-  virtual void ThreadedGenerateData ( itk::ProgressReporter & reporter,
-                                        const OutputImageRegionType& outputRegionForThread, int threadId );
+  /** Specification-like in the case where DirectionOfTransformation stands for FORWARD or INVERSE */
+  virtual void ThreadedForwardGenerateData ( const OutputImageRegionType& outputRegionForThread, int threadId );
+  virtual void ThreadedInverseGenerateData ( const OutputImageRegionType& outputRegionForThread, int threadId );
 
-  /** Iterative call to the filter bank at each dimension */
-  virtual void ThreadedGenerateData ( unsigned int idx, unsigned int direction, 
-                                        itk::ProgressReporter & reporter,
-                                        const OutputImageRegionType& outputRegionForThread, int threadId );
+  /** Specific case applied on the input image in forward transformation */
+  virtual void ThreadedForwardGenerateData ( itk::ProgressReporter & reporter,
+                                              const OutputImageRegionType& outputRegionForThread, int threadId );
+
+  /** Iterative call to the forward filter bank at each dimension */
+  virtual void ThreadedForwardGenerateData ( unsigned int idx, unsigned int direction, 
+                                              itk::ProgressReporter & reporter,
+                                              const OutputImageRegionType& outputRegionForThread, int threadId );
+
+  /** Iterative call to the inverse filter bank at each dimension */
+  virtual void ThreadedInverseGenerateData ( unsigned int idx, unsigned int direction, 
+                                              InputImagePointerType & outputImage,
+                                              itk::ProgressReporter & reporter,
+                                              const InputImageRegionType& inputRegionForThread, int threadId );
+  
+  /** Specific  case applied on the last reconstruction in inverse transformation */
+  virtual void ThreadedInverseGenerateData ( itk::ProgressReporter & reporter,
+                                              const OutputImageRegionType& outputRegionForThread, int threadId );
 
-  unsigned int m_UpSampleFactor;
+  unsigned int m_UpSampleFilterFactor;
+  unsigned int m_SubSampleImageFactor;
 
 private:
   StationaryFilterBank( const Self & );
diff --git a/Code/MultiScale/otbStationaryFilterBank.txx b/Code/MultiScale/otbStationaryFilterBank.txx
index f1c80aa58632b29bb0c7d56ea0af8255e930377e..8f1a2800145bfca0a3ba3511683d73712bce2f17 100644
--- a/Code/MultiScale/otbStationaryFilterBank.txx
+++ b/Code/MultiScale/otbStationaryFilterBank.txx
@@ -23,44 +23,183 @@
 
 #include "otbStationaryFilterBank.h"
 
+#include "otbMacro.h"
+
 #include "itkNeighborhoodAlgorithm.h"
 #include "itkZeroFluxNeumannBoundaryCondition.h"
 #include "itkProgressReporter.h"
 
 namespace otb {
 
-template < class TInputImage, class TOutputImage, class TLowPassOperator, class THighPassOperator >
-StationaryFilterBank< TInputImage, TOutputImage, TLowPassOperator, THighPassOperator >
+template < class TInputImage, class TOutputImage, 
+            class TLowPassOperator, class THighPassOperator,
+            InverseOrForwardTransformationEnum TDirectionOfTransformation >
+StationaryFilterBank< TInputImage, TOutputImage, 
+                      TLowPassOperator, THighPassOperator, 
+                      TDirectionOfTransformation >
 ::StationaryFilterBank ()
 {
-  this->SetNumberOfRequiredInputs(1);
+  switch ( DirectionOfTransformation )
+  {
+    case FORWARD:
+    {
+      this->SetNumberOfRequiredInputs(1);
+
+      unsigned int numOfOutputs = 1<<InputImageType::ImageDimension;
+
+      this->SetNumberOfOutputs( numOfOutputs );
+      for ( unsigned i = 1; i < numOfOutputs; i++ )
+      {
+        this->SetNthOutput(i,OutputImageType::New());
+      }
+      
+      break;
+    }
+    case INVERSE:
+    {
+      this->SetNumberOfRequiredOutputs(1);
+      this->SetNumberOfInputs( 1 << InputImageType::ImageDimension );
+      break;
+    }
+    default:
+    {
+      itkExceptionMacro(<<"FilterBank transformation may be FORWARD or INVERSE only!!");
+      break;
+    }
+  }
+  m_UpSampleFilterFactor = 0;
+  m_SubSampleImageFactor = 1;
+}
 
-  unsigned int numOfOutput = 1<<InputImageType::ImageDimension;
 
-  this->SetNumberOfOutputs( numOfOutput );
-  for ( unsigned i = 1; i < numOfOutput; i++ )
+template < class TInputImage, class TOutputImage, 
+            class TLowPassOperator, class THighPassOperator,
+            InverseOrForwardTransformationEnum TDirectionOfTransformation >
+void
+StationaryFilterBank< TInputImage, TOutputImage, 
+                      TLowPassOperator, THighPassOperator, 
+                      TDirectionOfTransformation >
+::GenerateOutputInformation()
+{
+  Superclass::GenerateOutputInformation();
+
+  switch ( DirectionOfTransformation )
+  {
+    case FORWARD:
+    {
+      /**
+       * If necessary, we do not say to the filter, at this
+       * step, that we will down sample the output images...
+       */
+      break;
+    }
+    case INVERSE:
+    {
+      otbGenericMsgDebugMacro( << " down sampling output regions by a factor of " << GetSubSampleImageFactor() );
+
+      this->GetOutput()->CopyInformation( this->GetInput() );
+      this->GetOutput()->SetRegions( this->GetInput()->GetLargestPossibleRegion() );
+
+      if ( GetSubSampleImageFactor() > 1 )
+      {
+        for ( unsigned int i = 0; i < ImageDimension; i++ )
+        {
+          this->GetOutput()->GetRegion().GetIndex()[i] /= GetSubSampleImageFactor();
+          this->GetOutput()->GetRegion().GetSize()[i] /= GetSubSampleImageFactor();
+        }
+      }
+      break;
+    }
+    default:
+    {
+      itkExceptionMacro(<<"FilterBank transformation may be FORWARD or INVERSE only!!");
+      break;
+    }
+  }
+}
+
+template < class TInputImage, class TOutputImage, 
+            class TLowPassOperator, class THighPassOperator,
+            InverseOrForwardTransformationEnum TDirectionOfTransformation >
+void
+StationaryFilterBank< TInputImage, TOutputImage, 
+                      TLowPassOperator, THighPassOperator, 
+                      TDirectionOfTransformation >
+::BeforeThreadedGenerateData ()
+{
+  if ( static_cast<int>( DirectionOfTransformation ) == INVERSE )
   {
-    this->SetNthOutput(i,OutputImageType::New());
+    otbGenericMsgDebugMacro(<<"Subsample inputs by a factor of " << GetSubSampleImageFactor() );
+
+    // Sub sample inputs
   }
+}
 
-  m_UpSampleFactor = 0;
+template < class TInputImage, class TOutputImage, 
+            class TLowPassOperator, class THighPassOperator,
+            InverseOrForwardTransformationEnum TDirectionOfTransformation >
+void
+StationaryFilterBank< TInputImage, TOutputImage, 
+                      TLowPassOperator, THighPassOperator, 
+                      TDirectionOfTransformation >
+::AfterThreadedGenerateData ()
+{
+  if ( static_cast<int>( DirectionOfTransformation ) == FORWARD )
+  {
+    otbGenericMsgDebugMacro(<<"Downsample outputs by a factor of " << GetSubSampleImageFactor() );
+
+    // Down sample inputs
+  }
 }
 
-template < class TInputImage, class TOutputImage, class TLowPassOperator, class THighPassOperator >
+
+template < class TInputImage, class TOutputImage, 
+            class TLowPassOperator, class THighPassOperator,
+            InverseOrForwardTransformationEnum TDirectionOfTransformation >
 void
-StationaryFilterBank< TInputImage, TOutputImage, TLowPassOperator, THighPassOperator >
+StationaryFilterBank< TInputImage, TOutputImage, 
+                      TLowPassOperator, THighPassOperator, 
+                      TDirectionOfTransformation >
 ::ThreadedGenerateData ( const OutputImageRegionType& outputRegionForThread, int threadId )
 {
+  switch ( DirectionOfTransformation )
+  {
+    case FORWARD:
+      return ThreadedForwardGenerateData( outputRegionForThread, threadId );
+      break;
+    case INVERSE:
+      return ThreadedInverseGenerateData( outputRegionForThread, threadId );
+      break;
+    default:
+      itkExceptionMacro(<<"FilterBank transformation may be FORWARD or INVERSE only!!");
+      break;
+  } 
+}
+
+template < class TInputImage, class TOutputImage, 
+            class TLowPassOperator, class THighPassOperator,
+            InverseOrForwardTransformationEnum TDirectionOfTransformation >
+void
+StationaryFilterBank< TInputImage, TOutputImage, 
+                      TLowPassOperator, THighPassOperator, 
+                      TDirectionOfTransformation >
+::ThreadedForwardGenerateData ( const OutputImageRegionType& outputRegionForThread, int threadId )
+{
+
   itk::ProgressReporter reporter ( this, threadId, 
     outputRegionForThread.GetNumberOfPixels() * this->GetNumberOfOutputs() );
 
-  ThreadedGenerateData( reporter, outputRegionForThread, threadId );
+  ThreadedForwardGenerateData( reporter, outputRegionForThread, threadId );
 }
 
-template < class TInputImage, class TOutputImage, class TLowPassOperator, class THighPassOperator >
+template < class TInputImage, class TOutputImage, 
+            class TLowPassOperator, class THighPassOperator,
+            InverseOrForwardTransformationEnum TDirectionOfTransformation >
 void
-StationaryFilterBank< TInputImage, TOutputImage, TLowPassOperator, THighPassOperator >
-::ThreadedGenerateData 
+StationaryFilterBank< TInputImage, TOutputImage, 
+                      TLowPassOperator, THighPassOperator, 
+                      TDirectionOfTransformation >
+::ThreadedForwardGenerateData 
 ( itk::ProgressReporter & reporter,
   const OutputImageRegionType& outputRegionForThread, int threadId )
 {
@@ -79,8 +218,8 @@ StationaryFilterBank< TInputImage, TOutputImage, TLowPassOperator, THighPassOper
   if ( outputHighPass == 0 )
   {
     itk::OStringStream msg;
-                msg << "Sortie 1<<" << idx << " = " << (1<<idx) << " nulle\n";
-    msg << "Nombre de sortie attendue " << this->GetNumberOfOutputs() << "\n";
+    msg << "Output number 1<<" << idx << " = " << (1<<idx) << " null\n";
+    msg << "Number of excpected outputs " << this->GetNumberOfOutputs() << "\n";
     throw itk::ExceptionObject( __FILE__, __LINE__, msg.str().c_str(), ITK_LOCATION );
   }
 
@@ -97,7 +236,7 @@ StationaryFilterBank< TInputImage, TOutputImage, TLowPassOperator, THighPassOper
   // High pass part calculation
   HighPassOperatorType highPassOperator;
   highPassOperator.SetDirection(idx);
-  highPassOperator.SetUpSampleFactor( this->GetUpSampleFactor() );
+  highPassOperator.SetUpSampleFactor( this->GetUpSampleFilterFactor() );
   highPassOperator.CreateDirectional();
 
   faceList = faceCalculator( input, outputRegionForThread, highPassOperator.GetRadius() );
@@ -117,7 +256,7 @@ StationaryFilterBank< TInputImage, TOutputImage, TLowPassOperator, THighPassOper
   // Low pass part calculation
   LowPassOperatorType lowPassOperator;
   lowPassOperator.SetDirection(idx);
-  lowPassOperator.SetUpSampleFactor( this->GetUpSampleFactor() );
+  lowPassOperator.SetUpSampleFactor( this->GetUpSampleFilterFactor() );
   lowPassOperator.CreateDirectional();
 
   faceList = faceCalculator( input, outputRegionForThread, lowPassOperator.GetRadius() );
@@ -136,15 +275,19 @@ StationaryFilterBank< TInputImage, TOutputImage, TLowPassOperator, THighPassOper
 
   if ( idx > 0 )
   {
-    ThreadedGenerateData( 0, idx-1, reporter, outputRegionForThread, threadId );
-    ThreadedGenerateData( 1<<idx, idx-1, reporter, outputRegionForThread, threadId );
+    ThreadedForwardGenerateData( 0, idx-1, reporter, outputRegionForThread, threadId );
+    ThreadedForwardGenerateData( 1<<idx, idx-1, reporter, outputRegionForThread, threadId );
   }
 }
 
-template < class TInputImage, class TOutputImage, class TLowPassOperator, class THighPassOperator >
+template < class TInputImage, class TOutputImage, 
+            class TLowPassOperator, class THighPassOperator,
+            InverseOrForwardTransformationEnum TDirectionOfTransformation >
 void
-StationaryFilterBank< TInputImage, TOutputImage, TLowPassOperator, THighPassOperator >
-::ThreadedGenerateData 
+StationaryFilterBank< TInputImage, TOutputImage, 
+                      TLowPassOperator, THighPassOperator, 
+                      TDirectionOfTransformation >
+::ThreadedForwardGenerateData 
 ( unsigned int idx, unsigned int direction, itk::ProgressReporter & reporter,
   const OutputImageRegionType& outputRegionForThread, int threadId )
 {
@@ -162,7 +305,7 @@ StationaryFilterBank< TInputImage, TOutputImage, TLowPassOperator, THighPassOper
   // High pass part calculation
   HighPassOperatorType highPassOperator;
   highPassOperator.SetDirection(direction);
-  highPassOperator.SetUpSampleFactor( this->GetUpSampleFactor() );
+  highPassOperator.SetUpSampleFactor( this->GetUpSampleFilterFactor() );
   highPassOperator.CreateDirectional();
 
   faceList = faceCalculator( input, outputRegionForThread, highPassOperator.GetRadius() );
@@ -182,7 +325,7 @@ StationaryFilterBank< TInputImage, TOutputImage, TLowPassOperator, THighPassOper
   // Low pass part calculation
   LowPassOperatorType lowPassOperator;
   lowPassOperator.SetDirection(direction);
-  lowPassOperator.SetUpSampleFactor( this->GetUpSampleFactor() );
+  lowPassOperator.SetUpSampleFactor( this->GetUpSampleFilterFactor() );
   lowPassOperator.CreateDirectional();
 
   faceList = faceCalculator( input, outputRegionForThread, lowPassOperator.GetRadius() );
@@ -205,7 +348,7 @@ StationaryFilterBank< TInputImage, TOutputImage, TLowPassOperator, THighPassOper
 
   for ( inIt.GoToBegin(), outIt.GoToBegin(); !inIt.IsAtEnd(); ++inIt, ++outIt )
   {
-    outIt.Set( inIt.Get() );
+    outIt.Set( static_cast<InputPixelType>( inIt.Get() ) );
   }
 
   if ( direction != 0 )
@@ -215,6 +358,206 @@ StationaryFilterBank< TInputImage, TOutputImage, TLowPassOperator, THighPassOper
   }
 }
 
+template < class TInputImage, class TOutputImage, 
+            class TLowPassOperator, class THighPassOperator,
+            InverseOrForwardTransformationEnum TDirectionOfTransformation >
+void
+StationaryFilterBank< TInputImage, TOutputImage, 
+                      TLowPassOperator, THighPassOperator, 
+                      TDirectionOfTransformation >
+::ThreadedInverseGenerateData ( const OutputImageRegionType& outputRegionForThread, int threadId )
+{
+  itk::ProgressReporter reporter ( this, threadId, 
+    outputRegionForThread.GetNumberOfPixels() * this->GetNumberOfInputs() );
+
+  ThreadedInverseGenerateData( reporter, outputRegionForThread, threadId );
+}
+
+template < class TInputImage, class TOutputImage, 
+            class TLowPassOperator, class THighPassOperator,
+            InverseOrForwardTransformationEnum TDirectionOfTransformation >
+void
+StationaryFilterBank< TInputImage, TOutputImage, 
+                      TLowPassOperator, THighPassOperator, 
+                      TDirectionOfTransformation >
+::ThreadedInverseGenerateData 
+( itk::ProgressReporter & reporter,
+  const OutputImageRegionType& outputRegionForThread, int threadId )
+{
+  InputImageRegionType inputRegionForThread;
+	this->CallCopyOutputRegionToInputRegion( inputRegionForThread, outputRegionForThread );
+  
+  unsigned int idx = InputImageType::ImageDimension-1;
+
+  InputImagePointerType imgLowPassPointer = InputImageType::New();
+  InputImageType * imgLowPass = this->GetInput(0);
+  if ( idx != 0 )
+  {
+    imgLowPassPointer->SetRegions( inputRegionForThread );
+    imgLowPassPointer->Allocate();
+
+    ThreadedInverseGenerateData( 0, idx-1, imgLowPassPointer, reporter, inputRegionForThread, threadId );
+
+    imgLowPass = imgLowPassPointer.GetPointer();
+  }
+
+  InputImagePointerType imgHighPassPointer = InputImageType::New();
+  InputImageType * imgHighPass = this->GetInput(1);
+  if ( idx != 0 )
+  {
+    imgHighPassPointer->SetRegions( inputRegionForThread );
+    imgHighPassPointer->Allocate();
+
+    ThreadedInverseGenerateData( 1<<idx, idx-1, imgHighPassPointer, reporter, inputRegionForThread, threadId );
+  
+    imgHighPass = imgHighPassPointer.GetPointer();
+  }
+
+  // Low pass part calculation
+  LowPassOperatorType lowPassOperator;
+  lowPassOperator.SetDirection(idx);
+  lowPassOperator.SetUpSampleFactor( this->GetUpSampleFilterFactor() );
+  lowPassOperator.CreateDirectional();
+
+  // High pass part calculation
+  HighPassOperatorType highPassOperator;
+  highPassOperator.SetDirection(idx);
+  highPassOperator.SetUpSampleFactor( this->GetUpSampleFilterFactor() );
+  highPassOperator.CreateDirectional();
+
+  // Faces iterations
+  typedef NeighborhoodIteratorType::RadiusType radiusMax;
+  for ( unsigned int i = 0; i < ImageDimension; i++ )
+  {
+    radiusMax[i] = lowPassOperator.GetRadius()[i];
+    if ( radius[i] < highPassOperator.GetRadius()[i] )
+      radius[i] = highPassOperator.GetRadius()[i];
+  }
+
+  FaceCalculatorType faceCalculator;  
+  FaceListType faceList;
+  faceList = faceCalculator( imgHighPass, inputRegionForThread, radiusMax );
+
+  InnerProductType innerProduct;
+
+  for ( FaceListIterator faceIt = faceList.begin(); faceIt != faceList.end(); ++faceIt )
+  {
+    itk::ImageRegionIterator< OutputImageType > out ( this->GetOutput(), *faceIt );
+
+    NeighborhoodIteratorType lowIter ( lowPassOperator.GetRadius(), imgLowPass, *faceIt );
+    NeighborhoodIteratorType highIter ( highPassOperator.GetRadius(), imgHighPass, *faceIt );
+
+    lowIter.GoToBegin();
+    highIter.GoToBegin();
+    out.GoToBegin();
+
+    while ( !out.IsAtEnd() )
+    {  
+      out.Set( static_cast< OutputPixelType >( 
+                innerProduct( lowIter, lowPassOperator ) 
+                  + innerProduct( highIter, highPassOperator ) ) );
+
+      ++lowIter;
+      ++highIter;
+      ++out;
+
+      reporter.CompletedPixel();
+    }
+  }
+}
+
+template < class TInputImage, class TOutputImage, 
+            class TLowPassOperator, class THighPassOperator,
+            InverseOrForwardTransformationEnum TDirectionOfTransformation >
+void
+StationaryFilterBank< TInputImage, TOutputImage, 
+                      TLowPassOperator, THighPassOperator, 
+                      TDirectionOfTransformation >
+::ThreadedInverseGenerateData 
+( unsigned int idx, unsigned int direction, 
+  InputImagePointerType & outputImage,
+  itk::ProgressReporter & reporter,
+  const InputImageRegionType& inputRegionForThread, int threadId )
+{
+  InputImagePointerType imgLowPassPointer = InputImageType::New();
+  InputImageType * imgLowPass = this->GetInput(idx);
+  if ( direction != 0 )
+  {
+    imgLowPassPointer->SetRegions( inputRegionForThread );
+    imgLowPassPointer->Allocate();
+
+    ThreadedGenerateData( idx, direction-1, imgLowPassPointer, reporter, outputRegionForThread, threadId );
+
+    imgLowPass = imgLowPassPointer.GetPointer();
+  }
+
+  InputImagePointerType imgHighPassPointer = InputImageType::New();
+  InputImageType * imgHighPass = this->GetInput(idx + (1<<direction));
+  if ( direction != 0 )
+  {
+    imgHighPassPointer->SetReions( inputRegionForThread );
+    imgHighPassPointer->Allocate();
+
+    ThreadedInverseGenerateData( idx + (1<<direction), direction-1, imgHighPassPointer, reporter, inputRegionForThread, threadId );
+
+    imgHighPass = imgHighPassPointer.GetPointer();
+  }
+
+  // Low pass part calculation
+  LowPassOperatorType lowPassOperator;
+  lowPassOperator.SetDirection(idx);
+  lowPassOperator.SetUpSampleFactor( this->GetUpSampleFilterFactor() );
+  lowPassOperator.CreateDirectional();
+
+  // High pass part calculation
+  HighPassOperatorType highPassOperator;
+  highPassOperator.SetDirection(idx);
+  highPassOperator.SetUpSampleFactor( this->GetUpSampleFilterFactor() );
+  highPassOperator.CreateDirectional();
+
+  // Faces iterations
+  typedef NeighborhoodIteratorType::RadiusType radiusMax;
+  for ( unsigned int i = 0; i < ImageDimension; i++ )
+  {
+    radiusMax[i] = lowPassOperator.GetRadius()[i];
+    if ( radius[i] < highPassOperator.GetRadius()[i] )
+      radius[i] = highPassOperator.GetRadius()[i];
+  }
+
+  FaceCalculatorType faceCalculator;  
+  FaceListType faceList;
+  faceList = faceCalculator( imgHighPass, inputRegionForThread, radiusMax );
+
+  InnerProductType innerProduct;
+
+  for ( FaceListIterator faceIt = faceList.begin(); faceIt != faceList.end(); ++faceIt )
+  {
+    IteratorType out ( this->GetOutput(), *faceIt );
+
+    NeighborhoodIteratorType lowIter ( lowPassOperator.GetRadius(), imgLowPass, *faceIt );
+    NeighborhoodIteratorType highIter ( highPassOperator.GetRadius(), imgHighPass, *faceIt );
+
+    lowIter.GoToBegin();
+    highIter.GoToBegin();
+    out.GoToBegin();
+
+    while ( !out.IsAtEnd() )
+    {  
+      out.Set( innerProduct( lowIter, lowPassOperator ) 
+                + innerProduct( highIter, highPassOperator ) );
+
+      ++lowIter;
+      ++highIter;
+      ++out;
+
+      reporter.CompletedPixel();
+    }
+  }
+}
+
+
+
+
 } // end of namespace
 
 #endif
diff --git a/Code/MultiScale/otbWaveletForwardTransform.h b/Code/MultiScale/otbWaveletForwardTransform.h
index a94474b841ef417babbb8453dbe497d59ed37210..18554318e892de5bd3a59b4f2eadcc9fa097f9a9 100644
--- a/Code/MultiScale/otbWaveletForwardTransform.h
+++ b/Code/MultiScale/otbWaveletForwardTransform.h
@@ -54,13 +54,13 @@ public:
   typedef WaveletForwardTransform Self;
   typedef itk::ImageToImageFilter< TInputImage, TOutputImage > Superclass;
   typedef itk::SmartPointer<Self> Pointer;
-        typedef itk::SmartPointer<const Self> ConstPointer;
+  typedef itk::SmartPointer<const Self> ConstPointer;
 
-        /** Type macro */
-        itkNewMacro(Self);
+  /** Type macro */
+  itkNewMacro(Self);
 
-        /** Creation through object factory macro */
-        itkTypeMacro(WaveletForwardTransform,ImageToImageFilter);
+  /** Creation through object factory macro */
+  itkTypeMacro(WaveletForwardTransform,ImageToImageFilter);
 
   typedef TInputImage InputImageType;
   typedef typename InputImageType::Pointer InputImagePointer;
diff --git a/Code/MultiScale/otbWaveletOperator.h b/Code/MultiScale/otbWaveletOperator.h
index b5263022cb0a19463627421c73e90a0f7648e317..5fd869196756be64e28f22d6284c1a6e9cf54eea 100644
--- a/Code/MultiScale/otbWaveletOperator.h
+++ b/Code/MultiScale/otbWaveletOperator.h
@@ -23,6 +23,9 @@
 #include "itkExceptionObject.h"
 #include "itkNeighborhoodOperator.h"
 
+// This include is needed to define InverseOrForwardTransformationEnum only...
+#include "otbGenericMapProjection.h"
+
 namespace otb {
 
 /**
@@ -65,15 +68,16 @@ public:
   itkTypeMacro(WaveletOperator,NeighborhoodOperator);
 
   /** Construction */
-  WaveletOperator() 
-  {
-    m_UpSampleFactor = 0;
-  }
+  WaveletOperator() :
+    m_UpSampleFactor( 0 ), m_Wavelet( "Unknown" )
+  { }
+
   /** Construction by copy */
   WaveletOperator( const Self & other ) 
     : itk::NeighborhoodOperator<TPixel, VDimension, TAllocator> (other)
   {
     m_UpSampleFactor = other.GetUpSampleFactor();
+    m_Wavelet = other.m_Wavelet;
   }
   virtual ~WaveletOperator() {}
 
@@ -82,6 +86,7 @@ public:
   {
     Superclass::operator=(other);
     m_UpSampleFactor = other.GetUpSampleFactor();
+    m_Wavelet = other.m_Wavelet;
     return *this;
   }
   /**
@@ -91,6 +96,7 @@ public:
   { 
     Superclass::PrintSelf(os, i.GetNextIndent());
     os << i << "Up-Sampling factor " << this->m_UpSampleFactor << "\n";
+    os << i << "Wavelet kind : " << GetWavelet() << std::endl;
   }
 
   /**
@@ -105,6 +111,19 @@ public:
     this->m_UpSampleFactor = upSampleFactor;
   }
 
+  /**
+   * Set/Get the name of the wavelet when necessary
+   */
+  virtual void SetWavelet ( const std::string & str ) {
+    this->m_Wavelet = str;
+  }
+
+  virtual void SetWavelet ( const char * str ) {
+    this->m_Wavelet = str; }
+
+  virtual const char * GetWavelet () const {
+    return this->m_Wavelet.c_str(); }
+
 protected:
   /**
    * Typedef support for coefficient vector type.  Necessary to
@@ -141,7 +160,85 @@ protected:
     return coeff;
   }
 
+  /** 
+   * Performs the definition of synthesis filter from analysis one.
+   * Input is the forward low pass filter coefficients.
+   * It performs \f$ {\tilde G}(z) = -H(-z) \f$.
+   */
+  CoefficientVector GetInverseHighPassFilterFromForwardLowPassFilter ( CoefficientVector & coeff ) 
+  {
+    unsigned long radius = static_cast<unsigned long>( coeff.size() );
+    this->SetRadius( radius );
+
+    unsigned long medianPosition = radius/2;
+
+    CoefficientVector highPassedCoeff;
+    highPassedCoeff = coeff;
+
+    for ( unsigned int i = 0; i < medianPosition; i+=2 )
+    {
+      highPassedCoeff[medianPosition + i] = - coeff[ medianPosition + i ];
+      highPassedCoeff[medianPosition - i] = - coeff[ medianPosition - i ];
+    }
+
+    coeff = highPassedCoeff;
+    return  coeff;
+  }
+
+  /** 
+   * Performs the definition of synthesis filter from analysis one.
+   * Input is the forward high pass filter coefficients.
+   * It performs \f$ {\tilde H}(z) = G(-z) \f$.
+   */
+  CoefficientVector GetInverseLowPassFilterFromForwardHighPassFilter ( CoefficientVector & coeff ) 
+  {
+    unsigned long radius = static_cast<unsigned long>( coeff.size() );
+    this->SetRadius( radius );
+
+    unsigned long medianPosition = radius/2;
+
+    CoefficientVector lowPassedCoeff;
+    lowPassedCoeff = coeff;
+
+    for ( unsigned int i = 1; i < medianPosition; i+=2 )
+    {
+      lowPassedCoeff[medianPosition + i] = - coeff[ medianPosition + i ];
+      lowPassedCoeff[medianPosition - i] = - coeff[ medianPosition - i ];
+    }
+
+    coeff = lowPassedCoeff;
+    return  coeff;
+  }
+
+  /** 
+   * Performs the definition of high pass filter from the low pass one
+   * in a Quadrature mirror filter bank framework. It is then valid to
+   * define high pass filters from orthogonal wavelets...
+   * Input is the forward low pass filter coefficients.
+   * It performs \f$ G(z) = H(-z) \f$.
+   */
+  CoefficientVector GetHighPassFilterFromLowPassFilter ( CoefficientVector & coeff ) 
+  {
+    unsigned long radius = static_cast<unsigned long>( coeff.size() );
+    this->SetRadius( radius );
+
+    unsigned long medianPosition = radius/2;
+
+    CoefficientVector highPassedCoeff;
+    highPassedCoeff = coeff;
+
+    for ( unsigned int i = 1; i < medianPosition; i+=2 )
+    {
+      highPassedCoeff[medianPosition + i] = - coeff[ medianPosition + i ];
+      highPassedCoeff[medianPosition - i] = - coeff[ medianPosition - i ];
+    }
+
+    coeff = highPassedCoeff;
+    return  coeff;
+  }
+
   unsigned int m_UpSampleFactor;
+  std::string m_Wavelet;
 };
 
 } // end of namespace otb