diff --git a/Modules/Applications/AppFusion/app/otbBundleToPerfectSensor.cxx b/Modules/Applications/AppFusion/app/otbBundleToPerfectSensor.cxx
index 2f31cd6344d4c8a76db4436b4303e1aed42af98d..62741969214b647891ac0bc47f282906080cf86b 100644
--- a/Modules/Applications/AppFusion/app/otbBundleToPerfectSensor.cxx
+++ b/Modules/Applications/AppFusion/app/otbBundleToPerfectSensor.cxx
@@ -16,25 +16,14 @@
 
  =========================================================================*/
 #include "otbWrapperApplicationFactory.h"
+#include "otbWrapperCompositeApplication.h"
 
-#include "otbMultiToMonoChannelExtractROI.h"
-#include "otbGenericRSResampleImageFilter.h"
-#include "otbGridResampleImageFilter.h"
-#include "otbImportGeoInformationImageFilter.h"
-#include "otbBCOInterpolateImageFunction.h"
-#include "otbSimpleRcsPanSharpeningFusionImageFilter.h"
-#include "itkFixedArray.h"
-
-// Elevation handler
-#include "otbWrapperElevationParametersHandler.h"
-
-#include "otbPleiadesPToXSAffineTransformCalculator.h"
 
 namespace otb
 {
 namespace Wrapper
 {
-class BundleToPerfectSensor : public Application
+class BundleToPerfectSensor : public CompositeApplication
 {
 public:
   /** Standard class typedefs. */
@@ -46,7 +35,7 @@ public:
   /** Standard macro */
   itkNewMacro(Self);
 
-  itkTypeMacro(BundleToPerfectSensor, otb::Application);
+  itkTypeMacro(BundleToPerfectSensor, otb::Wrapper::CompositeApplication);
 
 private:
 
@@ -65,38 +54,27 @@ private:
     AddDocTag(Tags::Geometry);
     AddDocTag(Tags::Pansharpening);
 
-    AddParameter(ParameterType_InputImage,   "inp",   "Input PAN Image");
-    SetParameterDescription("inp"," Input panchromatic image.");
-    AddParameter(ParameterType_InputImage,   "inxs",  "Input XS Image");
-    SetParameterDescription("inxs"," Input XS image.");
-
-    AddParameter(ParameterType_OutputImage,  "out",   "Output image");
-    SetParameterDescription("out"," Output image.");
-
-    // Elevation
-    ElevationParametersHandler::AddElevationParameters(this, "elev");
-
-    // Superposition mode
-    AddParameter(ParameterType_Choice,"mode", "Mode");
-    SetParameterDescription("mode", "Superimposition mode");
-    
-    AddChoice("mode.default", "Default mode");
-    SetParameterDescription("mode.default", "Default superimposition mode : "
-      "uses any projection reference or sensor model found in the images");
-    
-    AddChoice("mode.phr", "Pleiades mode");
-    SetParameterDescription("mode.phr", "Pleiades superimposition mode, "
-      "designed for the case of a P+XS bundle in SENSOR geometry. It uses"
-      " a simple transform on the XS image : a scaling and a residual "
-      "translation.");
+    ClearApplications();
+    AddApplication("Superimpose", "superimpose", "Reproject XS onto Pan");
+    AddApplication("Pansharpening", "pansharp", "Fusion of XS and Pan");
+
+    ShareParameter("inp","superimpose.inr","Input PAN Image","Input panchromatic image.");
+    ShareParameter("inxs","superimpose.inm","Input XS Image","Input XS image.");
+    ShareParameter("out","pansharp.out");
+    ShareParameter("elev","superimpose.elev");
+    ShareParameter("mode","superimpose.mode");
+    ShareParameter("lms","superimpose.lms",
+      "Spacing of the deformation field",
+      "Spacing of the deformation field. Default is 10 times the PAN image spacing.");
+    ShareParameter("fv","superimpose.fv");
+    ShareParameter("ram","superimpose.ram");
+
+    Connect("pansharp.inp","superimpose.inr");
+    Connect("pansharp.ram","superimpose.ram");
+
+    GetInternalApplication("superimpose")->SetParameterString("interpolator","bco");
+    GetInternalApplication("pansharp")->SetParameterString("method","rcs");
     
-    AddParameter(ParameterType_Float,        "lms",   "Spacing of the deformation field");
-    SetParameterDescription("lms"," Spacing of the deformation field. Default is 10 times the PAN image spacing.");
-
-    AddRAMParameter();
-
-    MandatoryOff("lms");
-
     // Doc example parameter settings
     SetDocExampleParameterValue("inp", "QB_Toulouse_Ortho_PAN.tif");
     SetDocExampleParameterValue("inxs", "QB_Toulouse_Ortho_XS.tif");
@@ -106,150 +84,19 @@ private:
 
   void DoUpdateParameters() ITK_OVERRIDE
   {
-    if(!HasUserValue("mode") && HasValue("inp") && HasValue("inxs") && otb::PleiadesPToXSAffineTransformCalculator::CanCompute(GetParameterImage("inp"),GetParameterImage("inxs")))
-      {
-      otbAppLogWARNING("Forcing PHR mode with PHR data. You need to add \"-mode default\" to force the default mode with PHR images.");
-      SetParameterString("mode","phr");
-      }
+    UpdateInternalParameters("superimpose");
   }
 
   void DoExecute() ITK_OVERRIDE
   {
-    FloatVectorImageType* panchroV = GetParameterImage("inp");
-    FloatVectorImageType* xs = GetParameterImage("inxs");
-
-    if ( panchroV->GetNumberOfComponentsPerPixel() != 1 )
-      {
-      itkExceptionMacro(<< "The panchromatic image must be a single channel image")
-      }
-
-    // Transform the PAN image to otb::Image
-    typedef otb::Image<FloatVectorImageType::InternalPixelType> InternalImageType;
-    typedef otb::MultiToMonoChannelExtractROI<float,float> ExtractFilterType;
-
-    ExtractFilterType::Pointer channelSelect = ExtractFilterType::New();
-    m_Ref.push_back(channelSelect.GetPointer());
-    channelSelect->SetChannel(1);
-    channelSelect->SetInput(panchroV);
-    channelSelect->UpdateOutputInformation();
-    InternalImageType::Pointer panchro = channelSelect->GetOutput();
-
-    typedef otb::BCOInterpolateImageFunction<FloatVectorImageType> InterpolatorType;
-    typedef otb::GenericRSResampleImageFilter<FloatVectorImageType, FloatVectorImageType>  ResamplerType;
-    typedef otb::GridResampleImageFilter<FloatVectorImageType, FloatVectorImageType>  BasicResamplerType;
-    typedef otb::ImportGeoInformationImageFilter<FloatVectorImageType,InternalImageType> ImportGeoInformationFilterType;
-    typedef otb::SimpleRcsPanSharpeningFusionImageFilter<InternalImageType, FloatVectorImageType, FloatVectorImageType> FusionFilterType;
+    ExecuteInternal("superimpose");
 
-    // Resample filter
-    ResamplerType::Pointer    resampler = ResamplerType::New();
-    m_Ref.push_back(resampler.GetPointer());
-    
-    BasicResamplerType::Pointer basicResampler = BasicResamplerType::New();
-    m_Ref.push_back(basicResampler.GetPointer());
-
-    ImportGeoInformationFilterType::Pointer geoImport = ImportGeoInformationFilterType::New();
-    m_Ref.push_back(geoImport.GetPointer());
-
-    InterpolatorType::Pointer interpolator = InterpolatorType::New();
-    resampler->SetInterpolator(interpolator);
-    basicResampler->SetInterpolator(interpolator);
-
-    // Fusion filter
-    FusionFilterType::Pointer  fusionFilter = FusionFilterType::New();
-    m_Ref.push_back(fusionFilter.GetPointer());
-    fusionFilter->SetPanInput(panchro);
-    
-    // Setup the DEM Handler
-    otb::Wrapper::ElevationParametersHandler::SetupDEMHandlerFromElevationParameters(this,"elev");
-
-    // Set up output image information
-    FloatVectorImageType::SpacingType spacing = panchro->GetSpacing();
-    FloatVectorImageType::IndexType   start = panchro->GetLargestPossibleRegion().GetIndex();
-    FloatVectorImageType::SizeType    size = panchro->GetLargestPossibleRegion().GetSize();
-    FloatVectorImageType::PointType   origin = panchro->GetOrigin();
-
-    FloatVectorImageType::PixelType defaultValue;
-    itk::NumericTraits<FloatVectorImageType::PixelType>::SetLength(defaultValue, xs->GetNumberOfComponentsPerPixel());
+    GetInternalApplication("pansharp")->SetParameterInputImage("inxs",
+      GetInternalApplication("superimpose")->GetParameterOutputImage("out"));
 
-    if(GetParameterString("mode") == "default")
-      {
-      otbAppLogINFO("Using the default mode");
-      if(IsParameterEnabled("lms") && HasValue("lms"))
-        {
-        double defScalarSpacing = GetParameterFloat("lms");
-        otbAppLogINFO(<< "Generating coarse deformation field (spacing="<<defScalarSpacing<<")" << std::endl);
-        FloatVectorImageType::SpacingType defSpacing;
-        
-        defSpacing[0] = defScalarSpacing;
-        defSpacing[1] = defScalarSpacing;
-        
-        resampler->SetDisplacementFieldSpacing(defSpacing);
-        }
-      else
-        {
-        FloatVectorImageType::SpacingType defSpacing;
-        defSpacing[0]=10*spacing[0];
-        defSpacing[1]=10*spacing[1];
-        resampler->SetDisplacementFieldSpacing(defSpacing);
-        }
-      
-      resampler->SetInput(xs);
-      resampler->SetOutputOrigin(origin);
-      resampler->SetOutputSpacing(spacing);
-      resampler->SetOutputSize(size);
-      resampler->SetOutputStartIndex(start);
-      resampler->SetOutputKeywordList(panchro->GetImageKeywordlist());
-      resampler->SetOutputProjectionRef(panchro->GetProjectionRef());
-      resampler->SetEdgePaddingValue(defaultValue);
-      fusionFilter->SetXsInput(resampler->GetOutput());
-      }
-    else if(GetParameterString("mode")=="phr")
-      {
-      otbAppLogINFO("Using the PHR mode");
-      
-      otb::PleiadesPToXSAffineTransformCalculator::TransformType::OffsetType offset
-        = otb::PleiadesPToXSAffineTransformCalculator::ComputeOffset(GetParameterImage("inp"),
-                                                                     GetParameterImage("inxs"));
-
-      origin+=offset;
-      origin[0]=origin[0]/4;
-      origin[1]=origin[1]/4;
-      
-      basicResampler->SetOutputOrigin(origin);
-      basicResampler->SetInput(xs);
-      basicResampler->SetOutputOrigin(origin);
-
-      FloatVectorImageType::SpacingType xsSpacing = GetParameterImage("inxs")->GetSpacing();
-      xsSpacing*=0.25;
-      
-      basicResampler->SetOutputSpacing(xsSpacing);
-      basicResampler->SetOutputSize(size);
-      basicResampler->SetOutputStartIndex(start);
-      basicResampler->SetEdgePaddingValue(defaultValue);
-
-      geoImport->SetInput(basicResampler->GetOutput());
-      geoImport->SetSource(panchro);
-
-      fusionFilter->SetXsInput(geoImport->GetOutput());
-
-      // Set the profRef & Keywordlist from Pan into the resampled XS image
-      basicResampler->UpdateOutputInformation();
-      itk::MetaDataDictionary& dict = basicResampler->GetOutput()->GetMetaDataDictionary();
-      itk::EncapsulateMetaData<std::string>(dict, MetaDataKey::ProjectionRefKey,
-                                            panchro->GetProjectionRef());
-      itk::EncapsulateMetaData<ImageKeywordlist>(dict, MetaDataKey::OSSIMKeywordlistKey,
-                                                 panchro->GetImageKeywordlist());
-      }
-    else
-      {
-      otbAppLogWARNING("Unknown mode");
-      }
-    
-    SetParameterOutputImage("out", fusionFilter->GetOutput());
+    ExecuteInternal("pansharp");
   }
 
-  std::vector<itk::ProcessObject::Pointer> m_Ref;
-
 };
 
 
diff --git a/Modules/Applications/AppFusion/otb-module.cmake b/Modules/Applications/AppFusion/otb-module.cmake
index 54fe75ccac06953703f04292cf71acadd3a4939c..e09047b0b4b7372b86c007a6b70532d6b6f4e691 100644
--- a/Modules/Applications/AppFusion/otb-module.cmake
+++ b/Modules/Applications/AppFusion/otb-module.cmake
@@ -10,6 +10,7 @@ otb_module(OTBAppFusion
     OTBInterpolation
 
   TEST_DEPENDS
+    OTBAppProjection
     OTBTestKernel
     OTBCommandLine
 
diff --git a/Modules/Applications/AppProjection/app/otbSuperimpose.cxx b/Modules/Applications/AppProjection/app/otbSuperimpose.cxx
index a2fc5e2549333380e9b2cca755f2cacf3f43eeea..ac37bdc6e7ce080d7ec95303d3f52e7d02e69be8 100644
--- a/Modules/Applications/AppProjection/app/otbSuperimpose.cxx
+++ b/Modules/Applications/AppProjection/app/otbSuperimpose.cxx
@@ -104,6 +104,7 @@ private:
     AddParameter(ParameterType_Float,        "lms",   "Spacing of the deformation field");
     SetParameterDescription("lms","Generate a coarser deformation field with the given spacing");
     SetDefaultParameterFloat("lms", 4.);
+    DisableParameter("lms");
     MandatoryOff("lms");
 
     AddParameter(ParameterType_Float, "fv", "Fill Value");
@@ -219,20 +220,24 @@ private:
 
     if(GetParameterString("mode")=="default")
       {
+      FloatVectorImageType::SpacingType defSpacing;
       if(IsParameterEnabled("lms"))
         {
         float defScalarSpacing = vcl_abs(GetParameterFloat("lms"));
         otbAppLogDEBUG("Generating coarse deformation field (spacing="<<defScalarSpacing<<")");
-        FloatVectorImageType::SpacingType defSpacing;
 
         defSpacing[0] = defScalarSpacing;
         defSpacing[1] = defScalarSpacing;
 
         if (spacing[0]<0.0) defSpacing[0] *= -1.0;
         if (spacing[1]<0.0) defSpacing[1] *= -1.0;
-
-        m_Resampler->SetDisplacementFieldSpacing(defSpacing);
         }
+      else
+        {
+        defSpacing[0]=10*spacing[0];
+        defSpacing[1]=10*spacing[1];
+        }
+      m_Resampler->SetDisplacementFieldSpacing(defSpacing);
       
       // Setup transform through projRef and Keywordlist
       m_Resampler->SetInputKeywordList(movingImage->GetImageKeywordlist());
diff --git a/Modules/Applications/AppProjection/test/CMakeLists.txt b/Modules/Applications/AppProjection/test/CMakeLists.txt
index bff04845b68deeb44c0924471b7d10066d522319..81eea8e987ac15269fb0677ce0b80dedadfc892f 100644
--- a/Modules/Applications/AppProjection/test/CMakeLists.txt
+++ b/Modules/Applications/AppProjection/test/CMakeLists.txt
@@ -320,6 +320,7 @@ otb_test_application(NAME apTvPrSuperimpose
                              -inm ${INPUTDATA}/QB_Toulouse_Ortho_XS_ROI_170x230.tif
                              -elev.dem ${INPUTDATA}/DEM/srtm_directory
                              -out ${TEMP}/apTvPrSuperimpose.tif int16
+                             -lms 4.0
                      VALID  --compare-image ${EPSILON_7}
                         ${BASELINE}/apTvPrSuperimpose.tif
                         ${TEMP}/apTvPrSuperimpose.tif)