diff --git a/Modules/Applications/AppFiltering/app/otbContrastEnhancement.cxx b/Modules/Applications/AppFiltering/app/otbContrastEnhancement.cxx
index c9bda376d9e2454fc714710c1d6ceff58cf747d8..dbcc3f38d6d254e4819e8b7528007f7fed4c7e82 100644
--- a/Modules/Applications/AppFiltering/app/otbContrastEnhancement.cxx
+++ b/Modules/Applications/AppFiltering/app/otbContrastEnhancement.cxx
@@ -530,7 +530,6 @@ private:
         }
       m_GainFilter[channel]->SetMin( min[channel] );
       m_GainFilter[channel]->SetMax( max[channel] );
-      m_GainFilter[channel]->SetThumbSize(m_ThumbSize);
       m_GainFilter[channel]->SetInputLut( 
         m_StreamingFilter[channel]->GetOutput() );
       m_BufferFilter[channel] -> SetInput ( 
@@ -599,7 +598,6 @@ private:
         }
       m_GainFilter[channel]->SetMin( min );
       m_GainFilter[channel]->SetMax( max );
-      m_GainFilter[channel]->SetThumbSize( m_ThumbSize );
       m_GainFilter[channel]->SetInputLut( 
         m_StreamingFilter[0]->GetOutput() );
       m_BufferFilter[channel]->SetInput(
diff --git a/Modules/Filtering/Contrast/include/otbApplyGainFilter.h b/Modules/Filtering/Contrast/include/otbApplyGainFilter.h
index 35aaa42ba998ac7cc23f155767bb5f01a0845b68..c735725382971d33b31273edcffcda0316184db0 100644
--- a/Modules/Filtering/Contrast/include/otbApplyGainFilter.h
+++ b/Modules/Filtering/Contrast/include/otbApplyGainFilter.h
@@ -72,6 +72,15 @@ public :
   itkGetMacro(NoDataFlag, bool)
   itkSetMacro(NoDataFlag, bool)
 
+  /** Get/Set macro to get/set the ThumbSizeFromSpacing flag value */
+  itkBooleanMacro(ThumbSizeFromSpacing)
+  itkGetMacro(ThumbSizeFromSpacing, bool)
+  itkSetMacro(ThumbSizeFromSpacing, bool)
+
+  /** Get/Set macro to get/set the thumbnail's size */
+  itkSetMacro(ThumbSize, typename InputImageType::SizeType)
+  itkGetMacro(ThumbSize, typename InputImageType::SizeType)
+
   /** Get/Set macro to get/set the minimum value */
   itkSetMacro(Min, InputPixelType)
   itkGetMacro(Min, InputPixelType)
@@ -80,10 +89,6 @@ public :
   itkSetMacro(Max, InputPixelType)
   itkGetMacro(Max, InputPixelType)
 
-  /** Get/Set macro to get/set the thumbnail's size */
-  itkSetMacro(ThumbSize, typename InputImageType::SizeType)
-  itkGetMacro(ThumbSize, typename InputImageType::SizeType)
-
   /** Set the input look up table*/
   void SetInputLut( const LutType * lut) ;
 
@@ -107,7 +112,7 @@ protected :
 
   void ThreadedGenerateData(const OutputImageRegionType & outputRegionForThread,
                             itk::ThreadIdType threadId) override;
-
+  void VerifyInputInformation() override {} ;
 
 private :
   ApplyGainFilter(const Self &) = delete ;
@@ -122,6 +127,7 @@ private :
   InputPixelType m_Min;
   InputPixelType m_Max;
   bool m_NoDataFlag;
+  bool m_ThumbSizeFromSpacing;
   double m_Step;
   typename LutType::SizeType m_LutSize;
   typename InputImageType::SizeType m_ThumbSize;
diff --git a/Modules/Filtering/Contrast/include/otbApplyGainFilter.txx b/Modules/Filtering/Contrast/include/otbApplyGainFilter.txx
index 2c70ed13afcbb5923ee5bad6e2a5d3d7ac3a58e0..3d9372892eb34c514b5bef3f1347eb05ff86fe93 100644
--- a/Modules/Filtering/Contrast/include/otbApplyGainFilter.txx
+++ b/Modules/Filtering/Contrast/include/otbApplyGainFilter.txx
@@ -24,7 +24,7 @@
 #include "otbApplyGainFilter.h"
 #include "itkImageRegionIterator.h"
 #include "itkImageRegionConstIteratorWithIndex.h"
-
+#include "itkContinuousIndex.h"
 
 #include <limits>
 
@@ -38,7 +38,8 @@ ApplyGainFilter < TInputImage , TLut , TOutputImage >
   m_Min = std::numeric_limits< InputPixelType >::quiet_NaN();
   m_Max = std::numeric_limits< InputPixelType >::quiet_NaN();
   m_NoData = std::numeric_limits< InputPixelType >::quiet_NaN();
-
+  m_NoDataFlag = false;
+  m_ThumbSizeFromSpacing = true;
   m_Step = -1;
 }
 
@@ -93,7 +94,14 @@ void ApplyGainFilter < TInputImage , TLut , TOutputImage >
 ::BeforeThreadedGenerateData()
 {
   typename LutType::ConstPointer lut ( GetInputLut() );
-
+  typename InputImageType::ConstPointer input ( GetInputImage() );
+  if ( m_ThumbSizeFromSpacing )
+    {
+    m_ThumbSize[0] = std::round( lut->GetSpacing()[0] 
+          / input->GetSpacing()[0] );
+    m_ThumbSize[1] = std::round( lut->GetSpacing()[1] 
+          / input->GetSpacing()[1] );
+    }
   m_Step = static_cast<double>( m_Max - m_Min ) \
                 / static_cast<double>( lut->GetVectorLength() - 1 );
 }
@@ -149,112 +157,146 @@ double ApplyGainFilter < TInputImage , TLut , TOutputImage >
                  unsigned int pixelLutValue ,
                  typename InputImageType::IndexType index)
 {
-  typename LutType::IndexType lutIndex;
-  lutIndex[0] = index[0]/m_ThumbSize[0];
-  lutIndex[1] = index[1]/m_ThumbSize[1];
-  float x ( static_cast< float >(index[0]%m_ThumbSize[0])
-            / static_cast< float >(m_ThumbSize[0]) );
-  float y ( static_cast< float >(index[1]%m_ThumbSize[1])
-            / static_cast< float >(m_ThumbSize[1]) );
-  float disty ( std::abs( y - 0.5f ) ) , distx ( std::abs( x - 0.5f ) );
-  float w(0.f) , gain(0.f);
-  if ( gridLut->GetPixel(lutIndex)[pixelLutValue] != -1 )
-    { 
-    w = ( 1 - distx )*( 1 - disty );
-    gain = gridLut->GetPixel(lutIndex)[pixelLutValue] *
-              ( 1 - distx ) * ( 1 - disty ) ;
-    }
-  typename LutType::OffsetType rightOffSet , upOffSet , leftOffSet , downOffSet;
+  // typename LutType::IndexType lutIndex;
+  // lutIndex[0] = index[0]/m_ThumbSize[0];
+  // lutIndex[1] = index[1]/m_ThumbSize[1];
+  // float x ( static_cast< float >(index[0]%m_ThumbSize[0])
+  //           / static_cast< float >(m_ThumbSize[0]) );
+  // float y ( static_cast< float >(index[1]%m_ThumbSize[1])
+  //           / static_cast< float >(m_ThumbSize[1]) );
+  // float disty ( std::abs( y - 0.5f ) ) , distx ( std::abs( x - 0.5f ) );
+  // float w(0.f) , gain(0.f);
+  // if ( gridLut->GetPixel(lutIndex)[pixelLutValue] != -1 )
+  //   { 
+  //   w = ( 1 - distx )*( 1 - disty );
+  //   gain = gridLut->GetPixel(lutIndex)[pixelLutValue] *
+  //             ( 1 - distx ) * ( 1 - disty ) ;
+  //   }
+  // typename LutType::OffsetType rightOffSet , upOffSet , leftOffSet , downOffSet;
 
-  rightOffSet.Fill(0);
-  rightOffSet[0] = 1 ;
-  bool right = ( x  >=  0.5f ) && 
-    ( ( rightOffSet[0] + lutIndex[0] ) < static_cast<int>( m_LutSize[0] ) );
+  // rightOffSet.Fill(0);
+  // rightOffSet[0] = 1 ;
+  // bool right = ( x  >=  0.5f ) && 
+  //   ( ( rightOffSet[0] + lutIndex[0] ) < static_cast<int>( m_LutSize[0] ) );
 
-  leftOffSet.Fill(0);
-  leftOffSet[0] = -1 ;
-  bool left = ( x <= 0.5f ) && 
-    ( ( leftOffSet[0] + lutIndex[0] ) >= 0 );
+  // leftOffSet.Fill(0);
+  // leftOffSet[0] = -1 ;
+  // bool left = ( x <= 0.5f ) && 
+  //   ( ( leftOffSet[0] + lutIndex[0] ) >= 0 );
 
-  upOffSet.Fill(0);
-  upOffSet[1] = -1 ;
-  bool up = ( y <= 0.5f ) && 
-    ( ( upOffSet[1] + lutIndex[1] ) >= 0 ) ;
+  // upOffSet.Fill(0);
+  // upOffSet[1] = -1 ;
+  // bool up = ( y <= 0.5f ) && 
+  //   ( ( upOffSet[1] + lutIndex[1] ) >= 0 ) ;
 
-  downOffSet.Fill(0);
-  downOffSet[1] = 1 ;
-  bool down = ( y >= 0.5f ) && 
-    ( downOffSet[1] + lutIndex[1] ) < static_cast<int>( m_LutSize[1] ) ;
-  if ( right 
-       && gridLut->GetPixel(lutIndex + rightOffSet)[pixelLutValue] != -1 )
-    {
-    gain += gridLut->GetPixel(lutIndex + rightOffSet)[pixelLutValue]
-            * (1 - disty ) * distx;
-    w += (1 - disty ) * distx;
-    }
-  if ( left
-       && gridLut->GetPixel(lutIndex + leftOffSet)[pixelLutValue] != -1 )
-    {
-    gain += gridLut->GetPixel(lutIndex + leftOffSet)[pixelLutValue]
-            * (1 - disty ) * distx;
-    w += (1 - disty ) * distx;
-    }
-  if ( up
-       && gridLut->GetPixel(lutIndex + upOffSet)[pixelLutValue] != -1 )
-    {
-    gain += gridLut->GetPixel(lutIndex + upOffSet)[pixelLutValue]
-            * disty * (1 - distx );
-    w += disty * (1 - distx );
-    }
-  if ( down
-       && gridLut->GetPixel(lutIndex + downOffSet)[pixelLutValue] != -1 )
-    {
-    gain += gridLut->GetPixel(lutIndex + downOffSet)[pixelLutValue]
-            * disty * (1 - distx );
-    w += disty * (1 - distx );
-    }
-  if ( up && left
-       && gridLut->GetPixel(lutIndex + upOffSet + leftOffSet)
-          [pixelLutValue] != -1 )
-    {
-    gain += gridLut->
-            GetPixel(lutIndex + upOffSet + leftOffSet)[pixelLutValue]
-              * disty * distx;
-    w += disty * distx;
-    }
-  if ( down && left
-       && gridLut->GetPixel(lutIndex + downOffSet + leftOffSet)
-          [pixelLutValue] != -1 )
-    {
-    gain += gridLut->
-            GetPixel(lutIndex + downOffSet + leftOffSet)[pixelLutValue]
-              * disty * distx;
-    w += disty * distx;
-    }
-  if ( up && right
-       && gridLut->GetPixel(lutIndex + upOffSet + rightOffSet)
-          [pixelLutValue] != -1 )
-    {
-    gain += gridLut->
-            GetPixel(lutIndex + upOffSet + rightOffSet)[pixelLutValue]
-              * disty * distx;
-    w += disty * distx ;
-    }
-  if ( down && right
-       && gridLut->GetPixel(lutIndex + downOffSet + rightOffSet)
-          [pixelLutValue] != -1 )
+  // downOffSet.Fill(0);
+  // downOffSet[1] = 1 ;
+  // bool down = ( y >= 0.5f ) && 
+  //   ( downOffSet[1] + lutIndex[1] ) < static_cast<int>( m_LutSize[1] ) ;
+  // if ( right 
+  //      && gridLut->GetPixel(lutIndex + rightOffSet)[pixelLutValue] != -1 )
+  //   {
+  //   gain += gridLut->GetPixel(lutIndex + rightOffSet)[pixelLutValue]
+  //           * (1 - disty ) * distx;
+  //   w += (1 - disty ) * distx;
+  //   }
+  // if ( left
+  //      && gridLut->GetPixel(lutIndex + leftOffSet)[pixelLutValue] != -1 )
+  //   {
+  //   gain += gridLut->GetPixel(lutIndex + leftOffSet)[pixelLutValue]
+  //           * (1 - disty ) * distx;
+  //   w += (1 - disty ) * distx;
+  //   }
+  // if ( up
+  //      && gridLut->GetPixel(lutIndex + upOffSet)[pixelLutValue] != -1 )
+  //   {
+  //   gain += gridLut->GetPixel(lutIndex + upOffSet)[pixelLutValue]
+  //           * disty * (1 - distx );
+  //   w += disty * (1 - distx );
+  //   }
+  // if ( down
+  //      && gridLut->GetPixel(lutIndex + downOffSet)[pixelLutValue] != -1 )
+  //   {
+  //   gain += gridLut->GetPixel(lutIndex + downOffSet)[pixelLutValue]
+  //           * disty * (1 - distx );
+  //   w += disty * (1 - distx );
+  //   }
+  // if ( up && left
+  //      && gridLut->GetPixel(lutIndex + upOffSet + leftOffSet)
+  //         [pixelLutValue] != -1 )
+  //   {
+  //   gain += gridLut->
+  //           GetPixel(lutIndex + upOffSet + leftOffSet)[pixelLutValue]
+  //             * disty * distx;
+  //   w += disty * distx;
+  //   }
+  // if ( down && left
+  //      && gridLut->GetPixel(lutIndex + downOffSet + leftOffSet)
+  //         [pixelLutValue] != -1 )
+  //   {
+  //   gain += gridLut->
+  //           GetPixel(lutIndex + downOffSet + leftOffSet)[pixelLutValue]
+  //             * disty * distx;
+  //   w += disty * distx;
+  //   }
+  // if ( up && right
+  //      && gridLut->GetPixel(lutIndex + upOffSet + rightOffSet)
+  //         [pixelLutValue] != -1 )
+  //   {
+  //   gain += gridLut->
+  //           GetPixel(lutIndex + upOffSet + rightOffSet)[pixelLutValue]
+  //             * disty * distx;
+  //   w += disty * distx ;
+  //   }
+  // if ( down && right
+  //      && gridLut->GetPixel(lutIndex + downOffSet + rightOffSet)
+  //         [pixelLutValue] != -1 )
+  //   {
+  //   gain += gridLut->
+  //           GetPixel(lutIndex + downOffSet + rightOffSet)[pixelLutValue]
+  //             * disty * distx;
+  //   w += disty * distx;
+  //   }
+
+
+  typename InputImageType::PointType pixelPoint;
+  typename itk::ContinuousIndex< double , 2 > pixelIndex;
+  typename InputImageType::ConstPointer input ( GetInputImage() );
+  typename LutType::ConstPointer lut ( GetInputLut() );
+  input->TransformIndexToPhysicalPoint( index , pixelPoint );
+  lut->TransformPhysicalPointToContinuousIndex( pixelPoint , pixelIndex );
+  std::vector< typename LutType::IndexType > neighbors(4);
+  neighbors[0][0] =std::floor(pixelIndex[0]) ; 
+  neighbors[0][1] =std::floor(pixelIndex[1]) ;
+  neighbors[1][0] = neighbors[0][0] + 1 ;
+  neighbors[1][1] = neighbors[0][1] ;
+  neighbors[2][0] = neighbors[0][0] ;
+  neighbors[2][1] = neighbors[0][1] + 1 ;
+  neighbors[3][0] = neighbors[0][0] + 1 ;
+  neighbors[3][1] = neighbors[0][1] + 1 ;
+  float gainp(0.f) , wp(0.f) , wtmp(0.f);
+  int sup0 ( gridLut->GetLargestPossibleRegion().GetSize()[0]  ) ,
+    sup1 ( gridLut->GetLargestPossibleRegion().GetSize()[1] );
+  for ( auto i : neighbors )
     {
-    gain += gridLut->
-            GetPixel(lutIndex + downOffSet + rightOffSet)[pixelLutValue]
-              * disty * distx;
-    w += disty * distx;
+    if ( i[0] < 0 || i[1] < 0  || i[0] >= sup0 || i[1] >= sup1 )
+      continue;
+    if ( gridLut->GetPixel(i)[pixelLutValue] == -1 )
+      continue;
+    wtmp = ( 1 - std::abs( pixelIndex[0] - i[0] ) ) 
+          * ( 1 - std::abs( pixelIndex[1] - i[1] ) );
+    if (wtmp>1 || wtmp <0)
+      std::cout<<"Prb : wtmp = "<<wtmp<<std::endl;
+    gainp += gridLut->GetPixel(i)[pixelLutValue] * wtmp;
+    wp += wtmp; 
     }
-  if (w == 0 )
+  if ( wp == 0 )
     {
-    gain = 1;
-    w = 1;
+    wp = 1;
+    gainp = 1;
     }
-  return gain/w;
+
+  return gainp/wp;
 }
 
 /**
@@ -265,13 +307,15 @@ void ApplyGainFilter < TInputImage , TLut , TOutputImage >
 ::PrintSelf(std::ostream& os, itk::Indent indent) const
 {
   Superclass::PrintSelf(os, indent);
-  os << indent << "Is no data activated: " << m_NoDataFlag << std::endl;
-  os << indent << "No Data: " << m_NoData << std::endl;
-  os << indent << "Minimum: " << m_Min << std::endl;
-  os << indent << "Maximum: " << m_Max << std::endl;
-  os << indent << "Step: " << m_Step << std::endl;
-  os << indent << "Look up table size: " << m_LutSize << std::endl;
-  os << indent << "Thumbnail size: " << m_ThumbSize << std::endl;
+  os << indent << "Is no data activated : " << m_NoDataFlag << std::endl;
+  os << indent << "No Data : " << m_NoData << std::endl;
+  os << indent << "Minimum : " << m_Min << std::endl;
+  os << indent << "Maximum : " << m_Max << std::endl;
+  os << indent << "Step : " << m_Step << std::endl;
+  os << indent << "Look up table size : " << m_LutSize << std::endl;
+  os << indent << "Is ThumbSize from sapcing is activated : " 
+                  << m_NoDataFlag << std::endl;
+  os << indent << "Thumbnail size : " << m_ThumbSize << std::endl;
 }
 
   
diff --git a/Modules/Filtering/Contrast/include/otbComputeHistoFilter.txx b/Modules/Filtering/Contrast/include/otbComputeHistoFilter.txx
index b78d4354255fbbdb36e4ef09c0828163c964d192..7fb61c1598d4581fda051be85949b39eaf6b8f5f 100644
--- a/Modules/Filtering/Contrast/include/otbComputeHistoFilter.txx
+++ b/Modules/Filtering/Contrast/include/otbComputeHistoFilter.txx
@@ -151,6 +151,19 @@ void ComputeHistoFilter < TInputImage , TOutputImage >
   region.SetIndex(start);
   output->SetNumberOfComponentsPerPixel(m_NbBin);
   output->SetLargestPossibleRegion(region);
+  typename InputImageType::SpacingType inputSpacing ( input->GetSpacing() );
+  typename InputImageType::PointType inputOrigin ( input->GetOrigin() );
+
+  typename OutputImageType::SpacingType histoSpacing ;
+  histoSpacing[0] = inputSpacing[0] * m_ThumbSize[0] ;
+  histoSpacing[1] = inputSpacing[1] * m_ThumbSize[1] ;
+  output->SetSpacing( histoSpacing ) ;
+
+  typename OutputImageType::PointType histoOrigin ;
+  histoOrigin[0] = histoSpacing[0] / 2 +  inputOrigin[0] - inputSpacing[0] / 2 ;
+  histoOrigin[1] = histoSpacing[1] / 2 +  inputOrigin[1] - inputSpacing[1] / 2 ;
+  output->SetOrigin( histoOrigin );
+
 }
 
 template <class TInputImage, class TOutputImage >