diff --git a/Code/BasicFilters/otbStreamingShrinkImageFilter.cxx b/Code/BasicFilters/otbStreamingShrinkImageFilter.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..3d4bd8d9e92b175790fb5236b101caa10bd7bf1e
--- /dev/null
+++ b/Code/BasicFilters/otbStreamingShrinkImageFilter.cxx
@@ -0,0 +1,103 @@
+/*=========================================================================
+
+  Program:   ORFEO Toolbox
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+
+  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+  See OTBCopyright.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.
+
+=========================================================================*/
+#include "otbStreamingShrinkImageFilter.h"
+
+namespace otb
+{
+
+unsigned int
+StreamingShrinkImageRegionSplitter
+::GetNumberOfSplits(const RegionType& region, unsigned int requestedNumber)
+{
+  unsigned int theoricalNbPixelPerTile = region.GetNumberOfPixels() / requestedNumber;
+  unsigned int theoricalTileDimension = static_cast<unsigned int> (vcl_sqrt(static_cast<double>(theoricalNbPixelPerTile)) );
+
+  // Take the previous multiple of m_TileSizeAlignment (eventually generate more splits than requested)
+  m_TileDimension = theoricalTileDimension / m_TileSizeAlignment * m_TileSizeAlignment;
+
+  // Minimal tile size is m_TileSizeAlignment * m_TileSizeAlignment
+  if (m_TileDimension < m_TileSizeAlignment)
+    {
+    otbMsgDevMacro(<< "Using the minimal tile size : " << m_TileSizeAlignment << " * " << m_TileSizeAlignment);
+    m_TileDimension = m_TileSizeAlignment;
+    }
+
+  // Use the computed tile size, and generate (m_TileDimension * 1) tiles
+  const SizeType&  regionSize = region.GetSize();
+  m_SplitsPerDimension[0] = (regionSize[0] + m_TileDimension - 1) / m_TileDimension;
+  m_SplitsPerDimension[1] = regionSize[1] / m_TileSizeAlignment;
+
+  unsigned int numPieces = 1;
+  for (unsigned int j = 0; j < ImageDimension; ++j)
+    {
+    numPieces *= m_SplitsPerDimension[j];
+    }
+
+  otbMsgDevMacro(<< "Tile dimension : " << m_TileDimension)
+  otbMsgDevMacro(<< "Number of splits per dimension : " << m_SplitsPerDimension[0] << " " <<  m_SplitsPerDimension[1])
+
+  return numPieces;
+}
+
+StreamingShrinkImageRegionSplitter::RegionType
+StreamingShrinkImageRegionSplitter
+::GetSplit(unsigned int i, unsigned int numberOfPieces, const RegionType& region)
+{
+  RegionType splitRegion;
+  IndexType  splitIndex;
+
+  // Compute the actual number of splits
+  unsigned int numPieces = 1;
+  for (unsigned int j = 0; j < ImageDimension; ++j)
+    {
+    numPieces *= m_SplitsPerDimension[j];
+    }
+
+  if (i >= numPieces)
+    {
+    itkExceptionMacro("Requested split number " << i << " but region contains only " << numPieces << " splits");
+    }
+
+  // Compute the split index in the streaming grid
+  splitIndex[1] = i / m_SplitsPerDimension[0];
+  splitIndex[0] = i % m_SplitsPerDimension[0];
+
+  // Transform the split index to the actual coordinates
+  splitRegion.SetIndex(0, region.GetIndex(0) + m_TileDimension * splitIndex[0]);
+  splitRegion.SetIndex(1, region.GetIndex(1) + m_TileSizeAlignment * splitIndex[1]);
+
+  splitRegion.SetSize(0, m_TileDimension);
+  splitRegion.SetSize(1, 1);
+
+  // Handle the borders
+  splitRegion.Crop(region);
+
+  return splitRegion;
+}
+
+void
+StreamingShrinkImageRegionSplitter
+::PrintSelf(std::ostream& os, itk::Indent indent) const
+{
+  Superclass::PrintSelf(os, indent);
+  os << indent << "SplitsPerDimension : " << m_SplitsPerDimension << std::endl;
+  os << indent << "TileDimension      : " << m_TileDimension << std::endl;
+  os << indent << "TileSizeAlignment  : " << m_TileSizeAlignment << std::endl;
+}
+
+} // End namespace otb
diff --git a/Code/BasicFilters/otbStreamingShrinkImageFilter.h b/Code/BasicFilters/otbStreamingShrinkImageFilter.h
index c077557e021e7e242895479b509ad395c5efa305..b6b3e9eabc91da4b5c32fc56b3e5d7b8f29e407b 100644
--- a/Code/BasicFilters/otbStreamingShrinkImageFilter.h
+++ b/Code/BasicFilters/otbStreamingShrinkImageFilter.h
@@ -25,11 +25,134 @@
 #include "otbPersistentImageFilter.h"
 #include "otbPersistentFilterStreamingDecorator.h"
 
-#include "itkTimeProbe.h"
+#include "otbStreamingManager.h"
 
 namespace otb
 {
 
+class ITK_EXPORT StreamingShrinkImageRegionSplitter : public itk::ImageRegionSplitter<2>
+{
+public:
+  /** Standard class typedefs. */
+  typedef StreamingShrinkImageRegionSplitter        Self;
+  typedef itk::ImageRegionSplitter<2>               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(StreamingShrinkImageRegionSplitter, itk::Object);
+
+  /** Dimension of the image available at compile time. */
+  itkStaticConstMacro(ImageDimension, unsigned int, 2);
+
+  /** Dimension of the image available at run time. */
+  static unsigned int GetImageDimension()
+  {
+    return ImageDimension;
+  }
+
+  /** Index typedef support. An index is used to access pixel values. */
+  typedef itk::Index<ImageDimension>         IndexType;
+  typedef IndexType::IndexValueType IndexValueType;
+
+  /** Size typedef support. A size is used to define region bounds. */
+  typedef itk::Size<ImageDimension>        SizeType;
+  typedef SizeType::SizeValueType SizeValueType;
+
+  /** Region typedef support.   */
+  typedef itk::ImageRegion<ImageDimension> RegionType;
+
+  /** How many pieces can the specified region be split? A given region
+   *  cannot always be divided into the requested number of pieces.  For
+   *  instance, if the numberOfPieces exceeds the number of pixels along
+   *  a certain dimensions, then some splits will not be possible.
+   */
+  virtual unsigned int GetNumberOfSplits(const RegionType& region,
+                                         unsigned int requestedNumber);
+
+  /** Get a region definition that represents the ith piece a specified region.
+   * The "numberOfPieces" specified should be less than or equal to what
+   * GetNumberOfSplits() returns. */
+  virtual RegionType GetSplit(unsigned int i, unsigned int numberOfPieces,
+                              const RegionType& region);
+
+  itkGetMacro(TileSizeAlignment, unsigned int);
+  itkSetMacro(TileSizeAlignment, unsigned int);
+
+  itkGetMacro(TileDimension, unsigned int);
+
+  itkSetMacro(ShrinkFactor, unsigned int);
+  itkGetMacro(ShrinkFactor, unsigned int);
+
+protected:
+  StreamingShrinkImageRegionSplitter() : m_SplitsPerDimension(0U), m_ShrinkFactor(10) {}
+  virtual ~StreamingShrinkImageRegionSplitter() {}
+  void PrintSelf(std::ostream& os, itk::Indent indent) const;
+
+private:
+  StreamingShrinkImageRegionSplitter(const StreamingShrinkImageRegionSplitter &); //purposely not implemented
+  void operator =(const StreamingShrinkImageRegionSplitter&); //purposely not implemented
+
+  itk::FixedArray<unsigned int, ImageDimension> m_SplitsPerDimension;
+  unsigned int m_TileDimension;
+  unsigned int m_TileSizeAlignment;
+  unsigned int m_ShrinkFactor;
+};
+
+
+template <class TInputImage>
+class ITK_EXPORT StreamingShrinkStreamingManager : public StreamingManager<TInputImage>
+{
+public:
+  /** Standard class typedefs. */
+  typedef StreamingShrinkStreamingManager Self;
+  typedef StreamingManager<TInputImage>   Superclass;
+  typedef itk::SmartPointer<Self>         Pointer;
+  typedef itk::SmartPointer<const Self>   ConstPointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+
+  /** Runtime information support. */
+  itkTypeMacro(StreamingShrinkStreamingManager, StreamingManager);
+
+  typedef TInputImage                            ImageType;
+  typedef typename ImageType::Pointer            ImagePointerType;
+  typedef typename ImageType::RegionType         RegionType;
+  typedef typename RegionType::IndexType         IndexType;
+  typedef typename RegionType::SizeType          SizeType;
+  typedef typename ImageType::InternalPixelType  PixelType;
+
+  itkStaticConstMacro(InputImageDimension, unsigned int, TInputImage::ImageDimension);
+
+  /** Actually computes the stream divisions, according to the specified streaming mode,
+   * eventually using the input parameter to estimate memory consumption */
+  virtual void PrepareStreaming(itk::DataObject * input, const RegionType &region);
+
+  void SetShrinkFactor(unsigned int val)
+  {
+    m_ShrinkFactor = val;
+  }
+
+  unsigned int GetShrinkFactor() const
+  {
+    return m_ShrinkFactor;
+  }
+
+protected:
+  StreamingShrinkStreamingManager();
+  virtual ~StreamingShrinkStreamingManager();
+
+private:
+  StreamingShrinkStreamingManager(const StreamingShrinkStreamingManager &); //purposely not implemented
+  void operator =(const StreamingShrinkStreamingManager&); //purposely not implemented
+
+  unsigned int m_ShrinkFactor;
+};
+
 
 /** \class PersistentShrinkImageFilter
  * \brief
@@ -116,9 +239,6 @@ private:
 
   /** The shrink factor */
   unsigned int m_ShrinkFactor;
-
-  itk::TimeProbe m_Chrono;
-
 }; // end of class PersistentStatisticsVectorImageFilter
 
 
@@ -156,10 +276,14 @@ public:
   typedef TOutputImage                                OutputImageType;
   typedef typename Superclass::FilterType             PersistentFilterType;
 
+  typedef StreamingShrinkStreamingManager<InputImageType>       StreamingShrinkStreamingManagerType;
+  typedef typename StreamingShrinkStreamingManagerType::Pointer StreamingShrinkStreamingManagerPointerType;
+
   void SetInput(InputImageType * input)
   {
     this->GetFilter()->SetInput(input);
   }
+
   const InputImageType * GetInput()
   {
     return this->GetFilter()->GetInput();
@@ -173,15 +297,29 @@ public:
   otbSetObjectMemberMacro(Filter, ShrinkFactor, unsigned int);
   otbGetObjectMemberMacro(Filter, ShrinkFactor, unsigned int);
 
+  virtual void Update(void)
+  {
+    m_StreamingManager->SetShrinkFactor( this->GetFilter()->GetShrinkFactor() );
+    Superclass::Update();
+  }
+
 protected:
   /** Constructor */
-  StreamingShrinkImageFilter() {}
+  StreamingShrinkImageFilter()
+  {
+    // Use a specific StreamingManager implementation
+    m_StreamingManager = StreamingShrinkStreamingManagerType::New();
+    this->GetStreamer()->SetStreamingManager( m_StreamingManager );
+  }
+
   /** Destructor */
   virtual ~StreamingShrinkImageFilter() {}
 
 private:
   StreamingShrinkImageFilter(const Self &); //purposely not implemented
   void operator =(const Self&); //purposely not implemented
+
+  StreamingShrinkStreamingManagerPointerType m_StreamingManager;
 };
 
 } // End namespace otb
diff --git a/Code/BasicFilters/otbStreamingShrinkImageFilter.txx b/Code/BasicFilters/otbStreamingShrinkImageFilter.txx
index 4c7a810c1bf1d2ea5026ed9822ccd697cae73ca0..cd045e31f27cf8c625ed7bb97dda07de7a163956 100644
--- a/Code/BasicFilters/otbStreamingShrinkImageFilter.txx
+++ b/Code/BasicFilters/otbStreamingShrinkImageFilter.txx
@@ -26,6 +26,34 @@
 namespace otb
 {
 
+template <class TImage>
+StreamingShrinkStreamingManager<TImage>::StreamingShrinkStreamingManager()
+{
+}
+
+template <class TImage>
+StreamingShrinkStreamingManager<TImage>::~StreamingShrinkStreamingManager()
+{
+}
+
+template <class TImage>
+void
+StreamingShrinkStreamingManager<TImage>::PrepareStreaming( itk::DataObject * input, const RegionType &region )
+{
+  typedef otb::StreamingShrinkImageRegionSplitter TileSplitterType;
+  TileSplitterType::Pointer splitter = TileSplitterType::New();
+  splitter->SetTileSizeAlignment(m_ShrinkFactor);
+  this->m_Splitter = splitter;
+
+  unsigned long nbDivisions = EstimateOptimalNumberOfDivisions(input, region);
+  this->m_ComputedNumberOfSplits = this->m_Splitter->GetNumberOfSplits(region, nbDivisions);
+  otbMsgDevMacro(<< "Number of split : " << this->m_ComputedNumberOfSplits)
+
+  // Save the region to generate the splits later
+  this->m_Region = region;
+}
+
+
 /** Constructor */
 template <class TInputImage, class TOutputImage>
 PersistentShrinkImageFilter<TInputImage, TOutputImage>
@@ -79,31 +107,22 @@ PersistentShrinkImageFilter<TInputImage, TOutputImage>
   // Nothing that needs to be allocated for the remaining outputs
 }
 
+
 template<class TInputImage, class TOutputImage>
 void
 PersistentShrinkImageFilter<TInputImage, TOutputImage>
 ::Reset()
 {
-  // Reinit the chrono
-  m_Chrono = itk::TimeProbe();
-
-  // get pointers to the input and output
+  // Get pointers to the input and output
   InputImageType* inputPtr = const_cast<InputImageType*>(this->GetInput());
   inputPtr->UpdateOutputInformation();
 
   m_ShrinkedOutput = OutputImageType::New();
 
-  // we need to compute the output spacing, the output image size, and the
-  // output image start index
   const typename InputImageType::SpacingType&
                                            inputSpacing = inputPtr->GetSpacing();
   const typename InputImageType::SizeType& inputSize
     = inputPtr->GetLargestPossibleRegion().GetSize();
-  const typename InputImageType::IndexType& inputStartIndex
-    = inputPtr->GetLargestPossibleRegion().GetIndex();
-  
-  otbMsgDebugMacro(<< "Input index " << inputStartIndex);
-  otbMsgDebugMacro(<< "Input size: " << inputSize);
 
   typename OutputImageType::SpacingType shrinkedOutputSpacing;
   typename OutputImageType::RegionType  shrinkedOutputLargestPossibleRegion;
@@ -113,9 +132,7 @@ PersistentShrinkImageFilter<TInputImage, TOutputImage>
   for (unsigned int i = 0; i < OutputImageType::ImageDimension; ++i)
     {
     shrinkedOutputSpacing[i] = inputSpacing[i] * static_cast<double>(m_ShrinkFactor);
-    //shrinkedOutputSize[i] = static_cast<int>(static_cast<double>(inputSize[i]) / static_cast<double>(m_ShrinkFactor));
     shrinkedOutputSize[i] = inputSize[i] / m_ShrinkFactor;
-    //outputStartIndex[i] = inputStartIndex[i];
     shrinkedOutputStartIndex[i] = 0;
     }
 
@@ -134,7 +151,6 @@ void
 PersistentShrinkImageFilter<TInputImage, TOutputImage>
 ::Synthetize()
 {
-  otbMsgDevMacro( "Shrink time : " << m_Chrono.GetTotal() )
 }
 
 template<class TInputImage, class TOutputImage>
@@ -142,7 +158,6 @@ void
 PersistentShrinkImageFilter<TInputImage, TOutputImage>
 ::BeforeThreadedGenerateData()
 {
-  m_Chrono.Start();
 }
 
 template<class TInputImage, class TOutputImage>
@@ -175,7 +190,6 @@ void
 PersistentShrinkImageFilter<TInputImage, TOutputImage>
 ::AfterThreadedGenerateData()
 {
-  m_Chrono.Stop();
 }
 
 template <class TImage, class TOutputImage>