diff --git a/CMake/OTBCheckCpp11Keywords.cmake b/CMake/OTBCheckCpp11Keywords.cmake
index a956670218e0ee932f057ea994a534767da9402b..707fe8b05a4aa71343df8daf5de3950c341fad71 100644
--- a/CMake/OTBCheckCpp11Keywords.cmake
+++ b/CMake/OTBCheckCpp11Keywords.cmake
@@ -22,6 +22,8 @@ include(CheckCXXSourceCompiles)
 
 set(CMAKE_REQUIRED_FLAGS ${CMAKE_CXX_FLAGS})
 
+unset(OTB_HAS_CXX11 CACHE)
+
 CHECK_CXX_SOURCE_COMPILES("
 #ifdef _MSC_VER
   #if _MSC_VER <= 1700
diff --git a/Documentation/Cookbook/Scripts/otbGenerateWrappersRstDoc.py b/Documentation/Cookbook/Scripts/otbGenerateWrappersRstDoc.py
index e31bdcc37cc6508e75ac2ab42f32757a0d7fa6dc..4c6c30fa402b69ad2c3b342a1e3a4b3684650681 100755
--- a/Documentation/Cookbook/Scripts/otbGenerateWrappersRstDoc.py
+++ b/Documentation/Cookbook/Scripts/otbGenerateWrappersRstDoc.py
@@ -149,10 +149,10 @@ def FindLengthOfLargestColumnText(app,paramlist):
         else:
             if colLength[0] < len(param):
                 colLength[0] = len(param)
-            lenpdescr = len(app.GetParameterName(param))
+            lenpdescr = len(GenerateParameterType(app, param))
             if colLength[2] < lenpdescr:
                 colLength[2] = lenpdescr
-        lenptype = len(GenerateParameterType(app,param))
+        lenptype = len(app.GetParameterName(param))
         if colLength[1] < lenptype:
             colLength[1] = lenptype
     return colLength
@@ -181,14 +181,14 @@ def MakeText(text, size):
 def GenerateParametersTable(app,paramlist):
     colLength = FindLengthOfLargestColumnText(app, paramlist)
     output = linesep + ".. [#] Table: Parameters table for " + ConvertString(app.GetDocName()) + "." + linesep + linesep
-    headerlist = ["Parameter Key", "Parameter Type", "Parameter Description"]
+    headerlist = ["Parameter Key", "Parameter Name", "Parameter Type"]
     for i in xrange(len(headerlist)):
         colLength[i] = len(headerlist[i]) if colLength[i] < len(headerlist[i]) else colLength[i]
     output += RstTableHeading(headerlist, colLength)
     for param in paramlist:
         output += MakeText(param, colLength[0])
-        output += MakeText(GenerateParameterType(app,param), colLength[1])
-        output += MakeText(GenerateParameterType(app,param), colLength[2])
+        output += MakeText(app.GetParameterName(param), colLength[1])
+        output += MakeText(GenerateParameterType(app, param), colLength[2])
         output += '|' + linesep
         output += RstTableHeaderLine(headerlist, colLength, '-')
         if app.GetParameterType(param) ==  otbApplication.ParameterType_Choice:
diff --git a/Documentation/Cookbook/rst/recipes/improc.rst b/Documentation/Cookbook/rst/recipes/improc.rst
index ca935be146903a9b505fdccf2f32396d238c134d..776fa35ad94722c494e0f508d25ed2a48facf03d 100644
--- a/Documentation/Cookbook/rst/recipes/improc.rst
+++ b/Documentation/Cookbook/rst/recipes/improc.rst
@@ -145,9 +145,9 @@ the *MeanShiftSmoothing* application:
 
 ::
 
-    otbcli_MeanShiftSmoothing -in input_image 
+    otbcli_MeanShiftSmoothing -in input_image.tif
                               -fout filtered_range.tif 
-                              -foutpos filtered_spat.tif 
+                              -foutpos filtered_spatial.tif
                               -ranger 30 
                               -spatialr 5 
                               -maxiter 10 
@@ -173,7 +173,7 @@ so, the *LSMSSegmentation* will process them by tiles whose dimensions
 are defined by the *tilesizex* and *tilesizey* parameters, and by
 writing intermediate images to disk, thus keeping the memory consumption
 very low throughout the process. The segmentation will group together
-adjacent pixels whose range distance is below the *ranger* parameter and
+neighboring pixels whose range distance is below the *ranger* parameter and
 (optionally) spatial distance is below the *spatialr* parameter.
 
 ::
@@ -250,7 +250,7 @@ projection, so does the output GIS file).
 
 ::
 
-    otbcli_LSMSVectorization -in input_image 
+    otbcli_LSMSVectorization -in input_image.tif
                              -inseg segmentation_merged.tif 
                              -out segmentation_merged.shp 
                              -tilesizex 256 
diff --git a/Documentation/Cookbook/rst/recipes/pbclassif.rst b/Documentation/Cookbook/rst/recipes/pbclassif.rst
index 8de90bce37a3cee246b18c9664f035268b394947..9eaccd318a2ad4b78c7b622f1f6fc82fdcd54222 100644
--- a/Documentation/Cookbook/rst/recipes/pbclassif.rst
+++ b/Documentation/Cookbook/rst/recipes/pbclassif.rst
@@ -4,10 +4,10 @@ Classification
 Pixel based classification
 --------------------------
 
-Orfeo ToolBox ships with a set of application to perform supervised
-pixel-based image classification. This framework allows to learn from
-multiple images, and using several machine learning method such as
-SVM, Bayes, KNN, Random Forests, Artificial Neural Network, and
+Orfeo ToolBox ships with a set of application to perform supervised or
+unsupervised pixel-based image classification. This framework allows
+to learn from multiple images, and using several machine learning method
+such as SVM, Bayes, KNN, Random Forests, Artificial Neural Network, and
 others...(see application help of ``TrainImagesClassifier`` and
 ``TrainVectorClassifier`` for further details about all the available
 classifiers). Here is an overview of the complete workflow:
@@ -347,8 +347,9 @@ using the ``TrainVectorClassifier`` application.
                                 -feat band_0 band_1 band_2 band_3 band_4 band_5 band_6
 
 The ``-classifier`` parameter allows to choose which machine learning
-model algorithm to train. Please refer to the
-``TrainVectorClassifier`` application reference documentation.
+model algorithm to train. You have the possibility to do the unsupervised
+classification,for it, you must to choose the Shark kmeans classifier.
+Please refer to the ``TrainVectorClassifier`` application reference documentation.
 
 In case of multiple samples files, you can add them to the ``-io.vd``
 parameter (see  `Working with several images`_ section).
@@ -409,6 +410,11 @@ class too, based on the
 `ConfusionMatrixCalculator <http://www.orfeo-toolbox.org/doxygen-current/classotb_1_1ConfusionMatrixCalculator.html>`_ 
 class.
 
+If you have made an unsupervised classification, it must be specified
+to the ``ConputeConfusionMatrix`` application. In this case, a contingency table
+have to be create rather than a confusion matrix. For further details,
+see ``format`` parameter in the application help of *ConputeConfusionMatrix*.
+
 ::
 
     otbcli_ComputeConfusionMatrix -in                labeled_image.tif
diff --git a/Documentation/SoftwareGuide/Latex/ReadWrite.tex b/Documentation/SoftwareGuide/Latex/ReadWrite.tex
index 5c301d60511d4480b0a7757c7359be03072e1e92..2d82fac6b37302a4c00375c8797cf5eed0c8a7c4 100644
--- a/Documentation/SoftwareGuide/Latex/ReadWrite.tex
+++ b/Documentation/SoftwareGuide/Latex/ReadWrite.tex
@@ -253,6 +253,26 @@ IMPORTANT: Note that you'll probably need to "quote" the filename.
   \item Select the JPEG2000 sub-resolution image to read
   \item 0 by default
   \end{itemize}
+\item \begin{verbatim}&bands=r1,r2,...,rn\end{verbatim}
+\begin{itemize}
+    \item Select a subset of bands from the input image
+    \item The syntax is inspired by Python indexing syntax with
+      bands=r1,r2,r3,...,rn  where each ri is a band range that can be :
+      \begin{itemize}
+      \item a single index (1-based) :
+        \begin{itemize}
+          \item $'2'$ means 2nd band
+          \item $'-1'$ means last band
+          \end{itemize}
+        \item or a range of bands :
+          \begin{itemize}
+            \item $'3:'$ means 3rd band until the last one
+            \item $':-2'$ means the first bands until the second to last
+            \item $'2:4'$ means bands 2,3 and 4
+          \end{itemize}
+      \end{itemize}
+    \item empty by default (all bands are read from the input image) 
+\end{itemize}
 \item \begin{verbatim}&skipcarto=<(bool)true>\end{verbatim}
   \begin{itemize}
   \item Skip the cartographic information
@@ -339,8 +359,8 @@ IMPORTANT: Note that you'll probably need to "quote" the filename.
     \item The region must be set with 4 unsigned integers (the separator used is
       the colon ':'). Values are:
       \begin{itemize}
-        \item startx: first index on X
-        \item starty: first index on Y
+        \item startx: first index on X (starting with 0)
+        \item starty: first index on Y (starting with 0)
         \item sizex: size along X
         \item sizey: size along Y 
       \end{itemize}
@@ -349,6 +369,26 @@ IMPORTANT: Note that you'll probably need to "quote" the filename.
     itk::Size classes. The origin of the region within the image with which it
     is associated is defined by Index 
 \end{itemize}
+\item \begin{verbatim}&bands=r1,r2,...,rn\end{verbatim}
+\begin{itemize}
+    \item Select a subset of bands from the output image
+    \item The syntax is inspired by Python indexing syntax with
+      bands=r1,r2,r3,...,rn  where each ri is a band range that can be :
+      \begin{itemize}
+      \item a single index (1-based) :
+        \begin{itemize}
+          \item $'2'$ means 2nd band
+          \item $'-1'$ means last band
+          \end{itemize}
+        \item or a range of bands :
+          \begin{itemize}
+            \item $'3:'$ means 3rd band until the last one
+            \item $':-2'$ means the first bands until the second to last
+            \item $'2:4'$ means bands 2,3 and 4
+          \end{itemize}
+      \end{itemize}
+    \item empty by default (all bands are write from the output image)
+\end{itemize}
 
 \end{itemize}
 
diff --git a/Modules/Applications/AppSARUtils/CMakeLists.txt b/Modules/Applications/AppSARUtils/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..bd7a065d1828ce742920e76cd6382c222f5f67cf
--- /dev/null
+++ b/Modules/Applications/AppSARUtils/CMakeLists.txt
@@ -0,0 +1,2 @@
+project(OTBAppSARUtils)
+otb_module_impl()
diff --git a/Modules/Applications/AppSARUtils/app/CMakeLists.txt b/Modules/Applications/AppSARUtils/app/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f0e7132c08c68baa6c95c2bc7dd114974e26278f
--- /dev/null
+++ b/Modules/Applications/AppSARUtils/app/CMakeLists.txt
@@ -0,0 +1,9 @@
+set(OTBAppSARUtils_LINK_LIBS
+  ${OTBSARUtils_LIBRARIES}
+  ${OTBApplicationEngine_LIBRARIES}
+)
+
+otb_create_application(
+  NAME           ComputeModulusAndPhase
+  SOURCES        otbComputeModulusAndPhase.cxx
+  LINK_LIBRARIES ${${otb-module}_LIBRARIES})
diff --git a/Modules/Applications/AppSARUtils/app/otbComputeModulusAndPhase.cxx b/Modules/Applications/AppSARUtils/app/otbComputeModulusAndPhase.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..f3ea3c2349c357faf97b6a3d2baa6e36ed99725d
--- /dev/null
+++ b/Modules/Applications/AppSARUtils/app/otbComputeModulusAndPhase.cxx
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "otbWrapperApplication.h"
+#include "otbWrapperApplicationFactory.h"
+#include <otbMultiToMonoChannelExtractROI.h>
+
+#include "itkComplexToPhaseImageFilter.h"
+#include "itkComplexToModulusImageFilter.h"
+#include <itkMacro.h>
+
+namespace otb
+{
+//  Application class is defined in Wrapper namespace.
+namespace Wrapper
+{
+
+/** \class ComputeModulusAndPhase
+ *  \brief ComputeModulusAndPhase is an application that
+ *         computes modulus and phase from a complex SAR image.
+ *
+ * \ingroup AppSARUtils
+ */
+class ComputeModulusAndPhase: public Application
+{
+public:
+  // Class declaration is followed by ITK public types for the class, the superclass and smart pointers.
+  typedef ComputeModulusAndPhase Self;
+  typedef Application Superclass;
+  typedef itk::SmartPointer<Self> Pointer;
+  typedef itk::SmartPointer<const Self> ConstPointer;
+
+  /** Standard macro */
+  itkNewMacro (Self);
+  itkTypeMacro(ComputeModulusAndPhase, otb::Wrapper::Application);
+
+  //typedefs for the application
+  typedef otb::MultiToMonoChannelExtractROI<typename ComplexFloatVectorImageType::InternalPixelType, typename ComplexFloatImageType::PixelType> ExtractFilterType;
+  typedef itk::ComplexToModulusImageFilter<ComplexFloatImageType, FloatImageType>   ModulusFilterType;
+  typedef itk::ComplexToPhaseImageFilter<ComplexFloatImageType, FloatImageType>   PhaseFilterType;
+
+private:
+  void DoInit()
+  {
+    SetName("ComputeModulusAndPhase");
+    SetDescription("This application computes the modulus and the phase of a complex SAR image.");
+
+    SetDocName("Compute Modulus And Phase");
+    SetDocLongDescription(
+      "This application computes the modulus and the phase of a "
+      "complex SAR image. The input shoud be a single band image with "
+      "complex pixels."
+    );
+    SetDocLimitations("None");
+    SetDocAuthors("Alexia Mondot (alexia.mondot@c-s.fr) and Mickael Savinaud (mickael.savinaud@c-s.fr)");
+    SetDocSeeAlso("SARPolarMatrixConvert, SARPolarSynth");
+    AddDocTag(Tags::SAR);
+
+    // Input images
+    AddParameter(ParameterType_ComplexInputImage,  "in",   "Input Image");
+    SetParameterDescription("in", "Input image (complex single band)");
+
+    // Outputs
+    AddParameter(ParameterType_OutputImage, "modulus", "Modulus");
+    SetParameterDescription("modulus", "Modulus of the input: sqrt(real*real + imag*imag).");
+
+    AddParameter(ParameterType_OutputImage, "phase", "Phase");
+    SetParameterDescription("phase", "Phase of the input: atan2(imag, real).");
+
+    AddRAMParameter();
+
+    // Doc example parameter settings
+    SetDocExampleParameterValue("in", "monobandComplexFloat.tif");
+    SetDocExampleParameterValue("modulus", "modulus.tif");
+    SetDocExampleParameterValue("phase", "phase.tif");
+  }
+
+  // DoUpdateParameters() is called as soon as a parameter value change.
+  void DoUpdateParameters()
+  {
+  }
+
+  // DoExecute() contains the application core.
+  void DoExecute()
+  {
+    m_Modulus = ModulusFilterType::New();
+    m_Phase = PhaseFilterType::New();
+
+    ComplexFloatVectorImageType::Pointer inImage = GetParameterComplexImage("in");
+
+    if (inImage->GetNumberOfComponentsPerPixel() != 1)
+    {
+        otbAppLogFATAL("Input must be a single band complex image.");
+    }
+
+    // Get first band
+    m_Extract = ExtractFilterType::New();
+    m_Extract->SetInput(inImage);
+
+    // Compute modulus and phase
+    m_Modulus->SetInput(m_Extract->GetOutput());
+    m_Phase->SetInput(m_Extract->GetOutput());
+
+    SetParameterOutputImage("modulus", m_Modulus->GetOutput() );
+    SetParameterOutputImage("phase", m_Phase->GetOutput());
+  }
+
+  ExtractFilterType::Pointer m_Extract;
+  ModulusFilterType::Pointer m_Modulus;
+  PhaseFilterType::Pointer m_Phase;
+};
+
+} // namespace Wrapper
+} // namespace otb
+OTB_APPLICATION_EXPORT(otb::Wrapper::ComputeModulusAndPhase)
diff --git a/Modules/Applications/AppSARUtils/otb-module.cmake b/Modules/Applications/AppSARUtils/otb-module.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..41a1b43467aa97d35721a46dd6f4e4f4ad6b04be
--- /dev/null
+++ b/Modules/Applications/AppSARUtils/otb-module.cmake
@@ -0,0 +1,12 @@
+set(DOCUMENTATION "SAR Utils application.")
+
+otb_module(OTBAppSARUtils
+  DEPENDS
+    OTBApplicationEngine
+  TEST_DEPENDS
+    OTBTestKernel
+    OTBCommandLine
+
+  DESCRIPTION
+    "${DOCUMENTATION}"
+  )
diff --git a/Modules/Applications/AppSARUtils/test/CMakeLists.txt b/Modules/Applications/AppSARUtils/test/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..65dc6b75a9de038c360f9671a1a83c357a020bed
--- /dev/null
+++ b/Modules/Applications/AppSARUtils/test/CMakeLists.txt
@@ -0,0 +1,13 @@
+otb_module_test()
+#----------- ComputeModulusAndPhase TESTS ----------------
+otb_test_application(NAME apTvUtComputeModulusAndPhase_1inputComplex
+                     APP  ComputeModulusAndPhase
+                     OPTIONS -in ${INPUTDATA}/monobandComplexFloat.tif
+                             -modulus ${TEMP}/apTvUtMod1inputComplex.tif
+                             -phase ${TEMP}/apTvUtPha1inputComplex.tif
+                     VALID   --compare-n-images ${EPSILON_6} 2
+                             ${BASELINE}/Mod_monobandComplexFloat.tif
+                             ${TEMP}/apTvUtMod1inputComplex.tif
+                             ${BASELINE}/Pha_monobandComplexFloat.tif
+                             ${TEMP}/apTvUtPha1inputComplex.tif
+                     )
diff --git a/Modules/Applications/AppSegmentation/app/otbLSMSVectorization.cxx b/Modules/Applications/AppSegmentation/app/otbLSMSVectorization.cxx
index a1e8e9b36f7ee71d6c37c973ce5f2c15752ed3f2..a7dae77d1d92c6413c1a573fee73a4df9adc18ff 100644
--- a/Modules/Applications/AppSegmentation/app/otbLSMSVectorization.cxx
+++ b/Modules/Applications/AppSegmentation/app/otbLSMSVectorization.cxx
@@ -100,7 +100,7 @@ private:
     AddRAMParameter();
 
     // Doc example parameter settings
-    SetDocExampleParameterValue("in","avions.tif");
+    SetDocExampleParameterValue("in","maur_rgb.png");
     SetDocExampleParameterValue("inseg","merged.tif");
     SetDocExampleParameterValue("out","vector.shp");
     SetDocExampleParameterValue("tilesizex","256");
diff --git a/Modules/Applications/AppSegmentation/app/otbMeanShiftSmoothing.cxx b/Modules/Applications/AppSegmentation/app/otbMeanShiftSmoothing.cxx
index b5ae63bdfb6d6372d23242a0286313a10d8e5578..6184904bfc67a914d198ee74be5013f51d485cd3 100644
--- a/Modules/Applications/AppSegmentation/app/otbMeanShiftSmoothing.cxx
+++ b/Modules/Applications/AppSegmentation/app/otbMeanShiftSmoothing.cxx
@@ -109,8 +109,8 @@ private:
 
     // Doc example parameter settings
     SetDocExampleParameterValue("in", "maur_rgb.png");
-    SetDocExampleParameterValue("fout", "MeanShift_FilterOutput.tif");
-    SetDocExampleParameterValue("foutpos", "MeanShift_SpatialOutput.tif");
+    SetDocExampleParameterValue("fout", "smooth.tif");
+    SetDocExampleParameterValue("foutpos", "position.tif");
     SetDocExampleParameterValue("spatialr", "16");
     SetDocExampleParameterValue("ranger", "16");
     SetDocExampleParameterValue("thres", "0.1");
diff --git a/Modules/Core/ImageBase/include/otbImageIOBase.h b/Modules/Core/ImageBase/include/otbImageIOBase.h
index 50e79ffaef85755d348ed5fad177d1603c45152d..b6ae1ec2a1393e4c73c66af09d7253b875b85a47 100644
--- a/Modules/Core/ImageBase/include/otbImageIOBase.h
+++ b/Modules/Core/ImageBase/include/otbImageIOBase.h
@@ -303,7 +303,6 @@ public:
   virtual void SetOutputImagePixelType( bool isComplexInternalPixelType, 
                                         bool isVectorImage) = 0;
   
-
   /*-------- This part of the interfaces deals with reading data ----- */
 
   /** Determine the file type. Returns true if this ImageIO can read the
@@ -421,6 +420,12 @@ public:
    */
   const ArrayOfExtensionsType & GetSupportedWriteExtensions() const;
 
+  /** Remap band order in an input buffer using band mapping bandList
+   *  This operation is done in-place. The buffer size should enough to
+   *  contain extracted bands before and after mapping. bandList mapping
+   * between origin components and output components (before any
+   * conversion)*/
+  void DoMapBuffer(void* buffer, size_t numberOfPixels, std::vector<unsigned int>& bandList);
 
 protected:
   ImageIOBase();
diff --git a/Modules/Core/ImageBase/src/otbImageIOBase.cxx b/Modules/Core/ImageBase/src/otbImageIOBase.cxx
index efcf4d0244bc81d150f2686a3c871dd2ac17fca7..d88d601fd66a007b1db2ec7c4f782f1eee852b4b 100644
--- a/Modules/Core/ImageBase/src/otbImageIOBase.cxx
+++ b/Modules/Core/ImageBase/src/otbImageIOBase.cxx
@@ -1269,6 +1269,54 @@ ImageIOBase
   return axis;
 }
 
+void
+ImageIOBase
+::DoMapBuffer(void* buffer, size_t numberOfPixels, std::vector<unsigned int>& bandList)
+{
+  size_t componentSize = this->GetComponentSize();
+  size_t inPixelSize = componentSize * this->GetNumberOfComponents();
+  size_t outPixelSize = componentSize * bandList.size();
+  char* inPos = static_cast<char*>(buffer);
+  char* outPos = static_cast<char*>(buffer);
+  bool workBackward = (outPixelSize > inPixelSize);
+  char *pixBuffer = new char[outPixelSize];
+
+  memset(pixBuffer, 0, outPixelSize);
+
+  if (workBackward)
+    {
+    inPos = inPos + numberOfPixels*inPixelSize;
+    outPos = outPos + numberOfPixels*outPixelSize;
+    for (size_t n=0 ; n<numberOfPixels ; n++)
+      {
+      inPos -= inPixelSize;
+      outPos -= outPixelSize;
+      for (unsigned int i=0 ; i < bandList.size() ; i++)
+        {
+        memcpy(pixBuffer + i*componentSize, inPos + bandList[i]*componentSize, componentSize);
+        }
+      // copy pixBuffer to output
+      memcpy(outPos, pixBuffer, outPixelSize);
+      }
+    }
+  else
+    {
+    for (size_t n=0 ; n<numberOfPixels ; n++)
+      {
+      for (unsigned int i=0 ; i < bandList.size() ; i++)
+        {
+        memcpy(pixBuffer + i*componentSize, inPos + bandList[i]*componentSize, componentSize);
+        }
+      // copy pixBuffer to output
+      memcpy(outPos, pixBuffer, outPixelSize);
+      inPos += inPixelSize;
+      outPos += outPixelSize;
+      }
+    }
+
+  delete[] pixBuffer;
+}
+
 void ImageIOBase::PrintSelf(std::ostream& os, itk::Indent indent) const
 {
   Superclass::PrintSelf(os, indent);
diff --git a/Modules/Filtering/MathParser/src/otbParser.cxx b/Modules/Filtering/MathParser/src/otbParser.cxx
index 56bdd287dcdb7f2c12fdb481bbe7d6f71dd03de4..4280d3ac9c85b508453b5c23685bf0dc52f89255 100644
--- a/Modules/Filtering/MathParser/src/otbParser.cxx
+++ b/Modules/Filtering/MathParser/src/otbParser.cxx
@@ -62,6 +62,7 @@ public:
   {
     m_MuParser.DefineFun("ndvi", Self::NDVI);
     m_MuParser.DefineFun("NDVI", Self::NDVI);
+    m_MuParser.DefineFun("atan2", Self::ATAN2);
 
 #ifdef OTB_MUPARSER_HAS_CXX_LOGICAL_OPERATORS
     /* Starting with muParser 2.0.0, logical operators have been
@@ -208,6 +209,11 @@ private:
       }
     return (niri-r)/(niri+r);
   }
+  
+  static ValueType ATAN2(ValueType y, ValueType x)
+  {
+    return vcl_atan2(y,x);
+  }
 
 #ifdef OTB_MUPARSER_HAS_CXX_LOGICAL_OPERATORS
   static ValueType AND(ValueType left, ValueType right)
diff --git a/Modules/IO/ExtendedFilename/include/otbExtendedFilenameHelper.h b/Modules/IO/ExtendedFilename/include/otbExtendedFilenameHelper.h
index 1f6db89a082f5aa59589929c7ca44c8a8060d110..b6d29171cd0ef81fd67ad3822c06366c417f2544 100644
--- a/Modules/IO/ExtendedFilename/include/otbExtendedFilenameHelper.h
+++ b/Modules/IO/ExtendedFilename/include/otbExtendedFilenameHelper.h
@@ -55,6 +55,30 @@ public:
   itkGetStringMacro(ExtendedFileName);
   itkGetStringMacro(SimpleFileName);
 
+  struct GenericBandRange : std::pair<int,int>
+  {
+    GenericBandRange() {}
+
+    GenericBandRange(int a);
+
+    GenericBandRange(const std::pair<int,int>& a);
+
+    GenericBandRange(int a,int b);
+
+    bool SetString(const std::string& str, size_t start=0 , size_t size=std::string::npos);
+
+    void Print(std::ostream& os);
+  };
+
+  /**  Decode the string into a list of GenericBandRange, band indexes are
+   *  1-based. */
+  std::vector<ExtendedFilenameHelper::GenericBandRange> GetGenericBandRange(const std::string &bandRange) const;
+
+  /** Resolve the list of band ranges into real band indexes, according to
+   *  a total number of bands in the image. Note that the output indexes are
+   *  zero-based (0 is the first component) */
+  bool ResolveBandRange(const std::string &bandRange, const unsigned int &nbBands, std::vector<unsigned int> &output) const;
+
 protected:
   ExtendedFilenameHelper() {}
   ~ExtendedFilenameHelper() ITK_OVERRIDE {}
diff --git a/Modules/IO/ExtendedFilename/include/otbExtendedFilenameToReaderOptions.h b/Modules/IO/ExtendedFilename/include/otbExtendedFilenameToReaderOptions.h
index 0abb00111d23e4945ed98be97556d81928316654..79c8bb00e0a7058d1a5531174254661deb47da50 100644
--- a/Modules/IO/ExtendedFilename/include/otbExtendedFilenameToReaderOptions.h
+++ b/Modules/IO/ExtendedFilename/include/otbExtendedFilenameToReaderOptions.h
@@ -35,6 +35,13 @@ namespace otb
  * - &resol : resolution factor for jpeg200 files
  * - &skipcarto : switch to skip the cartographic information
  * - &skipgeom  : switch to skip the geometric information
+ * - &bands : select a band composition different from the input image,
+ *           syntax is bands=r1,r2,r3,...,rn  where each ri is a band range
+ *           that can be :
+ *             - a single index (1-based) : '2' means 2nd band, '-1' means last band
+ *             - a range of bands : '3:' means 3rd band until the last one
+ *                 ':-2' means the first bands until the second to last
+ *                 '2:4' means bands 2,3 and 4
  *
  *  \sa ImageFileReader
  *
@@ -67,6 +74,7 @@ public:
     std::pair< bool, bool         >  skipCarto;
     std::pair< bool, bool         >  skipGeom;
     std::pair< bool, bool         >  skipRpcTag;
+    std::pair< bool, std::string  >  bandRange;
     std::vector<std::string>         optionList;
   };
 
@@ -86,6 +94,10 @@ public:
   bool GetSkipGeom () const;
   bool SkipRpcTagIsSet () const;
   bool GetSkipRpcTag () const;
+  std::string GetBandRange () const;
+
+  /** Test if band range extended filename is set */
+  bool BandRangeIsSet () const;
 
 protected:
   ExtendedFilenameToReaderOptions();
diff --git a/Modules/IO/ExtendedFilename/include/otbExtendedFilenameToWriterOptions.h b/Modules/IO/ExtendedFilename/include/otbExtendedFilenameToWriterOptions.h
index b99b755b263aa1b32744e1c0913df706e32f25f2..81909d152832b2a6ef7f6c98333db05835a805b3 100644
--- a/Modules/IO/ExtendedFilename/include/otbExtendedFilenameToWriterOptions.h
+++ b/Modules/IO/ExtendedFilename/include/otbExtendedFilenameToWriterOptions.h
@@ -72,6 +72,7 @@ public:
     std::pair<bool,  std::string>                streamingSizeMode;
     std::pair<bool,  double>                     streamingSizeValue;
     std::pair<bool,  std::string>                box;
+    std::pair< bool, std::string>                bandRange;
     std::vector<std::string>                     optionList;
   };
 
@@ -91,10 +92,13 @@ public:
   std::string GetStreamingSizeMode() const;
   bool StreamingSizeValueIsSet() const;
   double GetStreamingSizeValue() const;
+  std::string GetBandRange () const;
 
   bool BoxIsSet() const;
   std::string GetBox() const;
 
+  /** Test if band range extended filename is set */
+  bool BandRangeIsSet () const;
 
 protected:
   ExtendedFilenameToWriterOptions();
diff --git a/Modules/IO/ExtendedFilename/src/otbExtendedFilenameHelper.cxx b/Modules/IO/ExtendedFilename/src/otbExtendedFilenameHelper.cxx
index e6885ffbaf77ba027edbd53f5bbee5ce203cc479..e92e2b05fb6dc23643e42bd7b4b56d7f7a14e95b 100644
--- a/Modules/IO/ExtendedFilename/src/otbExtendedFilenameHelper.cxx
+++ b/Modules/IO/ExtendedFilename/src/otbExtendedFilenameHelper.cxx
@@ -20,6 +20,8 @@
 
 #include "otbExtendedFilenameHelper.h"
 #include "otb_boost_string_header.h"
+#include "otbStringUtils.h"
+
 namespace otb
 {
 
@@ -43,32 +45,31 @@ ExtendedFilenameHelper
       {
       boost::split(tmp2, tmp1[1], boost::is_any_of("&"), boost::token_compress_on);
       for (unsigned int i=0; i<tmp2.size(); i++)
-       if (tmp2[i].length() >0)
+      if (!tmp2[i].empty())
         {
-			std::vector<std::string> tmp;
-			boost::split(tmp, tmp2[i], boost::is_any_of("="), boost::token_compress_on);
-			if (tmp.size()>1)
-				{
-				  if (tmp[1].length()>0)
-					  {
-						  if (m_OptionMap[tmp[0]].empty())
-							{
-								m_OptionMap[tmp[0]]=tmp[1];
-							}
-						  else
-							{
-								itkWarningMacro("Duplicated option detected: " << tmp[0] << ". Using value " << tmp[1] << ".");
-							}
-					  }
-				  else
-					itkGenericExceptionMacro( << "Value for option '" << tmp[0] << "' is not set.");
-				}
+        std::vector<std::string> tmp;
+        boost::split(tmp, tmp2[i], boost::is_any_of("="), boost::token_compress_on);
+        if (tmp.size()>1)
+          {
+          if (!tmp[1].empty())
+            {
+            if (m_OptionMap[tmp[0]].empty())
+              {
+              m_OptionMap[tmp[0]]=tmp[1];
+              }
+            else
+              {
+              itkWarningMacro("Duplicated option detected: " << tmp[0] << ". Using value " << tmp[1] << ".");
+              }
+            }
+          else
+            itkGenericExceptionMacro( << "Value for option '" << tmp[0] << "' is not set.");
+          }
         }
       }
     }
 }
 
-
 const ExtendedFilenameHelper::OptionMapType &
 ExtendedFilenameHelper
 ::GetOptionMap(void) const
@@ -76,4 +77,181 @@ ExtendedFilenameHelper
   return this->m_OptionMap;
 }
 
+/*-------------------- GenericBandRange ----------------------*/
+
+ExtendedFilenameHelper::GenericBandRange
+::GenericBandRange(int a)
+  : std::pair<int,int>(a,a)
+  {
+  }
+
+ExtendedFilenameHelper::GenericBandRange
+::GenericBandRange(const std::pair<int,int>& a)
+  : std::pair<int,int>(a)
+  {
+    if (a.second>=0 && a.second < a.first)
+      {
+      throw std::range_error("Invalid range");
+      }
+  }
+
+ExtendedFilenameHelper::GenericBandRange
+::GenericBandRange(int a,int b)
+  : std::pair<int,int>(a,b)
+  {
+    if (b>=0 && b < a)
+      {
+      throw std::range_error("Invalid range");
+      }
+  }
+
+bool
+ExtendedFilenameHelper::GenericBandRange
+::SetString(const std::string& str, size_t start , size_t size)
+  {
+  assert(start < str.size());
+  bool ret = true;
+  if (size == 0)
+    {
+    first = 0;
+    second = 0;
+    return false;
+    }
+  size_t end = str.size();
+  if (size != std::string::npos && (start+size) <= str.size())
+    {
+    end = start + size;
+    }
+  size_t pos = str.find(':',start);
+  if (pos != std::string::npos && pos<end)
+    {
+    // range of values
+    if (pos > start)
+      {
+      try
+        {
+        first = boost::lexical_cast<int>(str.c_str()+start, pos-start);
+        }
+      catch(boost::bad_lexical_cast &)
+        {
+        ret = false;
+        }
+      }
+    else
+      {
+      first = 0;
+      }
+    if (end > pos + 1)
+      {
+      try
+        {
+        second = boost::lexical_cast<int>(str.c_str()+ pos + 1, end - pos - 1);
+        }
+      catch(boost::bad_lexical_cast &)
+        {
+        ret = false;
+        }
+      }
+    else
+      {
+      second = 0;
+      }
+    }
+  else
+    {
+    // single value
+    try
+      {
+      first = boost::lexical_cast<int>(str.c_str()+start, end-start);
+      second = first;
+      }
+    catch(boost::bad_lexical_cast &)
+      {
+      ret = false;
+      }
+    }
+  return ret;
+  }
+
+void
+ExtendedFilenameHelper::GenericBandRange
+::Print(std::ostream& os)
+  {
+  if (this->first)
+    {
+    os << this->first;
+    }
+  if (this->first != this->second)
+    {
+    if (this->first || this->second)
+      {
+      os << ":";
+      }
+    if (this->second)
+      {
+      os << this->second;
+      }
+    }
+  }
+
+std::vector<ExtendedFilenameHelper::GenericBandRange>
+ExtendedFilenameHelper
+::GetGenericBandRange(const std::string &bandRange) const
+{
+  //Parse string to return vector of band range
+  std::vector<ExtendedFilenameHelper::GenericBandRange> vBands;
+  size_t start = 0;
+  size_t pos;
+  if (!bandRange.empty())
+    {
+    while (start != std::string::npos)
+      {
+      pos = bandRange.find(',',start);
+      if (pos > start)
+        {
+        ExtendedFilenameHelper::GenericBandRange range;
+        size_t size = (pos == std::string::npos ? pos : pos - start);
+
+        bool ret = range.SetString(bandRange, start, size);
+        if (ret) vBands.push_back(range);
+        }
+      if (pos != std::string::npos) pos++;
+      start = pos;
+      }
+    }
+  return vBands;
+}
+
+bool
+ExtendedFilenameHelper
+::ResolveBandRange(const std::string &bandRange, const unsigned int &nbBands, std::vector<unsigned int> &output) const
+{
+  output.clear();
+  std::vector<ExtendedFilenameHelper::GenericBandRange> bandRangeList = this->GetGenericBandRange(bandRange);
+  for (unsigned int i=0 ; i<bandRangeList.size() ; i++)
+    {
+    int a = bandRangeList[i].first;
+    int b = bandRangeList[i].second;
+    if (a<0) a+= nbBands+1;
+    if (b<0) b+= nbBands+1;
+    if (a==0) a=1;
+    if (b==0) b=nbBands;
+
+    if (1<=a && a<=b && b<=(int)nbBands)
+      {
+      for (unsigned int k=a ; k <= (unsigned int)b ; k++)
+        {
+        output.push_back((int)k -1);
+        }
+      }
+    else
+      {
+      // Invalid range wrt. the given number of bands
+      itkExceptionMacro("Invalid band number.");
+      return false;
+      }
+    }
+  return true;
+}
+
 } // end namespace otb
diff --git a/Modules/IO/ExtendedFilename/src/otbExtendedFilenameToReaderOptions.cxx b/Modules/IO/ExtendedFilename/src/otbExtendedFilenameToReaderOptions.cxx
index de61847cf8e42dd06856b9d5f34f7182bb1ecbda..308f5239c1e9aeb4aaccd7066e08cfaca1e605bc 100644
--- a/Modules/IO/ExtendedFilename/src/otbExtendedFilenameToReaderOptions.cxx
+++ b/Modules/IO/ExtendedFilename/src/otbExtendedFilenameToReaderOptions.cxx
@@ -20,6 +20,7 @@
 
 #include "otbExtendedFilenameToReaderOptions.h"
 #include "otb_boost_string_header.h"
+#include "itksys/RegularExpression.hxx"
 
 namespace otb
 {
@@ -48,12 +49,16 @@ ExtendedFilenameToReaderOptions
   m_Options.skipRpcTag.first  = false;
   m_Options.skipRpcTag.second = false;
 
+  m_Options.bandRange.first = false;
+  m_Options.bandRange.second = "";
+
   m_Options.optionList.push_back("geom");
   m_Options.optionList.push_back("sdataidx");
   m_Options.optionList.push_back("resol");
   m_Options.optionList.push_back("skipcarto");
   m_Options.optionList.push_back("skipgeom");
   m_Options.optionList.push_back("skiprpctag");
+  m_Options.optionList.push_back("bands");
 }
 
 void
@@ -124,6 +129,22 @@ ExtendedFilenameToReaderOptions
       }
     }
 
+  if (!map["bands"].empty())
+    {
+    // Basic check on bandRange (using regex)
+    itksys::RegularExpression reg;
+    reg.compile("^((\\-?[0-9]+)?(:(\\-?[0-9]+)?)?)(,(\\-?[0-9]+)?(:(\\-?[0-9]+)?)?)*$");
+    if (reg.find(map["bands"]))
+      {
+      m_Options.bandRange.first = true;
+      m_Options.bandRange.second = map["bands"];
+      }
+    else
+      {
+      itkExceptionMacro("Unkwown value "<<map["bands"]<<" for band range. Expect a list of tokens separated with comma (each token being a single band index or a range in the form x:y)");
+      }
+    }
+
   //Option Checking
   MapIteratorType it;
   for ( it=map.begin(); it != map.end(); it++ )
@@ -224,4 +245,18 @@ ExtendedFilenameToReaderOptions
   return m_Options.skipRpcTag.second;
 }
 
+bool
+ExtendedFilenameToReaderOptions
+::BandRangeIsSet () const
+{
+  return m_Options.bandRange.first;
+}
+
+std::string
+ExtendedFilenameToReaderOptions
+::GetBandRange () const
+{
+  return m_Options.bandRange.second;
+}
+
 } // end namespace otb
diff --git a/Modules/IO/ExtendedFilename/src/otbExtendedFilenameToWriterOptions.cxx b/Modules/IO/ExtendedFilename/src/otbExtendedFilenameToWriterOptions.cxx
index 305afc72ba4bdecd7b24fe511aaa02abdc83c0f0..b3413fdc53286ac0cbf322f76783edf10c4cdc6f 100644
--- a/Modules/IO/ExtendedFilename/src/otbExtendedFilenameToWriterOptions.cxx
+++ b/Modules/IO/ExtendedFilename/src/otbExtendedFilenameToWriterOptions.cxx
@@ -43,12 +43,16 @@ ExtendedFilenameToWriterOptions
   m_Options.streamingSizeMode.first   = false;
   m_Options.streamingSizeValue.first  = false;
 
+  m_Options.bandRange.first = false;
+  m_Options.bandRange.second = "";
+
   m_Options.optionList.push_back("writegeom");
   m_Options.optionList.push_back("writerpctags");
   m_Options.optionList.push_back("streaming:type");
   m_Options.optionList.push_back("streaming:sizemode");
   m_Options.optionList.push_back("streaming:sizevalue");
   m_Options.optionList.push_back("box");
+  m_Options.optionList.push_back("bands");
 }
 
 void
@@ -158,6 +162,22 @@ ExtendedFilenameToWriterOptions
       }
     }
 
+  if (!map["bands"].empty())
+    {
+    // Basic check on bandRange (using regex)
+    itksys::RegularExpression reg;
+    reg.compile("^((\\-?[0-9]+)?(:(\\-?[0-9]+)?)?)(,(\\-?[0-9]+)?(:(\\-?[0-9]+)?)?)*$");
+    if (reg.find(map["bands"]))
+      {
+      m_Options.bandRange.first = true;
+      m_Options.bandRange.second = map["bands"];
+      }
+    else
+      {
+      itkWarningMacro("Unkwown value "<<map["bands"]<<" for band range. Expect a list of tokens separated with comma (each token being a single band index or a range in the form x:y)");
+      }
+    }
+
   //Option Checking
   for ( it=map.begin(); it != map.end(); it++ )
     {
@@ -289,5 +309,18 @@ ExtendedFilenameToWriterOptions
   return m_Options.box.second;
 }
 
+bool
+ExtendedFilenameToWriterOptions
+::BandRangeIsSet () const
+{
+  return m_Options.bandRange.first;
+}
+
+std::string
+ExtendedFilenameToWriterOptions
+::GetBandRange () const
+{
+  return m_Options.bandRange.second;
+}
 
 } // end namespace otb
diff --git a/Modules/IO/ExtendedFilename/test/CMakeLists.txt b/Modules/IO/ExtendedFilename/test/CMakeLists.txt
index d5a7cedb3b88e0d39be9bff42f84b6459493f28e..2ab3ae184c45597375b44deb46810c98cea1e835 100644
--- a/Modules/IO/ExtendedFilename/test/CMakeLists.txt
+++ b/Modules/IO/ExtendedFilename/test/CMakeLists.txt
@@ -58,7 +58,7 @@ otb_add_test(NAME ioTvExtendedFilenameToReaderOptions_FullOptions COMMAND otbExt
   ${BASELINE}/ioTvExtendedFilenameToReaderOptions_FullOptions.txt
   ${TEMP}/ioTvExtendedFilenameToReaderOptions_FullOptions.txt
   otbExtendedFilenameToReaderOptions
-  /home/data/filename.tif?&geom=/home/dev/custom.geom&sdataidx=2&resol=4&skipcarto=On
+  /home/data/filename.tif?&geom=/home/dev/custom.geom&sdataidx=2&resol=4&skipcarto=On&bands=-23,:3,45:,-6:-6,234:-5
   ${TEMP}/ioTvExtendedFilenameToReaderOptions_FullOptions.txt
   )
 
@@ -71,6 +71,16 @@ otb_add_test(NAME ioTvExtendedFilenameToReaderOptions_NoOptions COMMAND otbExten
   ${TEMP}/ioTvExtendedFilenameToReaderOptions_NoOptions.txt
   )
 
+otb_add_test(NAME ioTvExtendedFilenameToReaderOptions_BandList COMMAND otbExtendedFilenameTestDriver
+  --compare-ascii ${NOTOL}
+  ${BASELINE}/ioTvExtendedFilenameToReaderOptions_BandList.txt
+  ${TEMP}/ioTvExtendedFilenameToReaderOptions_BandList.txt
+  otbExtendedFilenameToReaderOptions
+  /home/data/filename.tif?bands=3,5:,-3,2:-2
+  ${TEMP}/ioTvExtendedFilenameToReaderOptions_BandList.txt
+  6
+  )
+
 otb_add_test(NAME ioTvExtendedFilenameToWriterOptions_FullOptions COMMAND otbExtendedFilenameTestDriver
   --compare-ascii ${NOTOL}
   ${BASELINE}/ioTvExtendedFilenameToWriterOptions_FullOptions.txt
diff --git a/Modules/IO/ExtendedFilename/test/otbExtendedFilenameToReaderOptionsTest.cxx b/Modules/IO/ExtendedFilename/test/otbExtendedFilenameToReaderOptionsTest.cxx
index 31aab027ebd40b4c64586fea29623318db311987..46ea10134688591fe3fc93bc77fffdec0223474b 100644
--- a/Modules/IO/ExtendedFilename/test/otbExtendedFilenameToReaderOptionsTest.cxx
+++ b/Modules/IO/ExtendedFilename/test/otbExtendedFilenameToReaderOptionsTest.cxx
@@ -24,7 +24,7 @@
 
 typedef otb::ExtendedFilenameToReaderOptions FilenameHelperType;
 
-int otbExtendedFilenameToReaderOptions(int itkNotUsed(argc), char* argv[])
+int otbExtendedFilenameToReaderOptions(int argc, char* argv[])
 {
   // Verify the number of parameters in the command line
   const char * inputExtendedFilename  = argv[1];
@@ -52,5 +52,38 @@ int otbExtendedFilenameToReaderOptions(int itkNotUsed(argc), char* argv[])
   file << helper->SkipCartoIsSet() << std::endl;
   file << helper->GetSkipCarto() << std::endl;
 
+  file << helper->BandRangeIsSet() << std::endl;
+  file << "[";
+
+  std::vector<otb::ExtendedFilenameHelper::GenericBandRange> rangeList = helper->GetGenericBandRange(helper->GetBandRange());
+  for (unsigned int i=0 ; i<rangeList.size(); i++)
+    {
+    if (i) file << ",";
+    rangeList[i].Print(file);
+    }
+  file << "]" << std::endl;
+
+  if (argc >= 4)
+    {
+    unsigned int nbBands = atoi(argv[3]);
+    std::vector<unsigned int> bandList;
+    bool ret = helper->ResolveBandRange(helper->GetBandRange(), nbBands,bandList);
+    if (ret)
+      {
+      file << "BandList = [";
+      for (unsigned int k=0 ; k<bandList.size() ; k++)
+        {
+        if (k) file << ",";
+        file << bandList[k];
+        }
+      file << "]" << std::endl;
+      }
+    else
+      {
+      std::cout << "Invalid band range for a "<<nbBands<<" bands image"<< std::endl;
+      }
+    }
+
+  file.close();
   return EXIT_SUCCESS;
 }
diff --git a/Modules/IO/IOGDAL/src/otbGDALImageIO.cxx b/Modules/IO/IOGDAL/src/otbGDALImageIO.cxx
index c06cdd83acf3bd09fd2cd55cedf2114258e950a2..968ec2a5fff7a52fb1aa9292a7b85aaf9a4728c6 100644
--- a/Modules/IO/IOGDAL/src/otbGDALImageIO.cxx
+++ b/Modules/IO/IOGDAL/src/otbGDALImageIO.cxx
@@ -1205,7 +1205,23 @@ void GDALImageIO::InternalReadImageInformation()
     if ((GDALGetRasterColorInterpretation(hBand) == GCI_PaletteIndex)
         && (hTable = GDALGetRasterColorTable(hBand)) != ITK_NULLPTR)
       {
-      m_IsIndexed = true;
+
+      // Mantis: 1049 : OTB does not handle tif with NBITS=1 properly
+      // When a palette is available and pixel type is Byte, the image is
+      // automatically read as a color image (using the palette). Perhaps this
+      // behaviour should be restricted.  Comment color table interpretation in
+      // gdalimageio
+  
+      // FIXME: Better support of color table in OTB
+      // - disable palette conversion in GDALImageIO (the comments in this part
+      // of the code are rather careful)
+      // - GDALImageIO should report the palette to ImageFileReader (as a metadata ?
+      // a kind of LUT ?).
+      // - ImageFileReader should use a kind of adapter filter to convert the mono
+      // image into color.
+      
+      // Do not set indexed image attribute to true
+      //m_IsIndexed = true;
 
       unsigned int ColorEntryCount = GDALGetColorEntryCount(hTable);
 
diff --git a/Modules/IO/ImageIO/include/otbImageFileReader.h b/Modules/IO/ImageIO/include/otbImageFileReader.h
index 928cef11e9be230153b5ab7b8c51bb0fc4c3c16d..daf6c58e800fc4c14bccb519edc9dcfc47400324 100644
--- a/Modules/IO/ImageIO/include/otbImageFileReader.h
+++ b/Modules/IO/ImageIO/include/otbImageFileReader.h
@@ -207,6 +207,15 @@ private:
   unsigned int m_AdditionalNumber;
 
   bool m_KeywordListUpToDate;
+
+  /** Mapping between origin components and output components (before any
+   * conversion) */
+  std::vector<unsigned int> m_BandList;
+
+  /** Store the number of components to be exported to the output image
+   *  This variable can be the number of components in m_ImageIO or the
+   *  number of components in the m_BandList (if used) */
+  unsigned int m_IOComponents;
 };
 
 } //namespace otb
diff --git a/Modules/IO/ImageIO/include/otbImageFileReader.txx b/Modules/IO/ImageIO/include/otbImageFileReader.txx
index f0e30086dbd75a3425831cc5f531f478d4566893..cf647aac63f77a3945b60f8b48eb160d94d74779 100644
--- a/Modules/IO/ImageIO/include/otbImageFileReader.txx
+++ b/Modules/IO/ImageIO/include/otbImageFileReader.txx
@@ -69,7 +69,8 @@ ImageFileReader<TOutputImage, ConvertPixelTraits>
    m_ActualIORegion(),
    m_FilenameHelper(FNameHelperType::New()),
    m_AdditionalNumber(0),
-   m_KeywordListUpToDate(false)
+   m_KeywordListUpToDate(false),
+   m_IOComponents(0)
 {
 }
 
@@ -185,7 +186,8 @@ ImageFileReader<TOutputImage, ConvertPixelTraits>
   if (this->m_ImageIO->GetComponentTypeInfo()
       == typeid(typename ConvertOutputPixelTraits::ComponentType)
       && (this->m_ImageIO->GetNumberOfComponents()
-          == ConvertIOPixelTraits::GetNumberOfComponents()))
+          == ConvertIOPixelTraits::GetNumberOfComponents())
+      && !m_FilenameHelper->BandRangeIsSet())
     {
     // Have the ImageIO read directly into the allocated buffer
     this->m_ImageIO->Read(buffer);
@@ -197,19 +199,26 @@ ImageFileReader<TOutputImage, ConvertPixelTraits>
     // regardless of the actual type of the pixels.
     ImageRegionType region = output->GetBufferedRegion();
 
-    // Adapt the image size with the region
-    std::streamoff nbBytes = (this->m_ImageIO->GetComponentSize() * this->m_ImageIO->GetNumberOfComponents())
-                             * static_cast<std::streamoff>(region.GetNumberOfPixels());
+    // Adapt the image size with the region and take into account a potential
+    // remapping of the components. m_BandList is empty if no band range is set
+    std::streamoff nbBytes =
+      ( this->m_ImageIO->GetComponentSize()
+      * std::max(this->m_ImageIO->GetNumberOfComponents(),(unsigned int) m_BandList.size()))
+      * static_cast<std::streamoff>(region.GetNumberOfPixels());
 
     char * loadBuffer = new char[nbBytes];
 
-    otbMsgDevMacro(<< "size of Buffer to GDALImageIO::read = " << nbBytes << " = \n"
+    otbMsgDevMacro(<< "buffer size for ImageIO::read = " << nbBytes << " = \n"
         << "ComponentSize ("<< this->m_ImageIO->GetComponentSize() << ") x " \
-        << "Nb of Component (" << this->m_ImageIO->GetNumberOfComponents() << ") x " \
-        << "Nb of Pixel to read (" << region.GetNumberOfPixels() << ")" );
+        << "Nb of Component ( max(" << this->m_ImageIO->GetNumberOfComponents() \
+        << " , "<<m_BandList.size() << ") ) x " \
+        << "Nb of Pixel to read (" << region.GetNumberOfPixels() << ")");
 
     this->m_ImageIO->Read(loadBuffer);
 
+    if (m_FilenameHelper->BandRangeIsSet())
+      this->m_ImageIO->DoMapBuffer(loadBuffer, region.GetNumberOfPixels(), this->m_BandList);
+
     this->DoConvertBuffer(loadBuffer, region.GetNumberOfPixels());
 
     delete[] loadBuffer;
@@ -534,13 +543,28 @@ ImageFileReader<TOutputImage, ConvertPixelTraits>
   region.SetSize(dimSize);
   region.SetIndex(start);
 
+  // detect number of output components
+  m_IOComponents = this->m_ImageIO->GetNumberOfComponents();
+  m_BandList.clear();
+  if (m_FilenameHelper->BandRangeIsSet())
+    {
+    bool ret = m_FilenameHelper->ResolveBandRange(m_FilenameHelper->GetBandRange(), m_IOComponents, m_BandList);
+    if (ret == false || m_BandList.size() == 0)
+      {
+      // invalid range
+      itkGenericExceptionMacro("The given band range is either empty or invalid for a "
+        <<m_IOComponents <<" bands input image!");
+      }
+    m_IOComponents = m_BandList.size();
+    }
+
 // THOMAS : ajout
 // If a VectorImage, this requires us to set the
 // VectorLength before allocate
   if (strcmp(output->GetNameOfClass(), "VectorImage") == 0)
     {
     typedef typename TOutputImage::AccessorFunctorType AccessorFunctorType;
-    AccessorFunctorType::SetVectorLength(output, this->m_ImageIO->GetNumberOfComponents());
+    AccessorFunctorType::SetVectorLength(output, m_IOComponents);
     }
 
   output->SetLargestPossibleRegion(region);
@@ -808,7 +832,7 @@ ImageFileReader<TOutputImage, ConvertPixelTraits>
       >                                                 \
       ::ConvertVectorImage(                             \
        static_cast<type*>(inputData),                  \
-       m_ImageIO->GetNumberOfComponents(),             \
+       m_IOComponents,             \
        outputData,                                     \
        numberOfPixels);              \
      } \
@@ -821,7 +845,7 @@ ImageFileReader<TOutputImage, ConvertPixelTraits>
       >                                                 \
       ::Convert(                                        \
         static_cast<type*>(inputData),                  \
-        m_ImageIO->GetNumberOfComponents(),             \
+        m_IOComponents,             \
         outputData,                                     \
         numberOfPixels);              \
       } \
@@ -843,7 +867,7 @@ ImageFileReader<TOutputImage, ConvertPixelTraits>
         >                                                 \
         ::ConvertComplexVectorImageToVectorImageComplex(                             \
          static_cast<type*>(inputData),                \
-         m_ImageIO->GetNumberOfComponents(),             \
+         m_IOComponents,             \
          outputData,                                     \
          numberOfPixels); \
        }\
@@ -856,7 +880,7 @@ ImageFileReader<TOutputImage, ConvertPixelTraits>
         >                                                  \
         ::ConvertComplexVectorImageToVectorImage(                             \
          static_cast<type*>(inputData),                \
-         m_ImageIO->GetNumberOfComponents(),             \
+         m_IOComponents,             \
          outputData,                                     \
          numberOfPixels);              \
        }\
@@ -870,7 +894,7 @@ ImageFileReader<TOutputImage, ConvertPixelTraits>
       >                                                 \
       ::ConvertComplexToGray(                                        \
        static_cast<type*>(inputData),                  \
-       m_ImageIO->GetNumberOfComponents(),             \
+       m_IOComponents,             \
        outputData,                                     \
        numberOfPixels);              \
      } \
@@ -921,6 +945,7 @@ ImageFileReader<TOutputImage, ConvertPixelTraits>
 #undef OTB_CONVERT_CBUFFER_IF_BLOCK
 }
 
+
 } //namespace otb
 
 #endif
diff --git a/Modules/IO/ImageIO/include/otbImageFileWriter.h b/Modules/IO/ImageIO/include/otbImageFileWriter.h
index 47f64fb70eb57255d4e54afc00a25bac24dbdc56..b7bc6499b089a47cf7c75822523e56fb9cf819e0 100644
--- a/Modules/IO/ImageIO/include/otbImageFileWriter.h
+++ b/Modules/IO/ImageIO/include/otbImageFileWriter.h
@@ -261,6 +261,15 @@ private:
   bool          m_IsObserving;
   unsigned long m_ObserverID;
   InputIndexType m_ShiftOutputIndex;
+
+  /** Mapping between origin components and output components (before any
+   * conversion) */
+  std::vector<unsigned int> m_BandList;
+
+  /** Store the number of components to be exported to the output image
+   *  This variable can be the number of components in m_ImageIO or the
+   *  number of components in the m_BandList (if used) */
+  unsigned int m_IOComponents;
 };
 
 } // end namespace otb
diff --git a/Modules/IO/ImageIO/include/otbImageFileWriter.txx b/Modules/IO/ImageIO/include/otbImageFileWriter.txx
index da083b764e2bd349a217efb99df005dcabcb4fdc..3224f5a3860a47e2cb59c7d24d00296bb90747dd 100644
--- a/Modules/IO/ImageIO/include/otbImageFileWriter.txx
+++ b/Modules/IO/ImageIO/include/otbImageFileWriter.txx
@@ -69,7 +69,8 @@ ImageFileWriter<TInputImage>
     m_WriteGeomFile(false),
     m_FilenameHelper(),
     m_IsObserving(true),
-    m_ObserverID(0)
+    m_ObserverID(0),
+    m_IOComponents(0)
 {
   //Init output index shift
   m_ShiftOutputIndex.Fill(0);
@@ -710,6 +711,19 @@ ImageFileWriter<TInputImage>
 
     typedef typename InputImageType::AccessorFunctorType AccessorFunctorType;
     m_ImageIO->SetNumberOfComponents(AccessorFunctorType::GetVectorLength(input));
+
+    m_IOComponents = m_ImageIO->GetNumberOfComponents();
+    m_BandList.clear();
+    if (m_FilenameHelper->BandRangeIsSet())
+      {
+      // get band range
+      bool retBandRange = m_FilenameHelper->ResolveBandRange(m_FilenameHelper->GetBandRange(), m_IOComponents, m_BandList);
+      if (retBandRange == false || m_BandList.empty())
+        {
+        // invalid range
+        itkGenericExceptionMacro("The given band range is either empty or invalid for a " << m_IOComponents <<" bands input image!");
+        }
+      }
     }
   else
     {
@@ -734,8 +748,10 @@ ImageFileWriter<TInputImage>
     Convert(m_ImageIO->GetIORegion(), ioRegion, m_ShiftOutputIndex);
   InputImageRegionType bufferedRegion = input->GetBufferedRegion();
 
-  // before this test, bad stuff would happened when they don't match
-  if (bufferedRegion != ioRegion)
+  // before this test, bad stuff would happened when they don't match.
+  // In case of the buffer has not enough components, adapt the region.
+  if ((bufferedRegion != ioRegion) || (m_FilenameHelper->BandRangeIsSet()
+    && (m_IOComponents < m_BandList.size())))
     {
     if ( m_NumberOfDivisions > 1 || m_UserSpecifiedIORegion)
       {
@@ -744,9 +760,22 @@ ImageFileWriter<TInputImage>
 
       cacheImage = InputImageType::New();
       cacheImage->CopyInformation(input);
+
+      // set number of components at the band range size
+      if (m_FilenameHelper->BandRangeIsSet() && (m_IOComponents < m_BandList.size()))
+        {
+        cacheImage->SetNumberOfComponentsPerPixel(m_BandList.size());
+        }
+
       cacheImage->SetBufferedRegion(ioRegion);
       cacheImage->Allocate();
 
+      // set number of components at the initial size
+      if (m_FilenameHelper->BandRangeIsSet() && (m_IOComponents < m_BandList.size()))
+        {
+        cacheImage->SetNumberOfComponentsPerPixel(m_IOComponents);
+        }
+
       typedef itk::ImageRegionConstIterator<TInputImage> ConstIteratorType;
       typedef itk::ImageRegionIterator<TInputImage>      IteratorType;
 
@@ -777,6 +806,14 @@ ImageFileWriter<TInputImage>
       }
     }
 
+  if (m_FilenameHelper->BandRangeIsSet() && (!m_BandList.empty()))
+  {
+    // Adapt the image size with the region and take into account a potential
+    // remapping of the components. m_BandList is empty if no band range is set
+    m_ImageIO->DoMapBuffer(const_cast< void* >(dataPtr), bufferedRegion.GetNumberOfPixels(), this->m_BandList);
+    m_ImageIO->SetNumberOfComponents(m_BandList.size());
+  }
+
   m_ImageIO->Write(dataPtr);
 
   if (m_WriteGeomFile  || m_FilenameHelper->GetWriteGEOMFile())
diff --git a/Modules/IO/ImageIO/test/CMakeLists.txt b/Modules/IO/ImageIO/test/CMakeLists.txt
index fec74c10db2bd998c7509d4a064e7d63807fa246..d8374f8955993381a7db0634300990f485c57964 100644
--- a/Modules/IO/ImageIO/test/CMakeLists.txt
+++ b/Modules/IO/ImageIO/test/CMakeLists.txt
@@ -74,6 +74,8 @@ otbComplexImageManipulationTest.cxx
 otbImageFileWriterTest.cxx
 otbImageIOFactoryNew.cxx
 otbCompareWritingComplexImage.cxx
+otbImageFileReaderOptBandTest.cxx
+otbImageFileWriterOptBandTest.cxx
 )
 
 add_executable(otbImageIOTestDriver ${OTBImageIOTests})
@@ -788,7 +790,7 @@ set_property(TEST ioTvImageFileReaderFloatHDR2LUM PROPERTY DEPENDS ioTvImageFile
 otb_add_test(NAME ioTvCheckNbBandsPNGIndexee COMMAND otbImageIOTestDriver
   otbPNGIndexedNbBandsTest
   ${INPUTDATA}/sbuv_indexee.png
-  4 )
+  1 )
 
 otb_add_test(NAME ioTvImageFileReaderENVI2PNG COMMAND otbImageIOTestDriver
   --compare-image ${EPSILON_9}   ${INPUTDATA}/cthead1.png
@@ -1301,3 +1303,39 @@ otb_add_test(NAME  ioTvImageFileReaderPNG2ENVI COMMAND otbImageIOTestDriver
         otbImageFileReaderTest
         ${INPUTDATA}/cthead1.png
         ${TEMP}/ioImageFileReaderPNG2ENVI.hdr )
+
+otb_add_test(NAME ioTvImageIOToReaderOptions_OptBandTest COMMAND otbImageIOTestDriver
+  --compare-image ${EPSILON_9} ${BASELINE}/QB_Toulouse_Ortho_XS_OptBand2to4.tif
+                               ${TEMP}/QB_Toulouse_Ortho_XS_OptBand2to4.tif
+  otbImageFileReaderOptBandTest
+  ${INPUTDATA}/QB_Toulouse_Ortho_XS.tif?bands=2:4
+  ${TEMP}/QB_Toulouse_Ortho_XS_OptBand2to4.tif
+  4
+  )
+
+otb_add_test(NAME ioTvImageIOToReaderOptions_OptBandReorgTest COMMAND otbImageIOTestDriver
+  --compare-image ${EPSILON_9} ${BASELINE}/QB_Toulouse_Ortho_XS_OptBandReorg.tif
+                               ${TEMP}/QB_Toulouse_Ortho_XS_OptBandReorg.tif
+  otbImageFileReaderOptBandTest
+  ${INPUTDATA}/QB_Toulouse_Ortho_XS.tif?bands=2,:,-3,2:-1
+  ${TEMP}/QB_Toulouse_Ortho_XS_OptBandReorg.tif
+  4
+  )
+
+otb_add_test(NAME ioTvImageIOToWriterOptions_OptBandTest COMMAND otbImageIOTestDriver
+  --compare-image ${EPSILON_9} ${BASELINE}/QB_Toulouse_Ortho_XS_OptBand2to4.tif
+                               ${TEMP}/QB_Toulouse_Ortho_XS_WriterOptBand2to4.tif
+  otbImageFileWriterOptBandTest
+  ${INPUTDATA}/QB_Toulouse_Ortho_XS.tif
+  ${TEMP}/QB_Toulouse_Ortho_XS_WriterOptBand2to4.tif?bands=2:4
+  4
+  )
+
+otb_add_test(NAME ioTvImageIOToWriterOptions_OptBandReorgTest COMMAND otbImageIOTestDriver
+  --compare-image ${EPSILON_9} ${BASELINE}/QB_Toulouse_Ortho_XS_OptBandReorg.tif
+                               ${TEMP}/QB_Toulouse_Ortho_XS_WriterOptBandReorg.tif
+  otbImageFileWriterOptBandTest
+  ${INPUTDATA}/QB_Toulouse_Ortho_XS.tif
+  ${TEMP}/QB_Toulouse_Ortho_XS_WriterOptBandReorg.tif?bands=2,:,-3,2:-1
+  4
+  )
diff --git a/Modules/IO/ImageIO/test/otbImageFileReaderOptBandTest.cxx b/Modules/IO/ImageIO/test/otbImageFileReaderOptBandTest.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..5f308702b95f9df3c2cea8b3650c0ab85bdab715
--- /dev/null
+++ b/Modules/IO/ImageIO/test/otbImageFileReaderOptBandTest.cxx
@@ -0,0 +1,77 @@
+/*=========================================================================
+
+  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 "otbImage.h"
+#include "itkMacro.h"
+#include <iostream>
+#include <fstream>
+
+#include "otbVectorImage.h"
+#include "otbImageFileReader.h"
+#include "otbImageFileWriter.h"
+#include "otbExtendedFilenameToReaderOptions.h"
+
+int otbImageFileReaderOptBandTest(int itkNotUsed(argc), char* argv[])
+{
+  typedef otb::ExtendedFilenameToReaderOptions FilenameHelperType;
+  FilenameHelperType::Pointer helper = FilenameHelperType::New();
+
+  // Verify the number of parameters in the command line
+  const char * inputFilename  = argv[1];
+  const char * outputFilename = argv[2];
+
+
+
+  helper->SetExtendedFileName(inputFilename);
+  unsigned int nbBands = atoi(argv[3]);
+  std::vector<unsigned int> bandList;
+  bool ret = helper->ResolveBandRange(helper->GetBandRange(),nbBands,bandList);
+  if (ret)
+    {
+    std::cout << "BandList = [";
+    for (unsigned int k=0 ; k<bandList.size() ; k++)
+      {
+      if (k) std::cout << ",";
+      std::cout << bandList[k];
+      }
+    std::cout << "]" << std::endl;
+    }
+  else
+    {
+    std::cout << "Invalid band range for a "<<nbBands<<" bands image"<< std::endl;
+    }
+  
+  
+  typedef unsigned int PixelType;
+  const unsigned int Dimension = 2;
+  
+  typedef otb::VectorImage<PixelType, Dimension> ImageType;
+  
+  typedef otb::ImageFileReader<ImageType> ReaderType; 
+  typedef otb::ImageFileWriter<ImageType> WriterType;
+
+  ReaderType::Pointer reader = ReaderType::New();
+  WriterType::Pointer writer = WriterType::New();
+
+  reader->SetFileName(inputFilename);
+  writer->SetFileName(outputFilename);
+ 
+  writer->SetInput(reader->GetOutput());
+  writer->Update();
+
+  return EXIT_SUCCESS;
+}
diff --git a/Modules/IO/ImageIO/test/otbImageFileWriterOptBandTest.cxx b/Modules/IO/ImageIO/test/otbImageFileWriterOptBandTest.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..66173cd05ab14aa1dce8135ff2300d56a6bbc2e2
--- /dev/null
+++ b/Modules/IO/ImageIO/test/otbImageFileWriterOptBandTest.cxx
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "otbImage.h"
+#include "itkMacro.h"
+#include <iostream>
+#include <fstream>
+
+#include "otbVectorImage.h"
+#include "otbImageFileReader.h"
+#include "otbImageFileWriter.h"
+#include "otbExtendedFilenameToWriterOptions.h"
+
+int otbImageFileWriterOptBandTest(int itkNotUsed(argc), char* argv[])
+{
+  typedef otb::ExtendedFilenameToWriterOptions FilenameHelperType;
+  FilenameHelperType::Pointer helper = FilenameHelperType::New();
+
+  // Verify the number of parameters in the command line
+  const char * inputFilename  = argv[1];
+  const char * outputFilename = argv[2];
+
+  helper->SetExtendedFileName(outputFilename);
+  unsigned int nbBands = atoi(argv[3]);
+  std::vector<unsigned int> bandList;
+  bool ret = helper->ResolveBandRange(helper->GetBandRange(),nbBands,bandList);
+  if (ret)
+    {
+    std::cout << "BandList = [";
+    for (unsigned int k=0 ; k<bandList.size() ; k++)
+      {
+      if (k) std::cout << ",";
+      std::cout << bandList[k];
+      }
+    std::cout << "]" << std::endl;
+    }
+  else
+    {
+    std::cout << "Invalid band range for a "<<nbBands<<" bands image"<< std::endl;
+    }
+
+  typedef unsigned int PixelType;
+  const unsigned int Dimension = 2;
+
+  typedef otb::VectorImage<PixelType, Dimension> ImageType;
+
+  typedef otb::ImageFileReader<ImageType> ReaderType; 
+  typedef otb::ImageFileWriter<ImageType> WriterType;
+
+  ReaderType::Pointer reader = ReaderType::New();
+  WriterType::Pointer writer = WriterType::New();
+
+  reader->SetFileName(inputFilename);
+  writer->SetFileName(outputFilename);
+ 
+  writer->SetInput(reader->GetOutput());
+  writer->Update();
+
+  return EXIT_SUCCESS;
+}
diff --git a/Modules/IO/ImageIO/test/otbImageIOTestDriver.cxx b/Modules/IO/ImageIO/test/otbImageIOTestDriver.cxx
index 7621e85c445ee20c7d79d4342535182635dc549d..fb2aa583aa73653ece1ffb9f523ae6caaec71d84 100644
--- a/Modules/IO/ImageIO/test/otbImageIOTestDriver.cxx
+++ b/Modules/IO/ImageIO/test/otbImageIOTestDriver.cxx
@@ -152,4 +152,6 @@ void RegisterTests()
   REGISTER_TEST(otbImageFileWriterTest);
   REGISTER_TEST(otbImageIOFactoryNew);
   REGISTER_TEST(otbCompareWritingComplexImageTest);
+  REGISTER_TEST(otbImageFileReaderOptBandTest);
+  REGISTER_TEST(otbImageFileWriterOptBandTest);
 }
diff --git a/Modules/Learning/Supervised/test/otbSupervisedTestDriver.cxx b/Modules/Learning/Supervised/test/otbSupervisedTestDriver.cxx
index 5d0ccbe17c48695077cefec52e2114ca9e0f659b..3ff4103c3405530dc02e89e81bd220529f2aa822 100644
--- a/Modules/Learning/Supervised/test/otbSupervisedTestDriver.cxx
+++ b/Modules/Learning/Supervised/test/otbSupervisedTestDriver.cxx
@@ -19,7 +19,10 @@
  */
 
 #include "otbTestMain.h"
+
+#ifdef OTB_USE_OPENCV
 #include "otb_opencv_api.h"
+#endif
 
 void RegisterTests()
 {
diff --git a/Modules/Remote/otb-bv.remote.cmake b/Modules/Remote/otb-bv.remote.cmake
index 7249a0443e46dc7e04d0c2fb0aeaa745133f3e5a..4816ae226460fae6d54424daa86edad2e8888ddd 100644
--- a/Modules/Remote/otb-bv.remote.cmake
+++ b/Modules/Remote/otb-bv.remote.cmake
@@ -25,5 +25,5 @@ A more detailed description can be found on the project website:
 http://tully.ups-tlse.fr/jordi/otb-bv
 "
   GIT_REPOSITORY http://tully.ups-tlse.fr/jordi/otb-bv.git
-  GIT_TAG d13a3b3febe61c3c67777eac8261e07a6257a519
+  GIT_TAG master
 )
diff --git a/Modules/Remote/phenotb.remote.cmake b/Modules/Remote/phenotb.remote.cmake
index 4ffba060cf56583604e568cfbe92664b85d0ecff..d76b4f1cc1b30d88f22aab7c036e413eeaf4c068 100644
--- a/Modules/Remote/phenotb.remote.cmake
+++ b/Modules/Remote/phenotb.remote.cmake
@@ -27,5 +27,5 @@ A more detailed description can be found on the project website:
 http://tully.ups-tlse.fr/jordi/phenotb
 "
   GIT_REPOSITORY http://tully.ups-tlse.fr/jordi/phenotb.git
-  GIT_TAG 17d69b1bc1f23041dafe265e320b46ffb20229b6
+  GIT_TAG master
 )
diff --git a/Modules/Remote/temporal-gapfilling.remote.cmake b/Modules/Remote/temporal-gapfilling.remote.cmake
index 0ef5cd29ba0af30cda3e5de29d57efe219c8608b..5570ceee08dc704ed1ea8e5897db93d88e03d711 100644
--- a/Modules/Remote/temporal-gapfilling.remote.cmake
+++ b/Modules/Remote/temporal-gapfilling.remote.cmake
@@ -26,5 +26,5 @@ A more detailed description can be found on the project website:
 http://tully.ups-tlse.fr/jordi/temporalgapfilling
 "
   GIT_REPOSITORY http://tully.ups-tlse.fr/jordi/temporalgapfilling.git
-  GIT_TAG 14c56cb73250861d8694effeba934cebde09424c
+  GIT_TAG master
 )
diff --git a/Modules/ThirdParty/OssimPlugins/src/ossim/ossimSentinel1Model.cpp b/Modules/ThirdParty/OssimPlugins/src/ossim/ossimSentinel1Model.cpp
index 71fcec0deef817ca1dac61661422e4b0d98577fb..10ecc6080a69d32de8e12cd55f94b140ab8d50d1 100644
--- a/Modules/ThirdParty/OssimPlugins/src/ossim/ossimSentinel1Model.cpp
+++ b/Modules/ThirdParty/OssimPlugins/src/ossim/ossimSentinel1Model.cpp
@@ -298,11 +298,13 @@ namespace ossimplugins
          All these cases should not go slient on error message. It must be FATAL errors.
 
          */
-
-         ossimNotify(ossimNotifyLevel_FATAL)
-            << MODULE
-            << " !xmlFileName.exists() || !this->readProduct(xmlFileName) fails \n";
-         return false;
+      if(traceDebug())
+        {
+        ossimNotify(ossimNotifyLevel_DEBUG)
+          << MODULE
+          << " !xmlFileName.exists() || !this->readProduct(xmlFileName) fails \n";
+        }
+        return false;
       }
       else
       {
diff --git a/Modules/Visualization/Monteverdi/src/main.cxx b/Modules/Visualization/Monteverdi/src/main.cxx
index feccb84f5e3451e40784f083693ea57d608cb1cc..e44dbb8459d0b239c8bc5c5283d5c41a6412d7ef 100644
--- a/Modules/Visualization/Monteverdi/src/main.cxx
+++ b/Modules/Visualization/Monteverdi/src/main.cxx
@@ -111,7 +111,7 @@ main( int argc, char* argv[] )
 	  QCoreApplication::translate(
 	    PROJECT_NAME,
 	    "Usage: %1 [-h|--help] [-a|--applications] [<filename>...]\n"
-	    "  -1, --no-glsl      force OpenGL 1.x compatible rendering."
+	    "  -n, --no-glsl      force OpenGL 1.x compatible rendering."
 	    "  -a, --applications load OTB-applications from OTB_APPLICATIONS_PATH."
 	    "  -h, --help         display this help message.\n"
 	  )
@@ -130,7 +130,7 @@ main( int argc, char* argv[] )
       it = args.erase( it );
       }
 
-    else if(it->compare( "-1" )==0 ||
+    else if(it->compare( "-n" )==0 ||
 	    it->compare( "--no-glsl" )==0 )
       {
       flags.forceNoGLSL = true;
diff --git a/Modules/Visualization/Monteverdi/src/mvdMainWindow.cxx b/Modules/Visualization/Monteverdi/src/mvdMainWindow.cxx
index fada47696774b0d1bc6faaef8213a0abf146808a..84f7085b12557fd24f2d79a448ea5799071c3294 100644
--- a/Modules/Visualization/Monteverdi/src/mvdMainWindow.cxx
+++ b/Modules/Visualization/Monteverdi/src/mvdMainWindow.cxx
@@ -2515,8 +2515,8 @@ MainWindow
 
     text =
       tr( "(%1 %2 ; %3 %4 ; %5)" )
-      .arg( wgs84[ 0 ]>=0.0 ? "N" : "S" ).arg( fabs( wgs84[ 1 ] ) )
-      .arg( wgs84[ 1 ]>=0.0 ? "E" : "W" ).arg( fabs( wgs84[ 0 ] ) )
+      .arg( wgs84[ 1 ]>=0.0 ? "N" : "S" ).arg( fabs( wgs84[ 1 ] ) )
+      .arg( wgs84[ 0 ]>=0.0 ? "E" : "W" ).arg( fabs( wgs84[ 0 ] ) )
       .arg( alt );
     }
 
diff --git a/Modules/Visualization/MonteverdiGui/include/mvdShaderWidget.h b/Modules/Visualization/MonteverdiGui/include/mvdShaderWidget.h
index 971b0d941de3662f2a52dad377bcf9ee4ffbd4ad..4d1b55c63ca5c478c313f5f497fd3c67c37f77d9 100644
--- a/Modules/Visualization/MonteverdiGui/include/mvdShaderWidget.h
+++ b/Modules/Visualization/MonteverdiGui/include/mvdShaderWidget.h
@@ -146,6 +146,14 @@ private:
   /** */
   void virtual_SetSettings( ImageSettings * ) ITK_OVERRIDE;
 
+  /**
+   * Set the ComboBox effects item for the corresponding image settings.
+   * This will append or remove effects (lut) depending if settings
+   * correspond to grayscale image or not.
+   * \param imageSettings Settings of the current image.
+   */
+  void UpdateComboBoxEffectItems(ImageSettings *imageSettings) ;
+
 //
 // Private attributes.
 private:
diff --git a/Modules/Visualization/MonteverdiGui/include/mvdStatusBarWidget.h b/Modules/Visualization/MonteverdiGui/include/mvdStatusBarWidget.h
index 714a100883da50fc0dad696e9b29a8ea4739e8b7..6ff51de45d94a3a60c3d4a89471e3d4d28f6ccd1 100644
--- a/Modules/Visualization/MonteverdiGui/include/mvdStatusBarWidget.h
+++ b/Modules/Visualization/MonteverdiGui/include/mvdStatusBarWidget.h
@@ -161,6 +161,11 @@ private:
    */
   Ui::StatusBarWidget * m_UI;
 
+  /**
+   * \brief Change the scale when scaleLineEdit is pressed or editing is finished with change.
+   */
+  void ChangeScale();
+
   /*-[ PRIVATE SLOTS SECTION ]-----------------------------------------------*/
 
 //
@@ -175,6 +180,9 @@ private slots:
   /**
    */
   void on_pixelIndexLineEdit_returnPressed();
+  /**
+   */
+  void on_scaleLineEdit_returnPressed();
 };
 
 } // end namespace 'mvd'
diff --git a/Modules/Visualization/MonteverdiGui/src/mvdShaderWidget.cxx b/Modules/Visualization/MonteverdiGui/src/mvdShaderWidget.cxx
index 42dc9facf3e506fedb1d20cc17bb168e275aa476..36680eeaaeb232125c4fca2ff2c8c1c377176758 100644
--- a/Modules/Visualization/MonteverdiGui/src/mvdShaderWidget.cxx
+++ b/Modules/Visualization/MonteverdiGui/src/mvdShaderWidget.cxx
@@ -83,7 +83,7 @@ ShaderWidget
   m_UI->valueLineEdit->setValidator(
     new QDoubleValidator( m_UI->valueLineEdit )
   );
-} 
+}
 
 /*******************************************************************************/
 ShaderWidget
@@ -128,18 +128,18 @@ void ShaderWidget
 {
   assert( qApp!=NULL );
 
-  int index =
-    m_UI->effectComboBox->findText(
-      qApp->translate( "mvd", EFFECT_NAMES[ effect ] )
-    );
+  QString effectName = qApp->translate( "mvd", EFFECT_NAMES[ effect ] );
+  int index = m_UI->effectComboBox->findText(effectName);
 
   if( visible )
     {
     if( index<0 )
-      m_UI->effectComboBox->addItem( qApp->translate( "mvd", EFFECT_NAMES[ effect ] ) );
+      m_UI->effectComboBox->addItem( effectName );
     }
   else if( index>=0 )
+    {
     m_UI->effectComboBox->removeItem( index );
+    }
 }
 
 /*******************************************************************************/
@@ -159,67 +159,45 @@ ShaderWidget
     {
     assert( qApp!=NULL );
 
-    for( int i=0; i<m_UI->effectComboBox->count(); ++i )
-      if( m_UI->effectComboBox->itemText( i )
-	  .compare(
-	    qApp->translate( "mvd",
-			     EFFECT_NAMES[ settings->GetEffect() ] ) )==0 )
-        {
-        m_UI->effectComboBox->setCurrentIndex( i );
-
-        break;
-        }
-
-    m_UI->sizeSpinBox->setValue( settings->GetSize() );
+    const char *imageEffect = EFFECT_NAMES[settings->GetEffect()];
+    QString tradEffect = qApp->translate( "mvd", imageEffect );
 
-    char const * const text = settings->GetValueName();
+    // Add or remove items from the comboBox
+    UpdateComboBoxEffectItems(settings);
 
-    if( text==NULL )
-      {
-      m_UI->valueLabel->setVisible( false );
-      m_UI->valueLabel->setText( QString() );
-      }
-    else
+    for( int i = 0; i < m_UI->effectComboBox->count(); ++i )
       {
-      m_UI->valueLabel->setVisible( true );
-      m_UI->valueLabel->setText( QString( text ).append( ":" ) );
+      QString comboBoxEffect = m_UI->effectComboBox->itemText( i );
+      if( QString::compare( comboBoxEffect, tradEffect ) == 0 )
+        {
+        // This change will emit currentIndexChanged SIGNAL
+        // and then call on_effectComboBox_currentIndexChanged
+        QString oldText = m_UI->effectComboBox->currentText();
+        if(m_UI->effectComboBox->currentIndex() != i)
+          {
+          m_UI->effectComboBox->setCurrentIndex( i );
+          }
+        break;
+        }
       }
-
-    m_UI->valueLineEdit->setVisible( text!=NULL );
-    m_UI->valueLineEdit->setText(
-      settings->HasValue()
-      ? QString::number( settings->GetValue(), 'g', std::numeric_limits< double >::digits10 ) // ToQString( settings->GetValue() )
-      : QString()
-    );
-    m_UI->valueLineEdit->setCursorPosition( 0 );
     }
-
-  VectorImageSettings * vis = dynamic_cast<VectorImageSettings*>(settings);
-
-  if(vis!=NULL)
-    {
-    GrayscaleActivated(vis->IsGrayscaleActivated());
-    }
-  
-}
+  }
 
 /*******************************************************************************/
 /* SLOTS                                                                       */
 /*******************************************************************************/
-void
-ShaderWidget
-::on_effectComboBox_currentIndexChanged( const QString & text )
+void ShaderWidget::on_effectComboBox_currentIndexChanged(const QString &text)
 {
   if( !HasSettings() )
     return;
 
-  assert( qApp!=NULL );
+  assert( qApp != NULL );
 
-  for( int i=0; i<EFFECT_COUNT; ++i )
-    if( QString::compare( text, qApp->translate( "mvd", EFFECT_NAMES[ i ] ) )==0 )
+  for( int i = 0; i < EFFECT_COUNT; ++i )
+    if( QString::compare( text, qApp->translate( "mvd", EFFECT_NAMES[i] ) ) == 0 )
       {
-      ImageSettings * settings = GetSettings();
-      assert( settings!=NULL );
+      ImageSettings *settings = GetSettings();
+      assert( settings != NULL );
 
       settings->SetEffect( static_cast< Effect >( i ) );
 
@@ -228,29 +206,25 @@ ShaderWidget
 
       m_UI->sizeSpinBox->setValue( settings->GetSize() );
 
-      char const * const textName = settings->GetValueName();
+      char const *const textName = settings->GetValueName();
 
-      if( textName==NULL )
-	{
-	m_UI->valueLabel->setVisible( false );
-	m_UI->valueLabel->setText( QString() );
-	}
+      if( textName == NULL )
+        {
+        m_UI->valueLabel->setVisible( false );
+        m_UI->valueLabel->setText( QString() );
+        }
       else
-	{
-	m_UI->valueLabel->setVisible( true );
-	m_UI->valueLabel->setText( QString( textName ).append( ":" ) );
-	}
-
-      m_UI->valueLineEdit->setVisible( textName!=NULL );
-      m_UI->valueLineEdit->setText(
-	settings->HasValue()
-	? ToQString( settings->GetValue() )
-	: QString()
-      );
+        {
+        m_UI->valueLabel->setVisible( true );
+        m_UI->valueLabel->setText( QString( textName ).append( ":" ) );
+        }
+
+      m_UI->valueLineEdit->setVisible( textName != NULL );
+      m_UI->valueLineEdit->setText( settings->HasValue() ? ToQString( settings->GetValue() ) : QString() );
 
       emit SettingsChanged();
 
-      return;
+      break;
       }
 }
 
@@ -294,7 +268,7 @@ ShaderWidget
 
 void ShaderWidget
 ::GrayscaleActivated(bool status)
-{  
+{
   SetEffectVisible(EFFECT_LUT_JET,status);
   SetEffectVisible(EFFECT_LUT_LOCAL_JET,status);
   SetEffectVisible(EFFECT_LUT_HOT,status);
@@ -308,4 +282,21 @@ void ShaderWidget
   SetEffectVisible(EFFECT_SPECTRAL_ANGLE,!status);
 }
 
+
+void ShaderWidget::UpdateComboBoxEffectItems(ImageSettings *imageSettings)
+{
+  if( imageSettings != NULL )
+    {
+    VectorImageSettings *vis = dynamic_cast<VectorImageSettings *>(imageSettings);
+    if( vis != NULL )
+      {
+      // Add Gray shader effect to the ComboBox if the image is grayscale.
+      // Update items in the comboBox but do not fire signal each time an item is removed.
+      bool oldState = m_UI->effectComboBox->blockSignals( true );
+      GrayscaleActivated( vis->IsGrayscaleActivated() );
+      m_UI->effectComboBox->blockSignals( oldState );
+      }
+    }
+}
+
 } // end namespace 'mvd'
diff --git a/Modules/Visualization/MonteverdiGui/src/mvdStatusBarWidget.cxx b/Modules/Visualization/MonteverdiGui/src/mvdStatusBarWidget.cxx
index 358bc123cf9450e7ceb5fa881fc5317342a6dae1..6091f79e077190b7a0d00e963f3643b6bd0eb11e 100644
--- a/Modules/Visualization/MonteverdiGui/src/mvdStatusBarWidget.cxx
+++ b/Modules/Visualization/MonteverdiGui/src/mvdStatusBarWidget.cxx
@@ -217,9 +217,26 @@ StatusBarWidget
 }
 
 /*****************************************************************************/
+void
+StatusBarWidget
+::on_scaleLineEdit_returnPressed()
+{
+  ChangeScale();
+}
+
 void
 StatusBarWidget
 ::on_scaleLineEdit_editingFinished()
+{
+  if(m_UI->scaleLineEdit->isModified())
+    {
+      ChangeScale();
+    }
+}
+
+void
+StatusBarWidget
+::ChangeScale()
 {
   //
   // Cancel if scale text is empty.
diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperChoiceParameter.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperChoiceParameter.h
index da4d4537b7a30d7bcc9e227416878d15aa2e3dad..b376323214a31e02f6846b80d2aed4c7b126e6e3 100644
--- a/Modules/Wrappers/ApplicationEngine/include/otbWrapperChoiceParameter.h
+++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperChoiceParameter.h
@@ -90,13 +90,14 @@ public:
 
   bool HasValue() const ITK_OVERRIDE
   {
-    // a choice parameter always has a value
-    return true;
+    return !m_ChoiceList.empty();
   }
 
   void ClearValue() ITK_OVERRIDE
   {
-    // nothing to do : a choice parameter always has a value
+    // Same as constructor init value
+    // Note that this may be invalid if HasValue() == false
+    m_CurrentChoice = 0;
   }
 
 protected:
diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx
index c2d772d151c62a42a8ee3ba9a7e09a496518c66d..16f2a28637401ce72a634f4e4074a9f0bdf3bee9 100644
--- a/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx
+++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx
@@ -1015,19 +1015,26 @@ std::string Application::GetParameterString(std::string parameter)
   Parameter* param = GetParameterByKey(parameter);
 
   if (dynamic_cast<ChoiceParameter*>(param))
-    {
+  {
     ChoiceParameter* paramDown = dynamic_cast<ChoiceParameter*>(param);
-    std::string choiceKey = paramDown->GetChoiceKey( paramDown->GetValue() );
-    size_t lastPointPos = choiceKey.find_last_of('.');
-    if(lastPointPos != std::string::npos)
+    if (paramDown->HasValue())
+    {
+      std::string choiceKey = paramDown->GetChoiceKey( paramDown->GetValue() );
+      size_t lastPointPos = choiceKey.find_last_of('.');
+      if(lastPointPos != std::string::npos)
       {
-      ret = choiceKey.substr(lastPointPos);
-        }
-    else
+        ret = choiceKey.substr(lastPointPos);
+      }
+      else
       {
-      ret = choiceKey;
+        ret = choiceKey;
       }
     }
+    else
+    {
+        ret = "";
+    }
+  }
   else if (dynamic_cast<ListViewParameter*>(param))
     {
     ListViewParameter* paramDown = dynamic_cast<ListViewParameter*>(param);