diff --git a/Applications/Utils/otbColorMapping.cxx b/Applications/Utils/otbColorMapping.cxx
index d5be7a6fa32b183e133f5be9555eb5b0a2d7ad70..c42b4bdcddff498ccb937b01085f84d0e51826f6 100644
--- a/Applications/Utils/otbColorMapping.cxx
+++ b/Applications/Utils/otbColorMapping.cxx
@@ -20,17 +20,170 @@
 
 
 #include <fstream>
-
+#include <map>
 // Include differents method for color mapping
 #include "otbChangeLabelImageFilter.h"
 #include "itkLabelToRGBImageFilter.h"
 #include "itkScalarToRGBColormapImageFilter.h"
 #include "otbReliefColormapFunctor.h"
 
+#include "otbRAMDrivenStrippedStreamingManager.h"
+#include "otbStreamingShrinkImageFilter.h"
+#include "itkListSample.h"
+#include "otbListSampleToHistogramListGenerator.h"
+
+#include "itkDenseFrequencyContainer.h"
+#include "itkVariableLengthVector.h"
+#include "itkHistogram.h"
+#include "otbObjectList.h"
+#include "otbVisualizationPixelTraits.h"
+
+#include "itkImageRegionConstIterator.h"
+#include "otbVisualizationPixelTraits.h"
+#include "otbObjectList.h"
+
+#include "itkImageRegionConstIterator.h"
+#include "itkBinaryFunctorImageFilter.h"
+
 namespace otb
 {
+
+
 namespace Wrapper
 {
+namespace Functor
+{
+
+
+
+template <class TLabel, class TValue> class RGBFromImageValueFunctor
+{
+public:
+  typedef std::map<TLabel, TValue> MeanValueMapType;
+
+  void SetMaxVal(const TValue maxVal)
+  {
+    m_MaxVal.SetSize(maxVal.Size());
+    for (unsigned int index = 0; index < maxVal.Size(); index++)
+      {
+      m_MaxVal.SetElement(index, maxVal.GetElement(index));
+      }
+  }
+
+  void SetMinVal(const TValue minVal)
+  {
+    m_MinVal.SetSize(minVal.Size());
+    for (unsigned int index = 0; index < minVal.Size(); index++)
+      {
+      m_MinVal.SetElement(index, minVal.GetElement(index));
+      }
+  }
+
+  TValue GetMaxVal()
+  {
+    return m_MaxVal;
+  }
+
+  TValue GetMinVal()
+  {
+    return m_MinVal;
+  }
+
+  void AddNewLabel(TLabel label, TValue value)
+  {
+    TValue newValue;
+    newValue.SetSize(value.Size());
+    for (unsigned int index = 0; index < value.Size(); index++)
+      {
+      if (value[index] < m_MinVal[index])
+        newValue[index] = m_MinVal[index];
+      else
+        if (value[index] > m_MaxVal[index])
+          newValue[index] = m_MaxVal[index];
+        else newValue[index] = value[index];
+      }
+    m_LabelToImageIntensityMap[label] = newValue;
+    m_WeigthingMap[label] = 1;
+  }
+
+  void AddValue(const TLabel& label, const TValue& value)
+  {
+    TValue currentValue = m_LabelToImageIntensityMap[label];
+    m_WeigthingMap[label] = m_WeigthingMap[label] + 1;
+    for (unsigned int index = 0; index < value.Size(); index++)
+      {
+      if (value[index] < m_MinVal[index])
+        currentValue[index] += m_MinVal[index];
+      else
+        if (value[index] > m_MaxVal[index])
+          currentValue[index] += m_MaxVal[index];
+        else currentValue[index] += value[index];
+
+        }
+
+    m_LabelToImageIntensityMap[label] = currentValue;
+  }
+
+  /** operator */
+  TLabel operator ()(const TLabel& label, const TValue& value)
+  {
+    if (m_LabelToImageIntensityMap.count(label)<=0)
+      {
+      AddNewLabel(label, value);
+        }
+      else
+        {
+        AddValue(label, value);
+        }
+
+    return label;
+  }
+
+  MeanValueMapType GetMeanIntensity()
+  {
+    MeanValueMapType MeanMap;
+
+    for(unsigned int i=0;i<m_WeigthingMap.size();i++)
+      {
+      TValue value = m_LabelToImageIntensityMap[i];
+      for (unsigned int index = 0; index < value.Size(); index++)
+           {
+            value[index]=value[index]/static_cast<float>(m_WeigthingMap.at(i));
+           }
+      MeanMap[i]=value;
+      }
+
+
+    return MeanMap;
+  }
+
+  std::map<TLabel, unsigned int> GetLabelArea()
+  {
+    return m_WeigthingMap;
+  }
+
+  /** Constructor */
+  RGBFromImageValueFunctor()
+  {
+  }
+
+  bool operator !=(const RGBFromImageValueFunctor& other) const
+  {
+
+    return ((&m_LabelToImageIntensityMap) != &(other.m_LabelToImageIntensityMap));
+  }
+private:
+
+  std::map<TLabel, unsigned int> m_WeigthingMap; //counter
+  MeanValueMapType m_LabelToImageIntensityMap;
+  TValue m_MinVal;
+  TValue m_MaxVal;
+
+};
+
+}
+
+
 
 class ColorMapping: public Application
 {
@@ -54,6 +207,16 @@ public:
   typedef UInt8RGBImageType           RGBImageType;
   typedef RGBImageType::PixelType     RGBPixelType;
 
+  typedef itk::NumericTraits<FloatVectorImageType::PixelType>::ValueType ScalarType;
+  typedef itk::VariableLengthVector<ScalarType>   SampleType;
+  typedef itk::Statistics::ListSample<SampleType> ListSampleType;
+
+
+  typedef itk::ImageRegionConstIterator<FloatVectorImageType> IteratorType;
+  typedef itk::ImageRegionConstIterator<UInt16ImageType> LabelIteratorType;
+
+
+
   // Manual label LUT
   typedef otb::ChangeLabelImageFilter
   <LabelImageType, VectorImageType>    ChangeLabelFilterType;
@@ -68,6 +231,30 @@ public:
   typedef otb::Functor::ReliefColormapFunctor
   <PixelType, RGBPixelType>           ReliefColorMapFunctorType;
 
+  typedef RAMDrivenStrippedStreamingManager<FloatVectorImageType> RAMDrivenStrippedStreamingManagerType;
+
+  typedef otb::StreamingShrinkImageFilter<FloatVectorImageType,
+       FloatVectorImageType>              ImageSamplingFilterType;
+
+  typedef itk::Statistics::DenseFrequencyContainer DFContainerType;
+
+  typedef itk::NumericTraits<PixelType>::RealType RealScalarType;
+  typedef itk::VariableLengthVector<RealScalarType>         InternalPixelType;
+
+  typedef otb::ListSampleToHistogramListGenerator
+  <ListSampleType, ScalarType, DFContainerType>           HistogramFilterType;
+  typedef itk::Statistics::Histogram<
+       RealScalarType, 1, DFContainerType>         HistogramType;
+  typedef ObjectList<HistogramType>           HistogramListType;
+
+  typedef  HistogramType::Pointer     HistogramPointerType;
+
+  typedef otb::ImageMetadataInterfaceBase ImageMetadataInterfaceType;
+
+  typedef Functor::RGBFromImageValueFunctor<LabelType,FloatVectorImageType::PixelType> RGBFromImageValueFunctorType;
+  typedef itk::BinaryFunctorImageFilter<LabelImageType,FloatVectorImageType,LabelImageType,
+      RGBFromImageValueFunctorType>     RGBFromImageValueFilterType;
+
 private:
   void DoInit()
   {
@@ -158,6 +345,25 @@ private:
     SetMinimumParameterIntValue("method.segmentation.background", 0);
     SetMaximumParameterIntValue("method.segmentation.background", 255);
 
+    // Support image LUT
+    AddChoice("method.image","Color mapping with look-up table calculated on support image");
+    AddParameter(ParameterType_InputImage, "method.image.in", "Support Image");
+    SetParameterDescription("method.image.in", "Support image filename. LUT is calculated using the mean af pixel value on the area. First of all image is normalized with extrema rejection");
+    AddParameter(ParameterType_Int, "method.image.low", "lower quantile");
+    SetParameterDescription("method.image.low","lower quantile for image normalisation");
+    MandatoryOff("method.image.low");
+    SetParameterInt("method.image.low", 2);
+    SetMinimumParameterIntValue("method.image.low", 0);
+    SetMaximumParameterIntValue("method.image.low", 100);
+    AddParameter(ParameterType_Int, "method.image.up", "upper quantile");
+    SetParameterDescription("method.image.up","upper quantile for image normalisation");
+    SetParameterInt("method.segmentation.background", 0);
+    MandatoryOff("method.image.up");
+    SetParameterInt("method.image.up", 2);
+    SetMinimumParameterIntValue("method.image.up", 0);
+    SetMaximumParameterIntValue("method.image.up", 100);
+
+
     // Doc example parameter settings
     SetDocExampleParameterValue("in", "ROI_QB_MUL_1_SVN_CLASS_MULTI.png");
     SetDocExampleParameterValue("method", "custom");
@@ -167,56 +373,231 @@ private:
 
   void DoUpdateParameters()
   {
-    // Nothing to do here : all parameters are independent
+    // Nothing to do here : FloatVectorImageTypeall parameters are independent
   }
 
   void DoExecute()
   {
-    if(GetParameterInt("method")==0)
+    if (GetParameterInt("method") == 0)
       {
       m_CustomMapper = ChangeLabelFilterType::New();
       m_CustomMapper->SetInput(GetParameterUInt16Image("in"));
       m_CustomMapper->SetNumberOfComponentsPerPixel(3);
-      
+
       ReadLutFromFile();
-      
+
       SetParameterOutputImage("out", m_CustomMapper->GetOutput());
       }
-    else if(GetParameterInt("method")==1)
-      {
-      m_ContinuousColorMapper = ColorMapFilterType::New();
+    else
+      if (GetParameterInt("method") == 1)
+        {
+        m_ContinuousColorMapper = ColorMapFilterType::New();
 
-      m_ContinuousColorMapper->SetInput(GetParameterFloatImage("in"));
+        m_ContinuousColorMapper->SetInput(GetParameterFloatImage("in"));
 
-      // Disable automatic scaling
-      m_ContinuousColorMapper->UseInputImageExtremaForScalingOff();
+        // Disable automatic scaling
+        m_ContinuousColorMapper->UseInputImageExtremaForScalingOff();
 
-      // Set the lut
-      std::string lut = GetParameterString("method.continuous.lut");
+        // Set the lut
+        std::string lut = GetParameterString("method.continuous.lut");
 
-      otbAppLogINFO("LUT: "<<lut<<std::endl);
-      if(lut == "Relief")
-        {
-        ReliefColorMapFunctorType::Pointer reliefFunctor = ReliefColorMapFunctorType::New();
-        m_ContinuousColorMapper->SetColormap(reliefFunctor);
+        otbAppLogINFO("LUT: "<<lut<<std::endl);
+        if (lut == "Relief")
+          {
+          ReliefColorMapFunctorType::Pointer reliefFunctor = ReliefColorMapFunctorType::New();
+          m_ContinuousColorMapper->SetColormap(reliefFunctor);
+          }
+        else
+          {
+          m_ContinuousColorMapper->SetColormap((ColorMapFilterType::ColormapEnumType) m_LutMap[lut]);
+          }
+
+        m_ContinuousColorMapper->GetColormap()->SetMinimumInputValue(GetParameterFloat("method.continuous.min"));
+        m_ContinuousColorMapper->GetColormap()->SetMaximumInputValue(GetParameterFloat("method.continuous.max"));
+
+        SetParameterOutputImage("out", m_ContinuousColorMapper->GetOutput());
         }
       else
-        {
-        m_ContinuousColorMapper->SetColormap((ColorMapFilterType::ColormapEnumType)m_LutMap[lut]);
-        }
+        if (GetParameterInt("method") == 2)
+          {
+          m_SegmentationColorMapper = LabelToRGBFilterType::New();
+          m_SegmentationColorMapper->SetInput(GetParameterUInt16Image("in"));
+          m_SegmentationColorMapper->SetBackgroundValue(GetParameterInt("method.segmentation.background"));
+          SetParameterOutputImage("out", m_SegmentationColorMapper->GetOutput());
+          }
+        else
+          if (GetParameterInt("method") == 3)
+            {
+            otbAppLogINFO(" look-up table calculated on support image ");
 
-      m_ContinuousColorMapper->GetColormap()->SetMinimumInputValue(GetParameterFloat("method.continuous.min"));
-      m_ContinuousColorMapper->GetColormap()->SetMaximumInputValue(GetParameterFloat("method.continuous.max"));
+            // image normalisation of the sampling //
+            FloatVectorImageType::Pointer supportImage = this->GetParameterImage("method.image.in");
+            supportImage->UpdateOutputInformation();
+
+            //normalisation
+            //first of all resampling
+
+            //calculate split number
+            RAMDrivenStrippedStreamingManagerType::Pointer
+                streamingManager = RAMDrivenStrippedStreamingManagerType::New();
+            int availableRAM = GetParameterInt("ram");
+            streamingManager->SetAvailableRAMInMB(availableRAM);
+            float bias = 2.0; // empiric value;
+            streamingManager->SetBias(bias);
+            FloatVectorImageType::RegionType largestRegion = supportImage->GetLargestPossibleRegion();
+            FloatVectorImageType::SizeType largestRegionSize = largestRegion.GetSize();
+            streamingManager->PrepareStreaming(supportImage, largestRegion);
+
+            unsigned long nbDivisions = streamingManager->GetNumberOfSplits();
+            unsigned long largestPixNb = largestRegionSize[0] * largestRegionSize[1];
+
+            unsigned long maxPixNb = largestPixNb / nbDivisions;
+
+            ImageSamplingFilterType::Pointer imageSampler = ImageSamplingFilterType::New();
+            imageSampler->SetInput(supportImage);
+
+            double theoricNBSamplesForKMeans = maxPixNb;
+
+            const double upperThresholdNBSamplesForKMeans = 1000 * 1000;
+            const double actualNBSamplesForKMeans = std::min(theoricNBSamplesForKMeans,
+                                                             upperThresholdNBSamplesForKMeans);
+
+            const double shrinkFactor = vcl_floor(
+                                                  vcl_sqrt(
+                                                           supportImage->GetLargestPossibleRegion().GetNumberOfPixels()
+                                                               / actualNBSamplesForKMeans));
+            imageSampler->SetShrinkFactor(shrinkFactor);
+            imageSampler->Update();
+
+            otbAppLogINFO(<<imageSampler->GetOutput()->GetLargestPossibleRegion().GetNumberOfPixels()<<""
+                " sample will be used to estimate extrema value for outliers rejection."<<std::endl);
+
+            // use histogram to compute quantile value
+
+
+            FloatVectorImageType::Pointer histogramSource;
+            histogramSource = imageSampler->GetOutput();
+            histogramSource->SetRequestedRegion(imageSampler->GetOutput()->GetLargestPossibleRegion());
+
+            // Iterate on the image
+            itk::ImageRegionConstIterator<FloatVectorImageType> it(histogramSource,
+                                                                   histogramSource->GetBufferedRegion());
+
+            // declare a list to store the samples
+            ListSampleType::Pointer listSample = ListSampleType::New();
+            listSample->Clear();
+
+            unsigned int sampleSize = VisualizationPixelTraits::PixelSize(it.Get());
+            listSample->SetMeasurementVectorSize(sampleSize);
+
+            // Fill the samples list
+            it.GoToBegin();
+            while (!it.IsAtEnd())
+              {
+              SampleType sample(sampleSize);
+              VisualizationPixelTraits::Convert(it.Get(), sample);
+              listSample->PushBack(sample);
+              ++it;
+              }
+
+            // assign listSample
+
+            HistogramFilterType::Pointer histogramFilter = HistogramFilterType::New();
+            //histogramFilter->SetListSample(pixelRepresentationListSample);
+            histogramFilter->SetListSample(listSample);
+
+            histogramFilter->SetNumberOfBins(256);
+            histogramFilter->NoDataFlagOn();
+
+            // Generate
+            histogramFilter->Update();
+            HistogramListType::Pointer histogramList = histogramFilter->GetOutput();//
+            // HistogramPointerType histoBand=histogramList->GetNelements(0);
+            //  std::cout<<histoBand->GetFrequency(0,0)<<std::endl;
+
+
+            ImageMetadataInterfaceType::Pointer
+                metadataInterface = ImageMetadataInterfaceFactory::CreateIMI(supportImage->GetMetaDataDictionary());
+
+            std::vector<unsigned int> RGBIndex;
+
+            if (supportImage->GetNumberOfComponentsPerPixel() < 3)
+              {
+              RGBIndex.push_back(0);
+              RGBIndex.push_back(0);
+              RGBIndex.push_back(0);
+              }
+            else RGBIndex = metadataInterface->GetDefaultDisplay();
+            otbAppLogINFO(" RGB index are "<<RGBIndex[0]<<" "<<RGBIndex[1]<<" "<<RGBIndex[2]<<std::endl);
 
-      SetParameterOutputImage("out", m_ContinuousColorMapper->GetOutput());
-      }
-    else if(GetParameterInt("method")==2)
-      {
-      m_SegmentationColorMapper = LabelToRGBFilterType::New();
-      m_SegmentationColorMapper->SetInput(GetParameterUInt16Image("in"));
-      m_SegmentationColorMapper->SetBackgroundValue(GetParameterInt("method.segmentation.background"));
-      SetParameterOutputImage("out", m_SegmentationColorMapper->GetOutput());
-      }
+            FloatVectorImageType::PixelType minVal;
+            FloatVectorImageType::PixelType maxVal;
+            minVal.SetSize(supportImage->GetNumberOfComponentsPerPixel());
+            maxVal.SetSize(supportImage->GetNumberOfComponentsPerPixel());
+
+            for (unsigned int index = 0; index < supportImage->GetNumberOfComponentsPerPixel(); index++)
+              {
+              minVal.SetElement(index,static_cast<FloatVectorImageType::PixelType::ValueType> (histogramList->GetNthElement(index)->Quantile(0,static_cast<float> (this->GetParameterInt("method.image.low"))/ 100.0)));
+              maxVal.SetElement(index,static_cast<FloatVectorImageType::PixelType::ValueType> (histogramList->GetNthElement(index)->Quantile(0,(100.0- static_cast<float> (this->GetParameterInt("method.image.up")))/ 100.0)));
+              }
+
+            // create functor
+            RGBFromImageValueFunctorType functor;
+            functor.SetMinVal(minVal);
+            functor.SetMaxVal(maxVal);
+
+            m_RGBFromImageValueFilter = RGBFromImageValueFilterType::New();
+            m_RGBFromImageValueFilter->SetInput1(GetParameterUInt16Image("in"));
+            m_RGBFromImageValueFilter->SetInput2(this->GetParameterImage("method.image.in"));
+            m_RGBFromImageValueFilter->SetFunctor(functor);
+            m_RGBFromImageValueFilter->SetNumberOfThreads(1);
+
+            m_RGBFromImageValueFilter->Update();
+
+            std::map<LabelType, FloatVectorImageType::PixelType>
+                labelToMeanIntensityMap = m_RGBFromImageValueFilter->GetFunctor().GetMeanIntensity();
+
+            m_RBGFromImageMapper = ChangeLabelFilterType::New();
+            m_RBGFromImageMapper->SetInput(m_RGBFromImageValueFilter->GetOutput());
+            m_RBGFromImageMapper->SetNumberOfComponentsPerPixel(3);
+
+            std::map<LabelType, FloatVectorImageType::PixelType>::const_iterator
+                mapIt = labelToMeanIntensityMap.begin();
+            FloatVectorImageType::PixelType meanValue = labelToMeanIntensityMap.at(0);
+
+            otbAppLogINFO("The map contains :"<<labelToMeanIntensityMap.size()<<" labels."<<std::endl);
+            VectorPixelType color(3);
+            while (mapIt != labelToMeanIntensityMap.end())
+              {
+
+              LabelType clabel = mapIt->first;
+              if (clabel == 0)
+                {
+                color.Fill(0.0);
+                }
+              else
+                {
+
+                meanValue = mapIt->second;
+                for (int RGB = 0; RGB < 3; RGB++)
+                  {
+                  unsigned int dispIndex = RGBIndex[RGB];
+                  color[RGB] = ((meanValue.GetElement(dispIndex) - minVal.GetElement(dispIndex)) / (
+                      maxVal.GetElement(dispIndex) - minVal.GetElement(dispIndex))) * 255.0;
+                  }
+                }
+              otbAppLogINFO("Adding color mapping " << clabel << " -> [" << (int) color[0] << " " << (int) color[1] << " "<< (int) color[2] << " ]" << std::endl);
+              m_RBGFromImageMapper->SetChange(clabel, color);
+
+              ++mapIt;
+              }
+
+
+
+            SetParameterOutputImage("out", m_RBGFromImageMapper->GetOutput());
+
+
+            }
   }
 
   void ReadLutFromFile()
@@ -264,10 +645,15 @@ private:
     ifs.close();
   }
 
+
   ChangeLabelFilterType::Pointer m_CustomMapper;
   ColorMapFilterType::Pointer    m_ContinuousColorMapper;
   LabelToRGBFilterType::Pointer  m_SegmentationColorMapper;
   std::map<std::string, unsigned int> m_LutMap;
+  ChangeLabelFilterType::Pointer m_RBGFromImageMapper;
+  RGBFromImageValueFilterType::Pointer    m_RGBFromImageValueFilter;
+
+
 };
 }
 }