From b8a71a74602d363bc4ca69b3489eeaaeba45c858 Mon Sep 17 00:00:00 2001
From: Julien Malik <julien.malik@c-s.fr>
Date: Fri, 16 Sep 2011 18:56:33 +0200
Subject: [PATCH] ENH: port BundleToPerfectSensor to the new framework

---
 .../Projections/otbBundleToPerfectSensor.cxx  | 199 +++++++++---------
 1 file changed, 99 insertions(+), 100 deletions(-)

diff --git a/Applications/Projections/otbBundleToPerfectSensor.cxx b/Applications/Projections/otbBundleToPerfectSensor.cxx
index 5baa4e687b..a9a63c5985 100644
--- a/Applications/Projections/otbBundleToPerfectSensor.cxx
+++ b/Applications/Projections/otbBundleToPerfectSensor.cxx
@@ -15,81 +15,102 @@
  PURPOSE.  See the above copyright notices for more information.
 
  =========================================================================*/
-#include "otbBundleToPerfectSensor.h"
+#include "otbWrapperApplication.h"
+#include "otbWrapperApplicationFactory.h"
 
-#include <iostream>
-
-#include "otbImageFileReader.h"
-#include "otbStreamingImageFileWriter.h"
-#include "otbImage.h"
-#include "otbVectorImage.h"
+#include "itkVectorIndexSelectionCastImageFilter.h"
 #include "otbGenericRSResampleImageFilter.h"
 #include "otbBCOInterpolateImageFunction.h"
-
-#include "itkExceptionObject.h"
-
-#include "otbStandardWriterWatcher.h"
 #include "otbSimpleRcsPanSharpeningFusionImageFilter.h"
 #include "itkPixelBuilder.h"
-
 #include "itkFixedArray.h"
 
 namespace otb
 {
-int BundleToPerfectSensor::Describe(ApplicationDescriptor* descriptor)
+namespace Wrapper
 {
-  descriptor->SetName("BundleToSensorModel");
-  descriptor->SetDescription("Using available image metadata to determine the sensor model, computes a cartographic projection of the image");
-
-  descriptor->AddOption("InputPanchro","The input panchromatic image","inP", 1, true, otb::ApplicationDescriptor::InputImage);
-  descriptor->AddOption("InputXS","The input multi-spectral image","inXS", 1, true, otb::ApplicationDescriptor::InputImage);
-  descriptor->AddOption("DEMDirectory","Directory were to find the DEM tiles","dem", 1, false, otb::ApplicationDescriptor::DirectoryName);
-  descriptor->AddOption("LocMapSpacing","Generate a coarser deformation field with the given spacing.","lmSpacing", 1, false, otb::ApplicationDescriptor::Real);
-  descriptor->AddOption("AvailableMemory","Set the maximum of available memory for the pipeline execution in mega bytes (optional, 256 by default)","ram", 1, false, otb::ApplicationDescriptor::Integer);
 
-  descriptor->AddOutputImage();
 
-  return EXIT_SUCCESS;
-}
-
-int BundleToPerfectSensor::Execute(otb::ApplicationOptionsResult* parseResult)
+class BundleToPerfectSensor : public Application
 {
-  try
-    {
-
-    typedef unsigned short int PixelType;
+public:
+  /** Standard class typedefs. */
+  typedef BundleToPerfectSensor         Self;
+  typedef Application                   Superclass;
+  typedef itk::SmartPointer<Self>       Pointer;
+  typedef itk::SmartPointer<const Self> ConstPointer;
+
+  /** Standard macro */
+  itkNewMacro(Self);
+
+  itkTypeMacro(BundleToPerfectSensor, otb::Application);
+
+private:
+
+  BundleToPerfectSensor()
+  {
+    SetName("BundleToPerfectSensor");
+    SetDescription("Perform P+XS pansharpening");
+  }
+
+  virtual ~BundleToPerfectSensor()
+  {
+  }
+
+  void DoCreateParameters()
+  {
+    AddParameter(ParameterType_InputImage,   "inp",   "Input PAN Image");
+    AddParameter(ParameterType_InputImage,   "inxs",  "Input XS Image");
+    AddParameter(ParameterType_Directory,    "dem",   "DEM directory");
+    AddParameter(ParameterType_Float,        "lms",   "Spacing of the deformation field");
+    AddParameter(ParameterType_OutputImage,  "out",   "Output image");
+
+    MandatoryOff("lms");
+    MandatoryOff("dem");
+  }
+  
+  void DoUpdateParameters()
+  {
+    // Nothing to do here : all parameters are independent
+  }
+
+  void DoExecute()
+  {
+    FloatVectorImageType* panchroV = GetParameterImage("inp");
+    if ( panchroV->GetNumberOfComponentsPerPixel() != 1 )
+      {
+      itkExceptionMacro(<< "The panchromatic image must be a single channel image")
+      }
 
-    typedef otb::VectorImage<PixelType, 2>                XsImageType;
-    typedef otb::Image<PixelType, 2>                       PanImageType;
-    typedef otb::ImageFileReader<XsImageType>             XsReaderType;
-    typedef otb::ImageFileReader<PanImageType>            PanReaderType;
-    typedef otb::StreamingImageFileWriter<XsImageType>    WriterType;
-    typedef otb::BCOInterpolateImageFunction<XsImageType> InterpolatorType;
+    // Transform the PAN image to otb::Image
+    typedef otb::Image<FloatVectorImageType::InternalPixelType> FloatImageType;
+    typedef itk::VectorIndexSelectionCastImageFilter<FloatVectorImageType, FloatImageType> VectorIndexSelectionCastImageFilterType;
 
-    typedef otb::GenericRSResampleImageFilter<XsImageType, XsImageType>  ResamplerType;
+    VectorIndexSelectionCastImageFilterType::Pointer channelSelect = VectorIndexSelectionCastImageFilterType::New();
+    m_Ref.push_back(channelSelect.GetPointer());
+    channelSelect->SetIndex(0);
+    channelSelect->SetInput(panchroV);
+    channelSelect->UpdateOutputInformation();
+    FloatImageType::Pointer panchro = channelSelect->GetOutput();
 
-    typedef otb::SimpleRcsPanSharpeningFusionImageFilter<PanImageType, XsImageType, XsImageType> FusionFilterType;
 
-    typedef itk::ExtractImageFilter<XsImageType, XsImageType> ExtractFilterType;
+    FloatVectorImageType* xs = GetParameterImage("inxs");
 
-    // Read input images information
-    PanReaderType::Pointer preader= PanReaderType::New();
-    preader->SetFileName(parseResult->GetParameterString("InputPanchro"));
-    preader->GenerateOutputInformation();
+    typedef otb::BCOInterpolateImageFunction<FloatVectorImageType> InterpolatorType;
+    typedef otb::GenericRSResampleImageFilter<FloatVectorImageType, FloatVectorImageType>  ResamplerType;
+    typedef otb::SimpleRcsPanSharpeningFusionImageFilter<FloatImageType, FloatVectorImageType, FloatVectorImageType> FusionFilterType;
 
-    XsReaderType::Pointer xsreader= XsReaderType::New();
-    xsreader->SetFileName(parseResult->GetParameterString("InputXS"));
-    xsreader->GenerateOutputInformation();
-    
     // Resample filter
     ResamplerType::Pointer    resampler = ResamplerType::New();
+    m_Ref.push_back(resampler.GetPointer());
+
     InterpolatorType::Pointer interpolator = InterpolatorType::New();
     resampler->SetInterpolator(interpolator);
     
     // Configure DEM directory
-    if(parseResult->IsOptionPresent("DEMDirectory"))
+    if(IsParameterEnabled("dem") && HasValue("dem"))
       {
-      resampler->SetDEMDirectory(parseResult->GetParameterString("DEMDirectory", 0));
+      resampler->SetDEMDirectory( GetParameterString("dem") );
       }
     else
       {
@@ -100,16 +121,16 @@ int BundleToPerfectSensor::Execute(otb::ApplicationOptionsResult* parseResult)
       }
 
     // Set up output image informations
-    XsImageType::SpacingType spacing = preader->GetOutput()->GetSpacing();
-    XsImageType::IndexType start = preader->GetOutput()->GetLargestPossibleRegion().GetIndex();
-    XsImageType::SizeType size = preader->GetOutput()->GetLargestPossibleRegion().GetSize();
-    XsImageType::PointType origin = preader->GetOutput()->GetOrigin();
+    FloatVectorImageType::SpacingType spacing = panchro->GetSpacing();
+    FloatVectorImageType::IndexType   start = panchro->GetLargestPossibleRegion().GetIndex();
+    FloatVectorImageType::SizeType    size = panchro->GetLargestPossibleRegion().GetSize();
+    FloatVectorImageType::PointType   origin = panchro->GetOrigin();
 
-    if(parseResult->IsOptionPresent("LocMapSpacing"))
+    if(IsParameterEnabled("lms") && HasValue("lms"))
       {
-      double defScalarSpacing = parseResult->GetParameterFloat("LocMapSpacing");
-      std::cout<<"Generating coarse deformation field (spacing="<<defScalarSpacing<<")"<<std::endl;
-      XsImageType::SpacingType defSpacing;
+      double defScalarSpacing = GetParameterFloat("lms");
+      std::cout << "Generating coarse deformation field (spacing="<<defScalarSpacing<<")" << std::endl;
+      FloatVectorImageType::SpacingType defSpacing;
 
       defSpacing[0] = defScalarSpacing;
       defSpacing[1] = defScalarSpacing;
@@ -118,66 +139,44 @@ int BundleToPerfectSensor::Execute(otb::ApplicationOptionsResult* parseResult)
       }
     else
       {
-      XsImageType::SpacingType defSpacing;
+      FloatVectorImageType::SpacingType defSpacing;
       defSpacing[0]=10*spacing[0];
       defSpacing[1]=10*spacing[1];
       resampler->SetDeformationFieldSpacing(defSpacing);
       }
     
-    XsImageType::PixelType defaultValue;
-    itk::PixelBuilder<XsImageType::PixelType>::Zero(defaultValue,
-                                                    xsreader->GetOutput()->GetNumberOfComponentsPerPixel());
+    FloatVectorImageType::PixelType defaultValue;
+    itk::PixelBuilder<FloatVectorImageType::PixelType>::Zero(defaultValue,
+                                                             xs->GetNumberOfComponentsPerPixel());
 
-    resampler->SetInput(xsreader->GetOutput());
+    resampler->SetInput(xs);
     resampler->SetOutputOrigin(origin);
     resampler->SetOutputSpacing(spacing);
     resampler->SetOutputSize(size);
     resampler->SetOutputStartIndex(start);
-    resampler->SetOutputKeywordList(preader->GetOutput()->GetImageKeywordlist());
-    resampler->SetOutputProjectionRef(preader->GetOutput()->GetProjectionRef());
+    resampler->SetOutputKeywordList(panchro->GetImageKeywordlist());
+    resampler->SetOutputProjectionRef(panchro->GetProjectionRef());
     resampler->SetEdgePaddingValue(defaultValue);
 
+    resampler->UpdateOutputInformation();
+    FloatVectorImageType::Pointer xsResample = resampler->GetOutput();
+
     FusionFilterType::Pointer  fusionFilter = FusionFilterType::New();
-    fusionFilter->SetPanInput(preader->GetOutput());
+    m_Ref.push_back(fusionFilter.GetPointer());
+
+    fusionFilter->SetPanInput(panchro);
     fusionFilter->SetXsInput(resampler->GetOutput());
-    fusionFilter->GetOutput()->UpdateOutputInformation();
-    
-    WriterType::Pointer writer = WriterType::New();
-    writer->SetFileName(parseResult->GetOutputImage());
-    writer->SetInput(fusionFilter->GetOutput());
-    writer->SetWriteGeomFile(true);
+    fusionFilter->UpdateOutputInformation();
     
-    unsigned int ram = 256;
-    if (parseResult->IsOptionPresent("AvailableMemory"))
-      {
-      ram = parseResult->GetParameterUInt("AvailableMemory");
-      }
+    SetParameterOutputImage("out", fusionFilter->GetOutput());
+  }
 
-    const double bias = 1.27;
-    writer->SetAutomaticTiledStreaming(ram, bias);
-
-    otb::StandardWriterWatcher w4(writer, resampler,"Perfect sensor fusion");
-    writer->Update();
-    }
-  catch ( itk::ExceptionObject & err )
-    {
-    std::cout << "Exception itk::ExceptionObject raised !" << std::endl;
-    std::cout << err << std::endl;
-    return EXIT_FAILURE;
-    }
-  catch ( std::bad_alloc & err )
-    {
-    std::cout << "Exception bad_alloc : "<<(char*)err.what()<< std::endl;
-    return EXIT_FAILURE;
-    }
-  catch ( ... )
-    {
-    std::cout << "Unknown exception raised !" << std::endl;
-    return EXIT_FAILURE;
-    }
-  return EXIT_SUCCESS;
+  std::vector<itk::ProcessObject::Pointer> m_Ref;
 
+};
 
-}
 
 }
+}
+
+OTB_APPLICATION_EXPORT(otb::Wrapper::BundleToPerfectSensor)
-- 
GitLab