diff --git a/Code/Common/otbPipelineMemoryPrintCalculator.h b/Code/Common/otbPipelineMemoryPrintCalculator.h
new file mode 100644
index 0000000000000000000000000000000000000000..02498966e87d9ecd94d5f9d94d28aece4f2ca51b
--- /dev/null
+++ b/Code/Common/otbPipelineMemoryPrintCalculator.h
@@ -0,0 +1,223 @@
+/*=========================================================================
+
+  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 __otbPipelineMemoryPrintCalculator_h
+#define __otbPipelineMemoryPrintCalculator_h
+
+#include "itkProcessObject.h"
+#include "itkDataObject.h"
+#include "otbMath.h"
+#include "itkImage.h"
+#include "itkVectorImage.h"
+#include "itkFixedArray.h"
+
+namespace otb
+{
+/** \class PipelineMemoryPrintCalculator
+ *
+ */
+class ITK_EXPORT PipelineMemoryPrintCalculator :
+  public itk::Object
+{
+public:
+  /** Standard class typedefs */
+  typedef PipelineMemoryPrintCalculator Self;
+  typedef itk::Object            Superclass;
+  typedef itk::SmartPointer<Self>       Pointer;
+  typedef itk::SmartPointer<const Self> ConstPointer;
+
+  /** Useful typedefs */
+  typedef itk::ProcessObject            ProcessObjectType;
+  typedef ProcessObjectType::Pointer    ProcessObjectPointerType;
+  typedef itk::DataObject               DataObjectType;
+  typedef DataObjectType::Pointer       DataObjectPointerType;
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(PipelineMemoryPrintCalculator, itk::Object);
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+  
+  /** Get the total memory print (in Mo) */
+  itkGetMacro(MemoryPrint,double);
+  
+  /** Set/Get the available memory for pipeline execution (in Mo) */
+  itkSetMacro(AvailableMemory,double);
+  itkGetMacro(AvailableMemory,double);
+
+  /** Get the optimal number of stream division */
+  itkGetMacro(OptimalNumberOfStreamDivisions,unsigned long);
+
+  /** Set last pipeline filter */
+  itkSetObjectMacro(DataToWrite,DataObjectType);
+
+  /** Compute pipeline memory print */
+  void Compute()
+  {
+    // Dry run of pipeline synchronisation
+    m_DataToWrite->UpdateOutputInformation();
+    m_DataToWrite->SetRequestedRegionToLargestPossibleRegion();
+    m_DataToWrite->PropagateRequestedRegion();
+
+    // Get the source process object
+    ProcessObjectType * source = m_DataToWrite->GetSource();
+
+    // Check if source exists
+    if(source)
+      {
+      // Call the recursive memory print evaluation
+      m_MemoryPrint = EvaluateMemoryPrint(source);
+      }
+    else
+      {
+      // Get memory print for this data only
+      std::cout<<"DataToWrite has no source."<<std::endl;
+      m_MemoryPrint = EvaluateDataObjectPrint(m_DataToWrite);
+      }
+
+    // TODO: Remove this !
+    m_MemoryPrint*=2;
+
+    // Compute the optimal number of stream division
+    m_OptimalNumberOfStreamDivisions = vcl_ceil(m_MemoryPrint
+                                                /m_AvailableMemory);
+  }
+
+protected:
+  /** Constructor */
+  PipelineMemoryPrintCalculator()
+    : m_MemoryPrint(0),
+    m_AvailableMemory(256),
+    m_OptimalNumberOfStreamDivisions(0),
+    m_DataToWrite(NULL)
+    {}
+
+  /** Destructor */
+  virtual ~PipelineMemoryPrintCalculator() {}
+
+  /** PrintSelf method */
+  void PrintSelf(std::ostream& os, itk::Indent indent) const
+  {
+    // Call superclass implementation
+    Superclass::PrintSelf(os,indent);
+  }
+  
+  /** Internal recursive method to evaluate memory print in bytes */
+  double EvaluateMemoryPrint(ProcessObjectType * process)
+  {
+    // This variable will store the final print
+    double print = 0;
+
+    // Retrieve the array of inputs
+    ProcessObjectType::DataObjectPointerArray inputs = process->GetInputs();
+    // First, recurse on each input source
+    for(unsigned int i =0; i < process->GetNumberOfInputs();++i)
+      {
+      // Retrieve the data object
+      DataObjectType * input = inputs[i];
+      
+      // Retrieve possible source
+      ProcessObjectType * source = input->GetSource();
+
+      // If data object has a source
+      if(source)
+        {
+        print += this->EvaluateMemoryPrint(source);
+        }
+      else
+        {
+        double localPrint = this->EvaluateDataObjectPrint(input);
+        std::cout<<process->GetNameOfClass()<<"::Input"<<i<<" (sourceless) "<<localPrint<<" Mo"<<std::endl;
+        print += localPrint;
+        }
+      }
+    // Retrieve the output array
+    ProcessObjectType::DataObjectPointerArray outputs = process->GetOutputs();
+
+    // Now, evaluate the current object print
+    for(unsigned int i =0; i < process->GetNumberOfOutputs();++i)
+      {
+      double localPrint = this->EvaluateDataObjectPrint(outputs[0]);
+      std::cout<<process->GetNameOfClass()<<"::Output"<<i<<" "<<localPrint<<" Mo"<<std::endl;
+      print += localPrint;
+      }
+
+    // Finally, return the total print
+    return print;
+  }
+
+  /** Internal method to evaluate the print (in Mo) of a single data object */
+  double EvaluateDataObjectPrint(DataObjectType * data)
+  {
+
+#define OTB_IMAGE_SIZE_BLOCK(type) \
+    if(dynamic_cast<itk::Image<type,2> *>(data) != NULL) \
+      { \
+      itk::Image<type,2> * image = dynamic_cast<itk::Image<type,2> *>(data);\
+      std::cout<<"Image of "<< image->GetRequestedRegion().GetNumberOfPixels() <<" pixels of type " # type ": "<<sizeof(type)<<" octets, ("<<image->GetRequestedRegion()<<")"<<std::endl; \
+      return image->GetRequestedRegion().GetNumberOfPixels() * image->GetNumberOfComponentsPerPixel() * sizeof(type) * OctetToMegaOctet; \
+      } \
+    if(dynamic_cast<itk::VectorImage<type,2> * >(data) != NULL)     \
+      { \
+      itk::VectorImage<type,2> * image = dynamic_cast<itk::VectorImage<type,2> *>(data);\
+      std::cout<<"VectorImage of "<< image->GetRequestedRegion().GetNumberOfPixels() <<" pixels of "<<image->GetNumberOfComponentsPerPixel()<<" components of type " # type ": "<<sizeof(type)<<" octets, ("<<image->GetRequestedRegion()<<")"<<std::endl;\
+      return image->GetRequestedRegion().GetNumberOfPixels() * image->GetNumberOfComponentsPerPixel() * sizeof(type) * OctetToMegaOctet; \
+      } \
+  
+
+    OTB_IMAGE_SIZE_BLOCK(unsigned char)
+      OTB_IMAGE_SIZE_BLOCK(char)
+      OTB_IMAGE_SIZE_BLOCK(unsigned short)
+      OTB_IMAGE_SIZE_BLOCK( short)
+      OTB_IMAGE_SIZE_BLOCK(unsigned int)
+      OTB_IMAGE_SIZE_BLOCK( int)
+      OTB_IMAGE_SIZE_BLOCK(unsigned long)
+      OTB_IMAGE_SIZE_BLOCK( long)
+      OTB_IMAGE_SIZE_BLOCK(float)
+      OTB_IMAGE_SIZE_BLOCK( double)
+      OTB_IMAGE_SIZE_BLOCK(std::complex<float>)
+      OTB_IMAGE_SIZE_BLOCK(std::complex<double>)
+      typedef itk::FixedArray<float,2> FloatFixedArray2Type;
+      typedef itk::FixedArray<float,2> DoubleFixedArray2Type;
+      OTB_IMAGE_SIZE_BLOCK(FloatFixedArray2Type)
+      OTB_IMAGE_SIZE_BLOCK(DoubleFixedArray2Type)
+      
+      return 0;
+  }
+
+private:
+  PipelineMemoryPrintCalculator(const Self &); //purposely not implemented
+  void operator =(const Self&);                //purposely not implemented
+
+  /** The total memory print of the pipeline */
+  double       m_MemoryPrint;
+  /** The available memory for pipeline execution */
+  double       m_AvailableMemory;
+  /** The optimal number of stream division */
+  unsigned long m_OptimalNumberOfStreamDivisions;
+
+  /** Pointer to the last pipeline filter */
+  DataObjectPointerType m_DataToWrite;
+
+  static const double OctetToMegaOctet;
+};
+
+const double PipelineMemoryPrintCalculator::OctetToMegaOctet = 1./vcl_pow(2,20);
+
+} // end of namespace otb
+
+#endif
diff --git a/Testing/Code/Common/CMakeLists.txt b/Testing/Code/Common/CMakeLists.txt
index 3154ff08827babd976f2e3c985c231dc9c57c0fb..386040f8ed242b189ed02ce5dc39a9d856419daa 100644
--- a/Testing/Code/Common/CMakeLists.txt
+++ b/Testing/Code/Common/CMakeLists.txt
@@ -946,8 +946,14 @@ ADD_TEST(coTuVariableLengthVectorConverter ${COMMON_TESTS12}
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ otbCommonTests13 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+ADD_TEST(coTuPipelineMemoryPrintCalculatorNew ${COMMON_TESTS13}
+  otbPipelineMemoryPrintCalculatorNew
+    )
 
-
+ADD_TEST(coTvPipelineMemoryPrintCalculator ${COMMON_TESTS13}
+  otbPipelineMemoryPrintCalculatorTest
+  ${INPUTDATA}/qb_RoadExtract.img
+)
 
 
 # -------       Fichiers sources CXX -----------------------------------
@@ -1106,7 +1112,8 @@ otbVariableLengthVectorConverter.cxx
 
 SET(BasicCommon_SRCS13
 otbCommonTests13.cxx
-)
+otbPipelineMemoryPrintCalculatorTest.cxx)
+
 
 OTB_ADD_EXECUTABLE(otbCommonTests1 "${BasicCommon_SRCS1}" "OTBIO;OTBTesting")
 OTB_ADD_EXECUTABLE(otbCommonTests2 "${BasicCommon_SRCS2}" "OTBIO;OTBTesting")
diff --git a/Testing/Code/Common/otbCommonTests13.cxx b/Testing/Code/Common/otbCommonTests13.cxx
index fd1171dd7454d5da1e168c47ffa98b7d99a57892..8da628bf32cbb8990fc3c7c3e8fcf2826ceeb1d7 100644
--- a/Testing/Code/Common/otbCommonTests13.cxx
+++ b/Testing/Code/Common/otbCommonTests13.cxx
@@ -27,4 +27,6 @@
 void RegisterTests()
 {
   //  REGISTER_TEST(otbGISTableSourceNew);
+  REGISTER_TEST(otbPipelineMemoryPrintCalculatorNew);
+  REGISTER_TEST(otbPipelineMemoryPrintCalculatorTest);
 }
diff --git a/Testing/Code/Common/otbPipelineMemoryPrintCalculatorTest.cxx b/Testing/Code/Common/otbPipelineMemoryPrintCalculatorTest.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..e52dd61cbe5efd21430b4623ef7ad7b140ef3cf6
--- /dev/null
+++ b/Testing/Code/Common/otbPipelineMemoryPrintCalculatorTest.cxx
@@ -0,0 +1,56 @@
+/*=========================================================================
+
+  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 "otbPipelineMemoryPrintCalculator.h"
+
+#include "otbVectorImage.h"
+#include "otbImage.h"
+#include "otbImageFileReader.h"
+#include "otbVectorImageToIntensityImageFilter.h"
+
+int otbPipelineMemoryPrintCalculatorNew(int argc, char * argv[])
+{
+  otb::PipelineMemoryPrintCalculator::Pointer calculator = otb::PipelineMemoryPrintCalculator::New();
+
+  return EXIT_SUCCESS;
+}
+
+
+int otbPipelineMemoryPrintCalculatorTest(int argc, char * argv[])
+{
+  typedef otb::VectorImage<double,2>            VectorImageType;
+  typedef otb::Image<double,2>                  ImageType;
+  typedef otb::ImageFileReader<VectorImageType> ReaderType;
+  typedef otb::VectorImageToIntensityImageFilter
+    <VectorImageType,ImageType>                 IntensityImageFilterType;
+
+  ReaderType::Pointer reader = ReaderType::New();
+  reader->SetFileName(argv[1]);
+  
+  IntensityImageFilterType::Pointer intensity = IntensityImageFilterType::New();
+  intensity->SetInput(reader->GetOutput());
+
+  otb::PipelineMemoryPrintCalculator::Pointer calculator = otb::PipelineMemoryPrintCalculator::New();
+  calculator->SetDataToWrite(intensity->GetOutput());
+  calculator->SetAvailableMemory(0.1);
+  calculator->Compute();
+
+  std::cout<<"Pipeline memory print:   "<<calculator->GetMemoryPrint()<<" Mo"<<std::endl;
+  std::cout<<"Optimal stream division: "<<calculator->GetOptimalNumberOfStreamDivisions()<<" tiles"<<std::endl;
+
+  return EXIT_SUCCESS;
+}