diff --git a/Code/Common/otbStreamingManager.h b/Code/Common/otbStreamingManager.h
new file mode 100644
index 0000000000000000000000000000000000000000..6d5d81b43aca507d7c8b05df9fb7ba93dc099047
--- /dev/null
+++ b/Code/Common/otbStreamingManager.h
@@ -0,0 +1,196 @@
+/*=========================================================================
+
+  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.
+
+=========================================================================*/
+#ifndef __otbStreamingManager_h
+#define __otbStreamingManager_h
+
+#include "otbMacro.h"
+#include "otbConfigure.h"
+
+#include "itkLightObject.h"
+#include "itkImageRegionSplitter.h"
+
+namespace otb
+{
+
+namespace StreamingManagement
+{
+  enum StreamingMode
+  {
+    /** Estimates the memory used by the pipeline
+     * and set the strips size to fit the specified
+     * available RAM
+     */
+    STRIPPED_AVAILABLE_RAM,
+
+    /** Force the use of a specific number of lines per strips
+     */
+    STRIPPED_SET_NUMBEROFLINES,
+
+    /** Estimates the memory used that will be used during the pipeline
+     * execution and set the tile size to fit the specified
+     * available RAM.
+     */
+    TILED_AVAILABLE_RAM,
+
+    /** Force the use of a specific tile dimension
+     * The associated parameter is the size used in each dimension
+     */
+    TILED_SET_TILE_SIZE,
+  };
+}
+
+/** \class StreamingManager
+ *  \brief This class handles the streaming process used in the writers implementation
+ *
+ *  The streaming mode can be chosen with either SetStrippedRAMStreamingMode, SetStrippedNumberOfLinesStreamingMode,
+ *  SetTiledRAMStreamingMode, or SetTiledTileDimensionStreamingMode.
+ *
+ *  Then, PrepareStreaming must be called so that the stream type and dimensions are computed
+ *  This involves passing the actual DataObject who will be written, since it will be used
+ *  during memory estimation for some specific streaming modes.
+ *
+ *  After PrepareStreaming has been called, the actual number of splits and streaming mode which will be used
+ *  can be retrieved with GetStreamingMode and GetNumberOfSplits.
+ *  The different splits can be retrieved with GetSplit
+ *
+ * \sa StreamingImageFileWriter
+ * \sa StreamingImageVirtualFileWriter
+ */
+template<class TImage>
+class ITK_EXPORT StreamingManager : public itk::LightObject
+{
+public:
+  /** Standard class typedefs. */
+  typedef StreamingManager               Self;
+  typedef itk::LightObject               Superclass;
+  typedef itk::SmartPointer<Self>        Pointer;
+  typedef itk::SmartPointer<const Self>  ConstPointer;
+
+  typedef TImage                                 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;
+
+  typedef StreamingManagement::StreamingMode     StreamingModeType;
+
+  /** Creation through object factory macro */
+  itkNewMacro(Self);
+
+  /** Type macro */
+  itkTypeMacro(StreamingManager, itk::LightObject);
+
+  /** Dimension of input image. */
+  itkStaticConstMacro(ImageDimension, unsigned int, ImageType::ImageDimension);
+
+  /** Use stripped mode.
+   * The number of lines of the strips are computed by estimating the
+   * memory footprint of the pipeline, and chosen so that no more than
+   * availableRAM MBytes of memory are used.
+   * If no parameter is given, then the available RAM is retrieved from the
+   * OTB configuration file or build configuration option */
+  virtual void SetStrippedRAMStreamingMode( unsigned int availableRAMInMB = 0 );
+
+  /** Use stripped mode.
+   * The number of lines of the strips are explicitely specified */
+  virtual void SetStrippedNumberOfLinesStreamingMode( unsigned int numberOfLines );
+
+  /** Use tiled mode.
+   * The dimensions of the tiles are computed by estimating the
+   * memory footprint of the pipeline, and chosen so that no more than
+   * availableRAM MBytes of memory are used.
+   *
+   * If no parameter is given, then the available RAM is retrieved from the
+   * OTB configuration file or build configuration option.
+   *
+   * The tiles are set to be square, with dimension aligned with multiple of 16 */
+  virtual void SetTiledRAMStreamingMode( unsigned int availableRAMInMB = 0 );
+
+  /** Use tiled mode.
+   * The dimension of the tile are explicitely specified.
+   * The parameter specifies the size of the tile in each dimension.  */
+  virtual void SetTiledTileDimensionStreamingMode( unsigned int tileDimension );
+
+  /** Actually computes the stream divisions, accorfing to the specified streaming mode,
+   * eventually using the input parameter to estimate memory consumption */
+  virtual void PrepareStreaming(itk::DataObject * input, const RegionType &region);
+
+  /** Returns the actual streaming mode that will be used to process the image.
+   * PrepareStreaming() must have been called before.
+   * This can be different than the required streaming mode. For example, if
+   * the input passed to PrepareStreaming() is fully buffered, then
+   * the STRIPPED_SET_NUMBEROFLINES mode is used with only one strip */
+  virtual StreamingManagement::StreamingMode GetStreamingMode();
+
+  /** Returns the actual number of pieces that will be used to process the image.
+   * PrepareStreaming() must have been called before.
+   * This can be different than the requested number */
+  virtual unsigned int GetNumberOfSplits();
+
+  /** Get a region definition that represents the ith piece a specified region.
+   * The "numberOfPieces" must be equal to what
+   * GetNumberOfSplits() returns. */
+  virtual RegionType GetSplit(unsigned int i);
+
+
+public:
+  StreamingManager();
+  virtual ~StreamingManager();
+
+  virtual unsigned int EstimateOptimalNumberOfDivisions(itk::DataObject * input, const RegionType &region);
+
+  /** The desired streaming mode specified by the user */
+  StreamingManagement::StreamingMode m_DesiredMode;
+
+  /** The actual streaming mode which will be used */
+  StreamingManagement::StreamingMode m_ActualMode;
+
+  /** The available RAM set as parameter when using the STRIPPED_AVAILABLE_RAM or TILED_AVAILABLE_RAM mode */
+  unsigned int m_AvailableRAMInMB;
+
+  /** The desired number of lines when using the STRIPPED_SET_NUMBEROFLINES streaming mode */
+  unsigned int m_DesiredNumberOfLines;
+
+  /** The desired tile dimension when using the TILED_SET_TILE_SIZE streaming mode */
+  unsigned int m_DesiredTileDimension;
+
+  /** The computed number of splits after PrepareStreaming has been called */
+  unsigned int m_ComputedNumberOfSplits;
+
+  /** The region to stream */
+  RegionType m_Region;
+
+  /** The splitter used to compute the different strips */
+  typedef itk::ImageRegionSplitter<itkGetStaticConstMacro(ImageDimension)> AbstractSplitterType;
+  typedef typename AbstractSplitterType::Pointer AbstractSplitterPointerType;
+  AbstractSplitterPointerType m_Splitter;
+
+private:
+  StreamingManager(const StreamingManager &); //purposely not implemented
+  void operator =(const StreamingManager&); //purposely not implemented
+
+};
+
+} // End namespace otb
+
+#ifndef OTB_MANUAL_INSTANTIATION
+#include "otbStreamingManager.txx"
+#endif
+
+#endif
diff --git a/Code/Common/otbStreamingManager.txx b/Code/Common/otbStreamingManager.txx
new file mode 100644
index 0000000000000000000000000000000000000000..5816141f677d42ef900cf42331ef8ae89ac12a7a
--- /dev/null
+++ b/Code/Common/otbStreamingManager.txx
@@ -0,0 +1,291 @@
+/*=========================================================================
+
+  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.
+
+=========================================================================*/
+#ifndef __otbStreamingManager_txx
+#define __otbStreamingManager_txx
+
+#include "otbStreamingManager.h"
+#include "otbMacro.h"
+#include "otbConfigure.h"
+#include "otbConfigurationFile.h"
+#include "otbPipelineMemoryPrintCalculator.h"
+#include "itkExtractImageFilter.h"
+
+#include "otbImageRegionSquareTileSplitter.h"
+#include "itkImageRegionSplitter.h"
+
+namespace otb
+{
+
+template <class TImage>
+StreamingManager<TImage>::StreamingManager()
+  : m_DesiredMode(StreamingManagement::TILED_AVAILABLE_RAM),
+    m_ActualMode(StreamingManagement::TILED_AVAILABLE_RAM),
+    m_AvailableRAMInMB(0),
+    m_DesiredNumberOfLines(0),
+    m_DesiredTileDimension(0),
+    m_ComputedNumberOfSplits(0)
+{
+}
+
+template <class TImage>
+StreamingManager<TImage>::~StreamingManager()
+{
+}
+
+template <class TImage>
+void
+StreamingManager<TImage>::SetStrippedRAMStreamingMode( unsigned int availableRAMInMB )
+{
+  m_DesiredMode = StreamingManagement::STRIPPED_AVAILABLE_RAM;
+  m_AvailableRAMInMB = availableRAMInMB;
+}
+
+template <class TImage>
+void
+StreamingManager<TImage>::SetStrippedNumberOfLinesStreamingMode( unsigned int numberOfLines )
+{
+  m_DesiredMode = StreamingManagement::STRIPPED_SET_NUMBEROFLINES;
+  m_DesiredNumberOfLines = numberOfLines;
+}
+
+template <class TImage>
+void
+StreamingManager<TImage>::SetTiledRAMStreamingMode( unsigned int availableRAMInMB )
+{
+  otbMsgDevMacro(<< "StreamingManager::SetTiledRAMStreamingMode " << availableRAMInMB)
+  m_DesiredMode = StreamingManagement::TILED_AVAILABLE_RAM;
+  m_AvailableRAMInMB = availableRAMInMB;
+}
+
+template <class TImage>
+void
+StreamingManager<TImage>::SetTiledTileDimensionStreamingMode( unsigned int tileDimension )
+{
+  m_DesiredMode = StreamingManagement::TILED_SET_TILE_SIZE;
+  m_DesiredTileDimension = tileDimension;
+}
+
+template <class TImage>
+void
+StreamingManager<TImage>::PrepareStreaming( itk::DataObject * input, const RegionType &region )
+{
+  switch (m_DesiredMode)
+  {
+    case StreamingManagement::STRIPPED_AVAILABLE_RAM:
+      {
+      otbMsgDevMacro(<< "Activating STRIPPED_AVAILABLE_RAM streaming mode")
+      unsigned long nbDivisions = EstimateOptimalNumberOfDivisions(input, region);
+      m_Splitter = itk::ImageRegionSplitter<itkGetStaticConstMacro(ImageDimension)>::New();
+      m_ComputedNumberOfSplits = m_Splitter->GetNumberOfSplits(region, nbDivisions);
+
+      otbMsgDevMacro(<< "Number of split : " << m_ComputedNumberOfSplits)
+      }
+      break;
+
+    case StreamingManagement::STRIPPED_SET_NUMBEROFLINES:
+      {
+      otbMsgDevMacro(<< "Activating STRIPPED_SET_NUMBEROFLINES streaming mode")
+      if (m_DesiredNumberOfLines < 1)
+        {
+        itkWarningMacro(<< "DesiredNumberOfLines set to 0 : use 1 as strip number of lines")
+        m_DesiredNumberOfLines = 1;
+        }
+
+      /* Calculate number of split */
+      unsigned long numberLinesOfRegion = region.GetSize()[1]; // Y dimension
+      unsigned long nbSplit;
+      if (numberLinesOfRegion > m_DesiredNumberOfLines)
+        {
+        nbSplit =
+          static_cast<unsigned long>(vcl_ceil(static_cast<double>(numberLinesOfRegion) /
+                                              static_cast<double>(m_DesiredNumberOfLines)));
+        }
+      else
+        {
+        // Don't stream
+        nbSplit = 1;
+        }
+
+      m_Splitter = itk::ImageRegionSplitter<itkGetStaticConstMacro(ImageDimension)>::New();
+      m_ComputedNumberOfSplits = m_Splitter->GetNumberOfSplits(region, nbSplit);
+      otbMsgDevMacro(<< "Number of split : " << m_ComputedNumberOfSplits)
+      }
+      break;
+
+    case StreamingManagement::TILED_AVAILABLE_RAM:
+      {
+      otbMsgDevMacro(<< "Activating TILED_AVAILABLE_RAM streaming mode")
+      unsigned long nbDivisions = EstimateOptimalNumberOfDivisions(input, region);
+      m_Splitter = otb::ImageRegionSquareTileSplitter<itkGetStaticConstMacro(ImageDimension)>::New();
+      m_ComputedNumberOfSplits = m_Splitter->GetNumberOfSplits(region, nbDivisions);
+      otbMsgDevMacro(<< "Number of split : " << m_ComputedNumberOfSplits)
+      }
+      break;
+
+    case StreamingManagement::TILED_SET_TILE_SIZE:
+      {
+      otbMsgDevMacro(<< "Activating TILED_SET_TILE_SIZE streaming mode")
+      if (m_DesiredTileDimension < 16)
+        {
+        itkWarningMacro(<< "DesiredTileDimension inferior to 16 : use 16 as tile dimension")
+        m_DesiredTileDimension = 16;
+        }
+
+      // Calculate number of split
+      m_Splitter = otb::ImageRegionSquareTileSplitter<itkGetStaticConstMacro(ImageDimension)>::New();
+      unsigned int nbDesiredTiles = itk::Math::Ceil<unsigned int>( double(region.GetNumberOfPixels()) / (m_DesiredTileDimension * m_DesiredTileDimension) );
+      m_ComputedNumberOfSplits = m_Splitter->GetNumberOfSplits(region, nbDesiredTiles);
+      otbMsgDevMacro(<< "Number of split : " << m_ComputedNumberOfSplits)
+      }
+      break;
+  }
+
+  // Save the region to generate the splits later
+  m_Region = region;
+}
+
+
+template <class TImage>
+unsigned int
+StreamingManager<TImage>::EstimateOptimalNumberOfDivisions(itk::DataObject * input, const RegionType &region)
+{
+  otbMsgDevMacro(<< "m_AvailableRAMInMB " << m_AvailableRAMInMB)
+  unsigned int availableRAMInBytes = m_AvailableRAMInMB * 1024 * 1024;
+
+  if (availableRAMInBytes == 0)
+    {
+    otbMsgDevMacro(<< "Retrieving available RAM size from configuration")
+    // Retrieve it from the configuration
+    try
+      {
+      typedef otb::ConfigurationFile ConfigurationType;
+      ConfigurationType::Pointer conf = ConfigurationType::GetInstance();
+
+      availableRAMInBytes = conf->GetParameter<unsigned int>(
+        "OTB_STREAM_MAX_SIZE_BUFFER_FOR_STREAMING");
+      }
+    catch(...)
+      {
+      // We should never have to go here if the configuration file is
+      // correct and found.
+      // In case it is not fallback on the cmake
+      // defined constants.
+      availableRAMInBytes = OTB_STREAM_MAX_SIZE_BUFFER_FOR_STREAMING;
+      }
+    }
+
+  otbMsgDevMacro("RAM used to estimate memory footprint : " << availableRAMInBytes / 1024 / 1024  << " MB")
+
+  otb::PipelineMemoryPrintCalculator::Pointer memoryPrintCalculator;
+  memoryPrintCalculator = otb::PipelineMemoryPrintCalculator::New();
+
+  memoryPrintCalculator->SetAvailableMemory( availableRAMInBytes );
+
+  // Trick to avoid having the resampler compute the whole
+  // deformation field
+  double regionTrickFactor = 1;
+  ImageType* inputImage = dynamic_cast<ImageType*>(input);
+  //inputImage = 0;
+  if (inputImage)
+    {
+
+    typedef itk::ExtractImageFilter<ImageType,ImageType> ExtractFilterType;
+    typename ExtractFilterType::Pointer extractFilter = ExtractFilterType::New();
+    extractFilter->SetInput(inputImage);
+
+    // Define a small region to run the memory footprint estimation,
+    // around the image center, 100 pixels wide in each dimension
+    SizeType smallSize;
+    smallSize.Fill(100);
+    IndexType index;
+    index[0] = region.GetIndex()[0] + region.GetSize()[0]/2 - 50;
+    index[1] = region.GetIndex()[1] + region.GetSize()[1]/2 - 50;
+
+    RegionType smallRegion;
+    smallRegion.SetSize(smallSize);
+    smallRegion.SetIndex(index);
+
+    // In case the image is smaller than 100 pixels in a direction
+    smallRegion.Crop(region);
+
+    extractFilter->SetExtractionRegion(smallRegion);
+
+    bool smallRegionSuccess = smallRegion.Crop(region);
+
+    if (smallRegionSuccess)
+      {
+      otbMsgDevMacro("Using an extract to estimate memory : " << smallRegion)
+      // the region is well behaved, inside the largest possible region
+      memoryPrintCalculator->SetDataToWrite(extractFilter->GetOutput());
+      regionTrickFactor = static_cast<double>( region.GetNumberOfPixels() )
+          / static_cast<double>(smallRegion.GetNumberOfPixels());
+
+      memoryPrintCalculator->SetBiasCorrectionFactor(regionTrickFactor);
+      }
+    else
+      {
+      otbMsgDevMacro("Using the input region to estimate memory : " << region)
+      // the region is not well behaved
+      // use the full region
+      memoryPrintCalculator->SetDataToWrite(input);
+      memoryPrintCalculator->SetBiasCorrectionFactor(1.0);
+      }
+
+    memoryPrintCalculator->Compute();
+    }
+  else
+    {
+    // Use the original object to estimate memory footprint
+    memoryPrintCalculator->SetDataToWrite(input);
+    memoryPrintCalculator->SetBiasCorrectionFactor(1.0);
+
+    memoryPrintCalculator->Compute();
+    }
+
+  otbMsgDevMacro( "Estimated Memory print for the full image : "
+                   << static_cast<unsigned int>(memoryPrintCalculator->GetMemoryPrint() / 1024 / 1024 ) << std::endl)
+  otbMsgDevMacro( "Optimal number of stream divisions: "
+                   << memoryPrintCalculator->GetOptimalNumberOfStreamDivisions() << std::endl)
+
+  return memoryPrintCalculator->GetOptimalNumberOfStreamDivisions();
+}
+
+template <class TImage>
+StreamingManagement::StreamingMode
+StreamingManager<TImage>::GetStreamingMode()
+{
+  return m_ActualMode;
+}
+
+template <class TImage>
+unsigned int
+StreamingManager<TImage>::GetNumberOfSplits()
+{
+  return m_ComputedNumberOfSplits;
+}
+
+template <class TImage>
+typename StreamingManager<TImage>::RegionType
+StreamingManager<TImage>::GetSplit(unsigned int i)
+{
+  return m_Splitter->GetSplit(i, m_ComputedNumberOfSplits, m_Region);
+}
+
+} // End namespace otb
+
+#endif
diff --git a/Code/IO/otbStreamingImageVirtualWriter.h b/Code/IO/otbStreamingImageVirtualWriter.h
index 9ae59e84295c01dce381482e85a1852d6378d888..99e72c1c06736795f2aedfb9f58b02bfa16a7e82 100644
--- a/Code/IO/otbStreamingImageVirtualWriter.h
+++ b/Code/IO/otbStreamingImageVirtualWriter.h
@@ -20,8 +20,7 @@
 
 #include "itkMacro.h"
 #include "itkImageToImageFilter.h"
-#include "itkImageRegionSplitter.h"
-#include "otbStreamingTraits.h"
+#include "otbStreamingManager.h"
 
 namespace otb
 {
@@ -45,7 +44,7 @@ namespace otb
  * \sa PersistentStatisticsImageFilter
  * \sa PersistentImageStreamingDecorator.
  */
-template <class TInputImage>
+template <class TInputImage, class TStreamingManager = StreamingManager<TInputImage> >
 class ITK_EXPORT StreamingImageVirtualWriter : public itk::ImageToImageFilter<TInputImage, TInputImage>
 {
 public:
@@ -68,86 +67,62 @@ public:
   typedef typename InputImageType::PixelType  InputImagePixelType;
 
   /** Streaming traits helper typedef */
-  typedef StreamingTraits<InputImageType> StreamingTraitsType;
+  typedef TStreamingManager                      StreamingManagerType;
+  typedef typename StreamingManagerType::Pointer StreamingManagerPointerType;
 
   /** Dimension of input image. */
   itkStaticConstMacro(InputImageDimension, unsigned int,
                       InputImageType::ImageDimension);
 
-  /** Set/Get the image input of this writer.  */
-  void SetInput(const InputImageType *input);
-  const InputImageType * GetInput(void);
-  const InputImageType * GetInput(unsigned int idx);
+  StreamingManagerType* GetStreamingManager(void)
+    {
+    return m_StreamingManager;
+    }
 
-  void SetNthInput(unsigned int idx, const InputImageType *input);
-
-
-  /** SmartPointer to a region splitting object */
-  typedef itk::ImageRegionSplitter<itkGetStaticConstMacro(InputImageDimension)> SplitterType;
-  typedef typename SplitterType::Pointer                                        RegionSplitterPointer;
-
-  /**  Set buffer memory size (in bytes) use to calculate the number of stream divisions */
-  void SetBufferMemorySize(unsigned long);
-
-  /**  Set the buffer number of lines use to calculate the number of stream divisions */
-  void SetBufferNumberOfLinesDivisions(unsigned long);
-
-  /**  The number of stream divisions is calculate by using
-   * OTB_STREAM_IMAGE_SIZE_TO_ACTIVATE_STREAMING and
-   * OTB_STREAM_MAX_SIZE_BUFFER_FOR_STREAMING cmake variables.
-   */
-  void SetAutomaticNumberOfStreamDivisions(void);
-
-  /** Set the tiling automatic mode for streaming division */
-  void SetTilingStreamDivisions(void);
-  /** Choose number of divisions in tiling streaming division */
-  void SetTilingStreamDivisions(unsigned long);
-
-  /** Return the string to indicate the method use to calculate number of stream divisions. */
-  std::string GetMethodUseToCalculateNumberOfStreamDivisions(void);
-
-  /** Set the number of pieces to divide the input.  The upstream pipeline
-   * will be executed this many times. */
-  void SetNumberOfStreamDivisions(unsigned long);
-
-  /** Get the number of pieces to divide the input. The upstream pipeline
-   * will be executed this many times. */
-  unsigned long GetNumberOfStreamDivisions(void);
-
-  /** Set the helper class for dividing the input into chunks. */
-  itkSetObjectMacro(RegionSplitter, SplitterType);
-
-  /** Get the helper class for dividing the input into chunks. */
-  itkGetObjectMacro(RegionSplitter, SplitterType);
-
-  /** Type use to define number of divisions */
-  typedef StreamingMode CalculationDivisionEnumType;
-
-  virtual void GenerateInputRequestedRegion(void);
+  void SetStreamingManager(StreamingManagerType* streamingManager)
+    {
+    m_StreamingManager = streamingManager;
+    }
 
 protected:
   StreamingImageVirtualWriter();
+
   virtual ~StreamingImageVirtualWriter();
+
   void PrintSelf(std::ostream& os, itk::Indent indent) const;
 
   virtual void GenerateData(void);
 
+  virtual void GenerateInputRequestedRegion(void);
+
 private:
   StreamingImageVirtualWriter(const StreamingImageVirtualWriter &); //purposely not implemented
   void operator =(const StreamingImageVirtualWriter&); //purposely not implemented
 
-  /** This method calculate the number of stream divisions, by using the CalculationDivision type */
-  unsigned long CalculateNumberOfStreamDivisions(void);
+  void ObserveSourceFilterProgress(itk::Object* object, const itk::EventObject & event )
+  {
+    if (typeid(event) != typeid(itk::ProgressEvent))
+      {
+      return;
+      }
+
+    itk::ProcessObject* processObject = dynamic_cast<itk::ProcessObject*>(object);
+    if (processObject)
+      m_DivisionProgress = processObject->GetProgress();
+
+    this->UpdateFilterProgress();
+  }
 
-  /** Use to define the method used to calculate number of divisions */
-  unsigned long m_BufferMemorySize;
-  unsigned long m_BufferNumberOfLinesDivisions;
-  unsigned long m_NumberOfStreamDivisions;
+  void UpdateFilterProgress()
+  {
+    this->UpdateProgress( (m_DivisionProgress + m_CurrentDivision) / m_NumberOfDivisions );
+  }
 
-  RegionSplitterPointer m_RegionSplitter;
+  unsigned int m_NumberOfDivisions;
+  unsigned int m_CurrentDivision;
+  float m_DivisionProgress;
 
-  /** Use to determine method of calculation number of divisions */
-  CalculationDivisionEnumType m_CalculationDivision;
+  StreamingManagerPointerType m_StreamingManager;
 };
 
 } // end namespace otb
diff --git a/Code/IO/otbStreamingImageVirtualWriter.txx b/Code/IO/otbStreamingImageVirtualWriter.txx
index ce0b5938974e80d17265524e360b278f9aa013df..6ffd8621b5b05c4adf5c3439fb772b80694dcdd6 100644
--- a/Code/IO/otbStreamingImageVirtualWriter.txx
+++ b/Code/IO/otbStreamingImageVirtualWriter.txx
@@ -19,231 +19,55 @@
 #define __otbStreamingImageVirtualWriter_txx
 #include "otbStreamingImageVirtualWriter.h"
 
-#include "itkCommand.h"
-#include "itkImageRegionIterator.h"
-#include "itkObjectFactoryBase.h"
-#include "itkImageFileWriter.h"
-#include "itkImageRegionMultidimensionalSplitter.h"
-
 #include "otbMacro.h"
 #include "otbConfigure.h"
+#include "itkCommand.h"
 
 namespace otb
 {
-/**
- *
- */
-template <class TInputImage>
-StreamingImageVirtualWriter<TInputImage>
+
+template <class TInputImage, class TStreamingManager>
+StreamingImageVirtualWriter<TInputImage,TStreamingManager>
 ::StreamingImageVirtualWriter()
 {
-  m_BufferMemorySize = 0;
-  m_BufferNumberOfLinesDivisions = 0;
-  // default to 10 divisions
-  m_NumberOfStreamDivisions = 0;
-  // default to AUTOMATIC_NUMBER_OF_DIVISIONS
-  m_CalculationDivision = SET_AUTOMATIC_NUMBER_OF_STREAM_DIVISIONS;
-
-  // create default region splitter
-  m_RegionSplitter = itk::ImageRegionSplitter<InputImageDimension>::New();
+  m_StreamingManager = StreamingManagerType::New();
 }
 
-/**
- *
- */
-template <class TInputImage>
-StreamingImageVirtualWriter<TInputImage>
+template <class TInputImage, class TStreamingManager>
+StreamingImageVirtualWriter<TInputImage,TStreamingManager>
 ::~StreamingImageVirtualWriter()
 {
 }
 
-/**
- *
- */
-template <class TInputImage>
-void
-StreamingImageVirtualWriter<TInputImage>
-::SetBufferMemorySize(unsigned long memory_size_divisions)
-{
-  m_BufferMemorySize = memory_size_divisions;
-  m_CalculationDivision = SET_BUFFER_MEMORY_SIZE;
-  this->Modified();
-}
-
-/**
- *
- */
-template <class TInputImage>
-void
-StreamingImageVirtualWriter<TInputImage>
-::SetBufferNumberOfLinesDivisions(unsigned long nb_lines_divisions)
-{
-  m_BufferNumberOfLinesDivisions = nb_lines_divisions;
-  m_CalculationDivision = SET_BUFFER_NUMBER_OF_LINES;
-  this->Modified();
-}
-
-/**
- *
- */
-template <class TInputImage>
-void
-StreamingImageVirtualWriter<TInputImage>
-::SetNumberOfStreamDivisions(unsigned long nb_divisions)
-{
-  m_NumberOfStreamDivisions = nb_divisions;
-  m_CalculationDivision = SET_NUMBER_OF_STREAM_DIVISIONS;
-  this->Modified();
-}
-
-/**
- *
- */
-template <class TInputImage>
-void
-StreamingImageVirtualWriter<TInputImage>
-::SetAutomaticNumberOfStreamDivisions(void)
-{
-  m_CalculationDivision = SET_AUTOMATIC_NUMBER_OF_STREAM_DIVISIONS;
-  this->Modified();
-}
-
-/**
- *
- */
-template <class TInputImage>
+template <class TInputImage, class TStreamingManager>
 void
-StreamingImageVirtualWriter<TInputImage>
-::SetTilingStreamDivisions(void)
-{
-  m_CalculationDivision = SET_TILING_WITH_SET_AUTOMATIC_NUMBER_OF_STREAM_DIVISIONS;
-  m_RegionSplitter = itk::ImageRegionMultidimensionalSplitter<InputImageDimension>::New();
-  this->Modified();
-}
-
-template <class TInputImage>
-void
-StreamingImageVirtualWriter<TInputImage>
-::SetTilingStreamDivisions(unsigned long nb_divisions)
-{
-  m_CalculationDivision = SET_TILING_WITH_SET_NUMBER_OF_STREAM_DIVISIONS;
-  m_NumberOfStreamDivisions = nb_divisions;
-  m_RegionSplitter = itk::ImageRegionMultidimensionalSplitter<InputImageDimension>::New();
-  this->Modified();
-}
-
-template <class TInputImage>
-void
-StreamingImageVirtualWriter<TInputImage>
-::SetInput(const InputImageType *input)
-{
-  this->SetNthInput(0, input);
-}
-
-template <class TInputImage>
-void
-StreamingImageVirtualWriter<TInputImage>
-::SetNthInput(unsigned int idx, const InputImageType *input)
-{
-  // ProcessObject is not const_correct so this cast is required here.
-  this->itk::ProcessObject::SetNthInput(idx,
-                                        const_cast<TInputImage *>(input));
-}
-
-template <class TInputImage>
-const typename StreamingImageVirtualWriter<TInputImage>::InputImageType *
-StreamingImageVirtualWriter<TInputImage>
-::GetInput(void)
-{
-  if (this->GetNumberOfInputs() < 1)
-    {
-    return 0;
-    }
-
-  return static_cast<TInputImage*>
-           (this->itk::ProcessObject::GetInput(0));
-}
-
-template <class TInputImage>
-const typename StreamingImageVirtualWriter<TInputImage>::InputImageType *
-StreamingImageVirtualWriter<TInputImage>
-::GetInput(unsigned int idx)
+StreamingImageVirtualWriter<TInputImage,TStreamingManager>
+::PrintSelf(std::ostream& os, itk::Indent indent) const
 {
-  return static_cast<TInputImage*> (this->itk::ProcessObject::GetInput(idx));
+  Superclass::PrintSelf(os, indent);
 }
 
-template <class TInputImage>
+template <class TInputImage, class TStreamingManager>
 void
-StreamingImageVirtualWriter<TInputImage>
+StreamingImageVirtualWriter<TInputImage,TStreamingManager>
 ::GenerateInputRequestedRegion(void)
 {
   InputImagePointer                        inputPtr = const_cast<InputImageType *>(this->GetInput(0));
+
+  InputImageRegionType                     region;
   typename InputImageRegionType::SizeType  size;
   typename InputImageRegionType::IndexType index;
-  InputImageRegionType                     region;
+
   index.Fill(0);
   size.Fill(0);
   region.SetSize(size);
   region.SetIndex(index);
   inputPtr->SetRequestedRegion(region);
 }
-/**
- *
- */
-template <class TInputImage>
-unsigned long
-StreamingImageVirtualWriter<TInputImage>
-::GetNumberOfStreamDivisions(void)
-{
-  return (CalculateNumberOfStreamDivisions());
-}
-template<class TInputImage>
-unsigned long
-StreamingImageVirtualWriter<TInputImage>
-::CalculateNumberOfStreamDivisions(void)
-{
-  return StreamingTraitsType
-         ::CalculateNumberOfStreamDivisions(this->GetInput(),
-                                            this->GetInput()->GetLargestPossibleRegion(),
-                                            m_RegionSplitter,
-                                            m_CalculationDivision,
-                                            m_NumberOfStreamDivisions,
-                                            m_BufferMemorySize,
-                                            m_BufferNumberOfLinesDivisions);
-}
-/**
- *
- */
-template <class TInputImage>
-std::string
-StreamingImageVirtualWriter<TInputImage>
-::GetMethodUseToCalculateNumberOfStreamDivisions(void)
-{
-  return (StreamingTraitsType::GetMethodUseToCalculateNumberOfStreamDivisions(m_CalculationDivision));
-}
-/**
- *
- */
-template <class TInputImage>
-void
-StreamingImageVirtualWriter<TInputImage>
-::PrintSelf(std::ostream& os, itk::Indent indent) const
-{
-  Superclass::PrintSelf(os, indent);
-  os << indent << "Number of stream divisions: " << m_NumberOfStreamDivisions
-     << std::endl;
-  if (m_RegionSplitter)
-    {
-    os << indent << "Region splitter:" << m_RegionSplitter << std::endl;
-    }
-  else
-    {
-    os << indent << "Region splitter: (none)" << std::endl;
-    }
-}
-template<class TInputImage>
+
+template<class TInputImage, class TStreamingManager>
 void
-StreamingImageVirtualWriter<TInputImage>
+StreamingImageVirtualWriter<TInputImage,TStreamingManager>
 ::GenerateData(void)
 {
   /**
@@ -257,6 +81,7 @@ StreamingImageVirtualWriter<TInputImage>
    * Tell all Observers that the filter is starting
    */
   this->InvokeEvent(itk::StartEvent());
+
   /**
    * Grab the input
    */
@@ -267,25 +92,47 @@ StreamingImageVirtualWriter<TInputImage>
    * minimum of what the user specified via SetNumberOfStreamDivisions()
    * and what the Splitter thinks is a reasonable value.
    */
-  unsigned int numDivisions;
-  numDivisions = static_cast<unsigned int>(CalculateNumberOfStreamDivisions());
+  m_StreamingManager->PrepareStreaming(inputPtr, outputRegion);
+  m_NumberOfDivisions = m_StreamingManager->GetNumberOfSplits();
+
+  /**
+   * Register to the ProgressEvent of the source filter
+   */
+  // Get the source process object
+  itk::ProcessObject* source = inputPtr->GetSource();
+
+  // Check if source exists
+  if(source)
+    {
+    typedef itk::MemberCommand<Self> CommandType;
+    typedef typename CommandType::Pointer CommandPointerType;
+
+    CommandPointerType command = CommandType::New();
+    command->SetCallbackFunction(this, &Self::ObserveSourceFilterProgress);
+
+    source->AddObserver(itk::ProgressEvent(), command);
+    }
+  else
+    {
+    itkWarningMacro(<< "Could not get the source process object. Progress report might be buggy");
+    }
 
   /**
    * Loop over the number of pieces, execute the upstream pipeline on each
    * piece, and copy the results into the output image.
    */
   InputImageRegionType streamRegion;
-  unsigned int         piece;
-  for (piece = 0;
-       piece < numDivisions && !this->GetAbortGenerateData();
-       piece++)
+  for (m_CurrentDivision = 0;
+       m_CurrentDivision < m_NumberOfDivisions && !this->GetAbortGenerateData();
+       m_CurrentDivision++, m_DivisionProgress = 0, this->UpdateFilterProgress())
     {
-    streamRegion = m_RegionSplitter->GetSplit(piece, numDivisions, outputRegion);
+    streamRegion = m_StreamingManager->GetSplit(m_CurrentDivision);
+    otbMsgDevMacro(<< "Processing region : " << streamRegion )
     inputPtr->ReleaseData();
     inputPtr->SetRequestedRegion(streamRegion);
     inputPtr->Update();
-    this->UpdateProgress((float) piece / numDivisions);
     }
+
   /**
    * If we ended due to aborting, push the progress up to 1.0 (since
    * it probably didn't end there)
@@ -308,11 +155,14 @@ StreamingImageVirtualWriter<TInputImage>
       this->GetOutput(idx)->DataHasBeenGenerated();
       }
     }
+
   /**
    * Release any inputs if marked for release
    */
   this->ReleaseInputs();
 }
+
+
 } // end namespace otb
 
 #endif
diff --git a/Testing/Code/BasicFilters/otbMatrixTransposeMatrixImageFilter.cxx b/Testing/Code/BasicFilters/otbMatrixTransposeMatrixImageFilter.cxx
index beebc71c1231462c0535364c697f48eab7e090c4..2d9a433f506d4827fd86b45a3c46b07c64c976b8 100644
--- a/Testing/Code/BasicFilters/otbMatrixTransposeMatrixImageFilter.cxx
+++ b/Testing/Code/BasicFilters/otbMatrixTransposeMatrixImageFilter.cxx
@@ -50,7 +50,7 @@ int otbMatrixTransposeMatrixImageFilter(int argc, char * argv[])
   reader2->SetFileName(infname2);
 
   // filter->SetStreamingMode(otb::SET_NUMBER_OF_STREAM_DIVISIONS);
-  filter->GetStreamer()->SetNumberOfStreamDivisions(200);
+  //filter->GetStreamer()->SetNumberOfStreamDivisions(200);
   filter->SetFirstInput(reader1->GetOutput());
   filter->SetSecondInput(reader2->GetOutput());
   filter->SetUsePadFirstInput(true);
diff --git a/Testing/Code/BasicFilters/otbStreamingInnerProductVectorImageFilter.cxx b/Testing/Code/BasicFilters/otbStreamingInnerProductVectorImageFilter.cxx
index 2987a0f63604e0d6c49050e4f7a50c7fef9babd6..bf4c392613c74d4c7786a4d823b0391e0c797bf2 100644
--- a/Testing/Code/BasicFilters/otbStreamingInnerProductVectorImageFilter.cxx
+++ b/Testing/Code/BasicFilters/otbStreamingInnerProductVectorImageFilter.cxx
@@ -40,7 +40,7 @@ int otbStreamingInnerProductVectorImageFilter(int argc, char* argv[])
   // Instantiation object
   FilterType::Pointer filter = FilterType::New();
 
-  filter->GetStreamer()->SetNumberOfStreamDivisions(10);
+  //filter->GetStreamer()->SetNumberOfStreamDivisions(10);
   filter->SetCenterData(centerdata);
   filter->SetInput(reader->GetOutput());
   filter->Update();
diff --git a/Testing/Code/BasicFilters/otbStreamingMinMaxImageFilter.cxx b/Testing/Code/BasicFilters/otbStreamingMinMaxImageFilter.cxx
index 0a4493c8306a063c2fb731fcc211a1684372a1a9..5f59b2d7f794a45b011c71968eb507af71c54355 100644
--- a/Testing/Code/BasicFilters/otbStreamingMinMaxImageFilter.cxx
+++ b/Testing/Code/BasicFilters/otbStreamingMinMaxImageFilter.cxx
@@ -43,7 +43,7 @@ int otbStreamingMinMaxImageFilter(int argc, char * argv[])
   reader->SetFileName(infname);
 
   //filter->SetStreamingMode(otb::SET_NUMBER_OF_STREAM_DIVISIONS);
-  filter->GetStreamer()->SetNumberOfStreamDivisions(200);
+  //filter->GetStreamer()->SetNumberOfStreamDivisions(200);
   filter->SetInput(reader->GetOutput());
   otb::StandardFilterWatcher watcher(filter, "Min Max Computation");
   filter->Update();
diff --git a/Testing/Code/BasicFilters/otbStreamingMinMaxVectorImageFilter.cxx b/Testing/Code/BasicFilters/otbStreamingMinMaxVectorImageFilter.cxx
index 778df22c3a34f2eddc7ae02ed10113fb4bdd8985..f8f2e265fec84ee19cb7547e1ee2e4f52ca303a4 100644
--- a/Testing/Code/BasicFilters/otbStreamingMinMaxVectorImageFilter.cxx
+++ b/Testing/Code/BasicFilters/otbStreamingMinMaxVectorImageFilter.cxx
@@ -43,7 +43,7 @@ int otbStreamingMinMaxVectorImageFilter(int argc, char * argv[])
   reader->SetFileName(infname);
 
   //filter->SetStreamingMode(otb::SET_NUMBER_OF_STREAM_DIVISIONS);
-  filter->GetStreamer()->SetNumberOfStreamDivisions(200);
+  //filter->GetStreamer()->SetNumberOfStreamDivisions(200);
   filter->SetInput(reader->GetOutput());
   otb::StandardFilterWatcher watcher(filter, "Min Max Computation");
   filter->Update();
diff --git a/Testing/Code/BasicFilters/otbStreamingStatisticsImageFilter.cxx b/Testing/Code/BasicFilters/otbStreamingStatisticsImageFilter.cxx
index adb2fc6c71399e1afc7f9dd2c4d40aa702d292a5..22fae71fb8c86d644fc9d2c273cfb4b75d8fcacb 100644
--- a/Testing/Code/BasicFilters/otbStreamingStatisticsImageFilter.cxx
+++ b/Testing/Code/BasicFilters/otbStreamingStatisticsImageFilter.cxx
@@ -43,7 +43,7 @@ int otbStreamingStatisticsImageFilter(int argc, char * argv[])
   reader->SetFileName(infname);
 
   //filter->GetStreamer()->SetStreamingMode(otb::SET_NUMBER_OF_STREAM_DIVISIONS);
-  filter->GetStreamer()->SetNumberOfStreamDivisions(200);
+  //filter->GetStreamer()->SetNumberOfStreamDivisions(200);
   filter->SetInput(reader->GetOutput());
   filter->Update();
 
diff --git a/Testing/Code/BasicFilters/otbStreamingStatisticsVectorImageFilter.cxx b/Testing/Code/BasicFilters/otbStreamingStatisticsVectorImageFilter.cxx
index e0c312c80be531fb50907cce675f0ec7d0bbd90a..8316823fb3a819eeac2e09edf5de9099875fd64f 100644
--- a/Testing/Code/BasicFilters/otbStreamingStatisticsVectorImageFilter.cxx
+++ b/Testing/Code/BasicFilters/otbStreamingStatisticsVectorImageFilter.cxx
@@ -42,7 +42,7 @@ int otbStreamingStatisticsVectorImageFilter(int argc, char * argv[])
   reader->SetFileName(infname);
 
   //filter->SetStreamingMode(otb::SET_NUMBER_OF_STREAM_DIVISIONS);
-  filter->GetStreamer()->SetNumberOfStreamDivisions(200);
+  //filter->GetStreamer()->SetNumberOfStreamDivisions(200);
   filter->SetInput(reader->GetOutput());
   filter->Update();