From 67585c0a51ea3e3b5717e39852f8bdb9d4a51f9d Mon Sep 17 00:00:00 2001
From: Jonathan Guinet <jonathan.guinet@c-s.fr>
Date: Mon, 16 May 2011 15:43:43 +0200
Subject: [PATCH] REFAC class otb class inheritance and method overloading to
 clean code.

---
 .../otbLabelObjectOpeningMuParserFilter.h     |   2 +
 .../otbLabelObjectOpeningMuParserFilter.txx   |  67 ++++--
 .../otbRelabelComponentImageFilter.h          | 168 +------------
 .../otbRelabelComponentImageFilter.txx        | 222 +-----------------
 ...bBandsStatisticsAttributesLabelMapFilter.h |   2 +
 ...andsStatisticsAttributesLabelMapFilter.txx |  70 ++++--
 Code/OBIA/otbLabelMapToLabelImageFilter.txx   |  28 +--
 Code/OBIA/otbShapeAttributesLabelMapFilter.h  |   3 +
 .../OBIA/otbShapeAttributesLabelMapFilter.txx |  63 +++--
 9 files changed, 152 insertions(+), 473 deletions(-)

diff --git a/Code/BasicFilters/otbLabelObjectOpeningMuParserFilter.h b/Code/BasicFilters/otbLabelObjectOpeningMuParserFilter.h
index b34c95a2f4..29fb1a19d4 100644
--- a/Code/BasicFilters/otbLabelObjectOpeningMuParserFilter.h
+++ b/Code/BasicFilters/otbLabelObjectOpeningMuParserFilter.h
@@ -113,6 +113,8 @@ void DisplayVar() const;
 /** return list of Mu Parser varialbes and address**/
 const std::map<std::string, double*>& GetVar() const;
 
+virtual void AllocateOutputs();
+
 void GenerateInputRequestedRegion();
 
 void EnlargeOutputRequestedRegion(itk::DataObject *){};
diff --git a/Code/BasicFilters/otbLabelObjectOpeningMuParserFilter.txx b/Code/BasicFilters/otbLabelObjectOpeningMuParserFilter.txx
index dbc8c0d77d..ada358c96f 100644
--- a/Code/BasicFilters/otbLabelObjectOpeningMuParserFilter.txx
+++ b/Code/BasicFilters/otbLabelObjectOpeningMuParserFilter.txx
@@ -109,36 +109,53 @@ void LabelObjectOpeningMuParserFilter<TImage, TFunction>::SetAttributes(std::vec
   this->m_Functor.SetAttributes(shapeAttributes, statAttributes, nbOfBands);
 }
 
+/** Get the reduced attribute set */
 template  < class TImage, class TFunction>
-void LabelObjectOpeningMuParserFilter<TImage, TFunction>::GenerateInputRequestedRegion()
-{
-  ImagePointer input = const_cast<ImageType *>(this->GetInput());
+void LabelObjectOpeningMuParserFilter<TImage, TFunction>
+::AllocateOutputs()
+ {
+ // if told to run in place and the types support it,
+  if( this->GetInPlace() && this->CanRunInPlace() )
+    {
+    // Graft this first input to the output.  Later, we'll need to
+    // remove the input's hold on the bulk data.
+    //
+   ImagePointer inputAsOutput = dynamic_cast<TImage *>(const_cast<TImage *>(this->GetInput()));
 
-      if ( !input )
-       { return; }
+    if( inputAsOutput )
+      {
+
+      this->GraftOutput( inputAsOutput );
+      this->GetOutput()->SetLargestPossibleRegion(this->GetOutput()->GetLargestPossibleRegion());
+      this->GetOutput()->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());
+      this->GetOutput()->SetBufferedRegion(this->GetOutput()->GetBufferedRegion());
+
+      }
 
-  for (unsigned int idx = 0; idx < this->GetNumberOfInputs(); ++idx)
+    // If there are more than one outputs, allocate the remaining outputs
+    for (unsigned int i=1; i < this->GetNumberOfOutputs(); i++)
       {
-       ImagePointer input = const_cast<ImageType *>(this->GetInput(idx));
-      if (!input.IsNull())
-        {
-        input->SetRequestedRegionToLargestPossibleRegion();
-        // Check whether the input is an image of the appropriate
-        // dimension (use ProcessObject's version of the GetInput()
-        // method since it returns the input as a pointer to a
-        // DataObject as opposed to the subclass version which
-        // static_casts the input to an TInputImage).
-
-        // Use the function object RegionCopier to copy the output region
-        // to the input.  The default region copier has default implementations
-        // to handle the cases where the input and output are the same
-        // dimension, the input a higher dimension than the output, and the
-        // input a lower dimension than the output.
-        InputImageRegionType inputRegion;
-        this->CallCopyOutputRegionToInputRegion(inputRegion, this->GetOutput()->GetRequestedRegion());
-        input->SetRequestedRegion( inputRegion );
-        }
+      ImagePointer outputPtr;
+
+      outputPtr = this->GetOutput(i);
+      outputPtr->SetBufferedRegion(outputPtr->GetRequestedRegion());
+      outputPtr->Allocate();
       }
+    }
+  else
+    {
+    Superclass::AllocateOutputs();
+    // copy the content of the input image to the output image (will be done by ImageSource AllocateOutputs Method)
+    // would never occur : inputasoutput condition is always true, since output and input type is TImage for
+    // LabelObjectOpeningMuParserFilter class
+    }
+}
+
+
+template  < class TImage, class TFunction>
+void LabelObjectOpeningMuParserFilter<TImage, TFunction>::GenerateInputRequestedRegion()
+{
+ itk::ImageToImageFilter<TImage,TImage>::GenerateInputRequestedRegion();
 }
 
 
diff --git a/Code/BasicFilters/otbRelabelComponentImageFilter.h b/Code/BasicFilters/otbRelabelComponentImageFilter.h
index 21ae2eb688..6807e8c4c1 100644
--- a/Code/BasicFilters/otbRelabelComponentImageFilter.h
+++ b/Code/BasicFilters/otbRelabelComponentImageFilter.h
@@ -17,7 +17,7 @@
 #ifndef __otbRelabelComponentImageFilter_h
 #define __otbRelabelComponentImageFilter_h
 
-#include "itkInPlaceImageFilter.h"
+#include "itkRelabelComponentImageFilter.h"
 #include "itkImage.h"
 #include <vector>
 
@@ -72,14 +72,14 @@ namespace otb
 
 template <class TInputImage, class TOutputImage>
 class ITK_EXPORT RelabelComponentImageFilter :
-    public itk::InPlaceImageFilter< TInputImage, TOutputImage >
+    public itk::RelabelComponentImageFilter< TInputImage, TOutputImage >
 {
 public:
   /**
    * Standard "Self" & Superclass typedef.
    */
   typedef RelabelComponentImageFilter                     Self;
-  typedef itk::InPlaceImageFilter< TInputImage, TOutputImage > Superclass;
+  typedef itk::RelabelComponentImageFilter < TInputImage, TOutputImage > Superclass;
 
   /**
    * Types from the Superclass
@@ -124,176 +124,24 @@ public:
    */
   itkNewMacro(Self);
 
-  /** Type used as identifier for the different component lables. */
+  /** Type used as identifier for the different component labels. */
   typedef unsigned long int    LabelType;
 
   /** Type used to count number of pixels in objects. */
   typedef unsigned long int    ObjectSizeType;
 
-  /** Get the number of objects in the image. This information is only
-   * valid after the filter has executed. */
-  itkGetConstMacro(NumberOfObjects, LabelType);
-  
-  /** Get the original number of objects in the image before small
-   * objects were discarded. This information is only valid after
-   * the filter has executed. If the caller has not specified a
-   * minimum object size, OriginalNumberOfObjects is the same as
-   * NumberOfObjects. */
-  itkGetConstMacro(OriginalNumberOfObjects, LabelType);
-
-  /** Get/Set the number of objects enumerated and described when the
-   * filter is printed. */
-  itkSetMacro(NumberOfObjectsToPrint, LabelType);
-  itkGetConstReferenceMacro(NumberOfObjectsToPrint, LabelType);
-
-  /** Set the minimum size in pixels for an object. All objects
-   * smaller than this size will be discarded and will not appear
-   * in the output label map. NumberOfObjects will count only the
-   * objects whose pixel counts are greater than or equal to the
-   * minimum size. Call GetOriginalNumberOfObjects to find out how
-   * many objects were present in the original label map. */
-  itkSetMacro(MinimumObjectSize, ObjectSizeType);
-
-  /** Get the caller-defined minimum size of an object in pixels.
-   * If the caller has not set the minimum, 0 will be returned,
-   * which is to be interpreted as meaning that no minimum exists,
-   * and all objects in the original label map will be passed
-   * through to the output. */
-  itkGetConstMacro(MinimumObjectSize, ObjectSizeType);
-   
-  /** Get the size of each object in pixels. This information is only
-   * valid after the filter has executed.  Size of the background is
-   * not calculated.  Size of object #1 is
-   * GetSizeOfObjectsInPixels()[0]. Size of object #2 is
-   * GetSizeOfObjectsInPixels()[1]. Etc. */
-  const std::vector<ObjectSizeType>& GetSizeOfObjectsInPixels() const
-    { return m_SizeOfObjectsInPixels; }
-
-  /** Get the size of each object in physical space (in units of pixel
-   * size). This information is only valid after the filter has
-   * executed. Size of the background is not calculated.  Size of
-   * object #1 is GetSizeOfObjectsInPhysicalUnits()[0]. Size of object
-   * #2 is GetSizeOfObjectsInPhysicalUnits()[1]. Etc. */
-  const std::vector<float>& GetSizeOfObjectsInPhysicalUnits() const
-    { return m_SizeOfObjectsInPhysicalUnits; }
-
-  /** Get the size of a particular object in pixels. This information is only
-   * valid after the filter has executed.  Size of the background
-   * (object #0) is not calculated.  */
-  ObjectSizeType GetSizeOfObjectInPixels( LabelType obj ) const
-    {
-    if (obj > 0 && obj <= m_NumberOfObjects)
-      {
-      return m_SizeOfObjectsInPixels[obj-1];
-      }
-    else
-      {
-      return 0;
-      }
-    }
-  
-  /** Get the size of a particular object in physical space (in units of pixel
-   * size). This information is only valid after the filter has
-   * executed. Size of the background (object #0) is not calculated.  */
-  float GetSizeOfObjectInPhysicalUnits( LabelType obj ) const
-    {
-    if (obj > 0 && obj <= m_NumberOfObjects)
-      {
-      return m_SizeOfObjectsInPhysicalUnits[obj-1];
-      }
-    else
-      {
-      return 0;
-      }
-    }
-
-#ifdef ITK_USE_CONCEPT_CHECKING
-  /** Begin concept checking */
-  itkConceptMacro(InputEqualityComparableCheck,
-    (itk::Concept::EqualityComparable<InputPixelType>));
-  itkConceptMacro(UnsignedLongConvertibleToInputCheck,
-    (itk::Concept::Convertible<LabelType, InputPixelType>));
-  itkConceptMacro(OutputLongConvertibleToUnsignedLongCheck,
-    (itk::Concept::Convertible<OutputPixelType, LabelType>));
-  itkConceptMacro(InputConvertibleToOutputCheck,
-    (itk::Concept::Convertible<InputPixelType, OutputPixelType>));
-  itkConceptMacro(SameDimensionCheck,
-    (itk::Concept::SameDimension<InputImageDimension, ImageDimension>));
-  /** End concept checking */
-#endif
-
 protected:
 
-  RelabelComponentImageFilter()
-    : m_NumberOfObjects(0), m_NumberOfObjectsToPrint(10),
-    m_OriginalNumberOfObjects(0), m_MinimumObjectSize(0)
-    { this->InPlaceOff(); }
+  RelabelComponentImageFilter();
   virtual ~RelabelComponentImageFilter() {}
-  RelabelComponentImageFilter(const Self&) {}
 
-  /**
-   * Standard pipeline method.
-   */
-  void GenerateData();
-
-  /** RelabelComponentImageFilter needs the entire input. Therefore
-   * it must provide an implementation GenerateInputRequestedRegion().
-   * \sa ProcessObject::GenerateInputRequestedRegion(). */
   void GenerateInputRequestedRegion();
 
-  /**
-    * Initialize parameters.
-    */
-   void Init();
-
-  /** Standard printself method */
-  void PrintSelf(std::ostream& os, itk::Indent indent) const;
-
-  struct RelabelComponentObjectType
-    {
-    LabelType       m_ObjectNumber;
-    ObjectSizeType  m_SizeInPixels;
-    float           m_SizeInPhysicalUnits;
-    };
-
-  // put the function objects here for sorting in descending order
-  class RelabelComponentSizeInPixelsComparator
-    {
-    public:
-      bool operator()(const RelabelComponentObjectType&a,
-                      const RelabelComponentObjectType &b)
-      {
-      if (a.m_SizeInPixels > b.m_SizeInPixels)
-        {
-        return true;
-        }
-      else if (a.m_SizeInPixels < b.m_SizeInPixels)
-        {
-        return false;
-        }
-      // size in pixels and physical units are the same, sort based on
-      // original object number
-      else if (a.m_ObjectNumber < b.m_ObjectNumber)
-        {
-        return true;
-        }
-      else
-        {
-        return false;
-        }
-      }
-  };
-  
+  void EnlargeOutputRequestedRegion(itk::DataObject *){};
 
 private:
-
-  LabelType       m_NumberOfObjects;
-  LabelType       m_NumberOfObjectsToPrint;
-  LabelType       m_OriginalNumberOfObjects;
-  ObjectSizeType  m_MinimumObjectSize;
-
-  std::vector<ObjectSizeType> m_SizeOfObjectsInPixels;
-  std::vector<float>          m_SizeOfObjectsInPhysicalUnits;
+  RelabelComponentImageFilter(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
 
 };
   
diff --git a/Code/BasicFilters/otbRelabelComponentImageFilter.txx b/Code/BasicFilters/otbRelabelComponentImageFilter.txx
index d2a81849e7..6d27b1193d 100644
--- a/Code/BasicFilters/otbRelabelComponentImageFilter.txx
+++ b/Code/BasicFilters/otbRelabelComponentImageFilter.txx
@@ -28,232 +28,22 @@
 namespace otb
 {
 
-template< class TInputImage, class TOutputImage >
-void
-RelabelComponentImageFilter< TInputImage, TOutputImage >
-::GenerateInputRequestedRegion()
+template <class TInputImage, class TOutputImage>
+RelabelComponentImageFilter<TInputImage, TOutputImage>
+::RelabelComponentImageFilter()
 {
-
-  itk::ImageToImageFilter<TInputImage, TOutputImage>::GenerateInputRequestedRegion();
 }
 
 
 template< class TInputImage, class TOutputImage >
 void
 RelabelComponentImageFilter< TInputImage, TOutputImage >
-::GenerateData()
+::GenerateInputRequestedRegion()
 {
-  unsigned long i;
-  
-  // Use a map to keep track of the size of each object.  Object
-  // number -> ObjectType (which has Object number and the two sizes)
-  typedef itk::hash_map<LabelType, RelabelComponentObjectType> MapType;
-  MapType sizeMap;
-  typename MapType::iterator mapIt;
-  typedef typename MapType::value_type MapValueType;
-
-  // Get the input and the output
-  typename TInputImage::ConstPointer input = this->GetInput();
-  typename TOutputImage::Pointer output = this->GetOutput();
-
-  // Setup a progress reporter.  We have 2 stages to the algorithm so
-  // use the total number of pixels accessed. We walk the entire input
-  // in the first pass, then walk just the output requested region in
-  // the second pass.
-  itk::ProgressReporter progress(this, 0,
-                            input->GetRequestedRegion().GetNumberOfPixels() +
-                            output->GetRequestedRegion().GetNumberOfPixels());
-
-
-  // Calculate the size of pixel
-  float physicalPixelSize = 1.0;
-  for (i=0; i < TInputImage::ImageDimension; ++i)
-    {
-    physicalPixelSize *= input->GetSpacing()[i];
-    }
-
-  RelabelComponentObjectType initialSize;
-  initialSize.m_SizeInPixels = 1;
-  initialSize.m_SizeInPhysicalUnits = physicalPixelSize;
-
-  // First pass: walk the entire input image and determine what
-  // labels are used and the number of pixels used in each label.
-  //
-
-  // walk the input
-  itk::ImageRegionConstIterator<InputImageType> it(input, input->GetRequestedRegion());
-  it.GoToBegin();
-
-  while (!it.IsAtEnd())
-    {
-    // Get the input pixel value
-    const LabelType inputValue = static_cast< LabelType>( it.Get() );
-
-    // if the input pixel is not the background
-    if (inputValue != itk::NumericTraits<LabelType>::Zero)
-      {
-      // Does this label already exist
-      mapIt = sizeMap.find( inputValue );
-      if ( mapIt == sizeMap.end() )
-        {
-        // label is not currently in the map
-        initialSize.m_ObjectNumber = inputValue;
-        sizeMap.insert( MapValueType( inputValue, initialSize ) );
-        }
-      else
-        {
-        // label is already in the map, update the values
-        (*mapIt).second.m_SizeInPixels++;
-        (*mapIt).second.m_SizeInPhysicalUnits += physicalPixelSize;
-        }
-      }
-
-    // increment the iterators
-    ++it;
-    progress.CompletedPixel();
-    }
-
-  // Now we need to reorder the labels. Use the m_ObjectSortingOrder
-  // to determine how to sort the objects. Define a map for converting
-  // input labels to output labels.
-  //
-  typedef std::vector<RelabelComponentObjectType> VectorType;
-  VectorType sizeVector;
-  typename VectorType::iterator vit;
-
-  typedef std::map< LabelType, LabelType > RelabelMapType;
-  RelabelMapType relabelMap;
-
-  // copy the original object map to a vector so we can sort it
-  for (mapIt = sizeMap.begin(); mapIt != sizeMap.end(); ++mapIt)
-    {
-    sizeVector.push_back( (*mapIt).second );
-    }
-
-  // sort the objects by size and define the map to use to relabel the image
-  std::sort(sizeVector.begin(), sizeVector.end(), RelabelComponentSizeInPixelsComparator() );
-
-  // create a lookup table to map the input label to the output label.
-  // cache the object sizes for later access by the user
-  m_NumberOfObjects = sizeVector.size();
-  m_OriginalNumberOfObjects = sizeVector.size();
-  m_SizeOfObjectsInPixels.clear();
-  m_SizeOfObjectsInPixels.resize(m_NumberOfObjects);
-  m_SizeOfObjectsInPhysicalUnits.clear();
-  m_SizeOfObjectsInPhysicalUnits.resize(m_NumberOfObjects);
-  int NumberOfObjectsRemoved = 0;
-  for (i=0, vit = sizeVector.begin(); vit != sizeVector.end(); ++vit, ++i)
-    {
-
-    // if we find an object smaller than the minimum size, we
-    // terminate the loop.
-    if (m_MinimumObjectSize > 0 && (*vit).m_SizeInPixels < m_MinimumObjectSize)
-      {
-      // map small objects to the background
-      NumberOfObjectsRemoved++;
-      relabelMap.insert(RelabelMapType::value_type( (*vit).m_ObjectNumber, 0));
-      }
-    else
-      {
-      // map for input labels to output labels (Note we use i+1 in the
-      // map since index 0 is the background)
-      relabelMap.insert(RelabelMapType::value_type( (*vit).m_ObjectNumber, i+1));
-      
-      // cache object sizes for later access by the user
-      m_SizeOfObjectsInPixels[i] = (*vit).m_SizeInPixels;
-      m_SizeOfObjectsInPhysicalUnits[i] = (*vit).m_SizeInPhysicalUnits;
-      }
-
-    }
-
-  // update number of objects and resize cache vectors if we have removed small objects
-  m_NumberOfObjects -= NumberOfObjectsRemoved;
-  if (NumberOfObjectsRemoved > 0)
-    {
-    m_SizeOfObjectsInPixels.resize(m_NumberOfObjects);
-    m_SizeOfObjectsInPhysicalUnits.resize(m_NumberOfObjects);
-    }
-
-  // Second pass: walk just the output requested region and relabel
-  // the necessary pixels.
-  //
-
-  // Allocate the output
-  this->AllocateOutputs();
-
-  // Remap the labels.  Note we only walk the region of the output
-  // that was requested.  This may be a subset of the input image.
-  OutputPixelType outputValue;
-  itk::ImageRegionIterator<OutputImageType> oit;
-  oit = itk::ImageRegionIterator<OutputImageType>(output,
-                                             output->GetRequestedRegion());
-  it = itk::ImageRegionConstIterator<InputImageType>(input,
-                                                output->GetRequestedRegion());
-
-  it.GoToBegin();
-  oit.GoToBegin();
-  while ( !oit.IsAtEnd() )
-    {
-    const LabelType inputValue = static_cast< LabelType>( it.Get() );
-    
-    if (inputValue != itk::NumericTraits<LabelType>::Zero)
-      {
-
-      // lookup the mapped label
-      outputValue = static_cast<OutputPixelType>(relabelMap[inputValue]);
-      oit.Set( outputValue );
-      }
-    else
-      {
-      oit.Set( inputValue );
-      }
-
-    // increment the iterators
-    ++it;
-    ++oit;
-    progress.CompletedPixel();
-    }
+  itk::ImageToImageFilter<TInputImage,TOutputImage>::GenerateInputRequestedRegion();
 }
 
 
-template< class TInputImage, class TOutputImage >
-void
-RelabelComponentImageFilter< TInputImage, TOutputImage >
-::PrintSelf(std::ostream& os, itk::Indent indent) const
-{
-  Superclass::PrintSelf(os, indent);
-
-  os << indent << "NumberOfObjects: " << m_NumberOfObjects << std::endl;
-  os << indent << "OriginalNumberOfObjects: " << m_OriginalNumberOfObjects << std::endl;
-  os << indent << "NumberOfObjectsToPrint: "
-     << m_NumberOfObjectsToPrint << std::endl;
-  os << indent << "MinimumObjectSizez: " << m_MinimumObjectSize << std::endl;
-
-  std::vector<ObjectSizeType>::const_iterator it;
-  std::vector<float>::const_iterator fit;
-  LabelType i;
-
-  // limit the number of objects to print
-  LabelType numPrint = m_NumberOfObjectsToPrint;
-  if (numPrint > m_SizeOfObjectsInPixels.size())
-    {
-    numPrint = m_SizeOfObjectsInPixels.size();
-    }
-
-
-  for (i=0, it = m_SizeOfObjectsInPixels.begin(),
-         fit = m_SizeOfObjectsInPhysicalUnits.begin();
-       i < numPrint; ++it, ++fit, ++i)
-    {
-    os << indent << "Object #" << i+1 << ": " << *it << " pixels, "
-       << *fit << " physical units" << std::endl;
-    }
-  if (numPrint < m_SizeOfObjectsInPixels.size())
-    {
-    os << indent << "..." << std::endl;
-    }
-}
-
-} // end namespace itk
+} // end namespace otb
 
 #endif
diff --git a/Code/OBIA/otbBandsStatisticsAttributesLabelMapFilter.h b/Code/OBIA/otbBandsStatisticsAttributesLabelMapFilter.h
index 501e230e82..19bd205a21 100644
--- a/Code/OBIA/otbBandsStatisticsAttributesLabelMapFilter.h
+++ b/Code/OBIA/otbBandsStatisticsAttributesLabelMapFilter.h
@@ -186,6 +186,8 @@ protected:
   /** Destructor */
   ~BandsStatisticsAttributesLabelMapFilter() {}
 
+  virtual void AllocateOutputs();
+
   void GenerateInputRequestedRegion();
 
   void EnlargeOutputRequestedRegion(itk::DataObject *){};
diff --git a/Code/OBIA/otbBandsStatisticsAttributesLabelMapFilter.txx b/Code/OBIA/otbBandsStatisticsAttributesLabelMapFilter.txx
index 64a34e798f..e6bd417c7e 100644
--- a/Code/OBIA/otbBandsStatisticsAttributesLabelMapFilter.txx
+++ b/Code/OBIA/otbBandsStatisticsAttributesLabelMapFilter.txx
@@ -210,34 +210,58 @@ BandsStatisticsAttributesLabelMapFilter<TImage, TFeatureImage>
   return this->GetFunctor().GetReducedAttributeSet();
 }
 
+
 template <class TImage, class TFeatureImage>
 void
 BandsStatisticsAttributesLabelMapFilter<TImage, TFeatureImage>
-::GenerateInputRequestedRegion()
-{
+::AllocateOutputs()
+ {
+ // if told to run in place and the types support it,
+  if( this->GetInPlace() && this->CanRunInPlace() )
+    {
+    // Graft this first input to the output.  Later, we'll need to
+    // remove the input's hold on the bulk data.
+    //
+   ImagePointer inputAsOutput = dynamic_cast<TImage *>(const_cast<TImage *>(this->GetInput()));
 
-  for (unsigned int idx = 0; idx < this->GetNumberOfInputs(); ++idx)
+    if( inputAsOutput )
       {
-       ImagePointer input = const_cast<ImageType *>(this->GetInput(idx));
-      if (!input.IsNull())
-        {
-        input->SetRequestedRegionToLargestPossibleRegion();
-        // Check whether the input is an image of the appropriate
-        // dimension (use ProcessObject's version of the GetInput()
-        // method since it returns the input as a pointer to a
-        // DataObject as opposed to the subclass version which
-        // static_casts the input to an TInputImage).
-
-        // Use the function object RegionCopier to copy the output region
-        // to the input.  The default region copier has default implementations
-        // to handle the cases where the input and output are the same
-        // dimension, the input a higher dimension than the output, and the
-        // input a lower dimension than the output.
-        InputImageRegionType inputRegion;
-        this->CallCopyOutputRegionToInputRegion(inputRegion, this->GetOutput()->GetRequestedRegion());
-        input->SetRequestedRegion( inputRegion );
-        }
+
+      this->GraftOutput( inputAsOutput );
+      this->GetOutput()->SetLargestPossibleRegion(this->GetOutput()->GetLargestPossibleRegion());
+      this->GetOutput()->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());
+      this->GetOutput()->SetBufferedRegion(this->GetOutput()->GetBufferedRegion());
+
       }
+
+    // If there are more than one outputs, allocate the remaining outputs
+    for (unsigned int i=1; i < this->GetNumberOfOutputs(); i++)
+      {
+      ImagePointer outputPtr;
+
+      outputPtr = this->GetOutput(i);
+      outputPtr->SetBufferedRegion(outputPtr->GetRequestedRegion());
+      outputPtr->Allocate();
+      }
+    }
+  else
+    {
+    //
+
+    Superclass::AllocateOutputs();
+    // copy the content of the input image to the output image (will be done by ImageSource AllocateOutputs Method)
+    // would never occur : inputasoutput condition is always true, since output and input type is TImage for
+    // BandsStatisticsAttributesLabelMapFilter class
+    }
+}
+
+
+template <class TImage, class TFeatureImage>
+void
+BandsStatisticsAttributesLabelMapFilter<TImage, TFeatureImage>
+::GenerateInputRequestedRegion()
+{
+  itk::ImageToImageFilter<TImage,TImage>::GenerateInputRequestedRegion();
 }
 
 
@@ -281,5 +305,5 @@ BandsStatisticsAttributesLabelMapFilter<TImage, TFeatureImage>
   Superclass::PrintSelf(os, indent);
 }
 
-} // end namespace itk
+} // end namespace otb
 #endif
diff --git a/Code/OBIA/otbLabelMapToLabelImageFilter.txx b/Code/OBIA/otbLabelMapToLabelImageFilter.txx
index 8eff1966a8..5bd3a8886f 100644
--- a/Code/OBIA/otbLabelMapToLabelImageFilter.txx
+++ b/Code/OBIA/otbLabelMapToLabelImageFilter.txx
@@ -35,34 +35,8 @@ void
 LabelMapToLabelImageFilter<TInputImage, TOutputImage>
 ::GenerateInputRequestedRegion()
 {
-
-
-  for (unsigned int idx = 0; idx < this->GetNumberOfInputs(); ++idx)
-      {
-       InputImagePointer input = const_cast<InputImageType *>(this->GetInput(idx));
-      if (!input.IsNull())
-        {
-        input->SetRequestedRegionToLargestPossibleRegion();
-        // Check whether the input is an image of the appropriate
-        // dimension (use ProcessObject's version of the GetInput()
-        // method since it returns the input as a pointer to a
-        // DataObject as opposed to the subclass version which
-        // static_casts the input to an TInputImage).
-
-        // Use the function object RegionCopier to copy the output region
-        // to the input.  The default region copier has default implementations
-        // to handle the cases where the input and output are the same
-        // dimension, the input a higher dimension than the output, and the
-        // input a lower dimension than the output.
-        InputImageRegionType inputRegion;
-        this->CallCopyOutputRegionToInputRegion(inputRegion, this->GetOutput()->GetRequestedRegion());
-        input->SetRequestedRegion( inputRegion );
-        }
-      }
-
-
+  itk::ImageToImageFilter<TInputImage,TOutputImage>::GenerateInputRequestedRegion();
 }
 
-
 }// end namespace otb
 #endif
diff --git a/Code/OBIA/otbShapeAttributesLabelMapFilter.h b/Code/OBIA/otbShapeAttributesLabelMapFilter.h
index ed4b358604..6a554901ca 100644
--- a/Code/OBIA/otbShapeAttributesLabelMapFilter.h
+++ b/Code/OBIA/otbShapeAttributesLabelMapFilter.h
@@ -205,6 +205,7 @@ public:
   typedef itk::SmartPointer<const Self> ConstPointer;
 
   typedef typename ImageType::Pointer         ImagePointer;
+
   /** ImageDimension constants */
   itkStaticConstMacro(ImageDimension, unsigned int, TImage::ImageDimension);
 
@@ -258,6 +259,8 @@ protected:
   /** PrintSelf method */
   void PrintSelf(std::ostream& os, itk::Indent indent) const;
 
+  virtual void AllocateOutputs();
+
   /** Things to to before threaded data generation */
   virtual void BeforeThreadedGenerateData();
 
diff --git a/Code/OBIA/otbShapeAttributesLabelMapFilter.txx b/Code/OBIA/otbShapeAttributesLabelMapFilter.txx
index dc9ebbec33..f541524d15 100644
--- a/Code/OBIA/otbShapeAttributesLabelMapFilter.txx
+++ b/Code/OBIA/otbShapeAttributesLabelMapFilter.txx
@@ -834,33 +834,52 @@ ShapeAttributesLabelMapFilter<TImage, TLabelImage>
 template <class TImage, class TLabelImage>
 void
 ShapeAttributesLabelMapFilter<TImage, TLabelImage>
-::GenerateInputRequestedRegion()
-{
+::AllocateOutputs()
+ {
+ // if told to run in place and the types support it,
+  if( this->GetInPlace() && this->CanRunInPlace() )
+    {
+    // Graft this first input to the output.  Later, we'll need to
+    // remove the input's hold on the bulk data.
+    //
+   ImagePointer inputAsOutput = dynamic_cast<TImage *>(const_cast<TImage *>(this->GetInput()));
 
-  for (unsigned int idx = 0; idx < this->GetNumberOfInputs(); ++idx)
+    if( inputAsOutput )
       {
-       ImagePointer input = const_cast<ImageType *>(this->GetInput(idx));
-      if (!input.IsNull())
-        {
-        input->SetRequestedRegionToLargestPossibleRegion();
-        // Check whether the input is an image of the appropriate
-        // dimension (use ProcessObject's version of the GetInput()
-        // method since it returns the input as a pointer to a
-        // DataObject as opposed to the subclass version which
-        // static_casts the input to an TInputImage).
-
-        // Use the function object RegionCopier to copy the output region
-        // to the input.  The default region copier has default implementations
-        // to handle the cases where the input and output are the same
-        // dimension, the input a higher dimension than the output, and the
-        // input a lower dimension than the output.
-        InputImageRegionType inputRegion;
-        this->CallCopyOutputRegionToInputRegion(inputRegion, this->GetOutput()->GetRequestedRegion());
-        input->SetRequestedRegion( inputRegion );
-        }
+
+      this->GraftOutput( inputAsOutput );
+      this->GetOutput()->SetLargestPossibleRegion(this->GetOutput()->GetLargestPossibleRegion());
+      this->GetOutput()->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());
+      this->GetOutput()->SetBufferedRegion(this->GetOutput()->GetBufferedRegion());
+
       }
 
+    // If there are more than one outputs, allocate the remaining outputs
+    for (unsigned int i=1; i < this->GetNumberOfOutputs(); i++)
+      {
+      ImagePointer outputPtr;
+
+      outputPtr = this->GetOutput(i);
+      outputPtr->SetBufferedRegion(outputPtr->GetRequestedRegion());
+      outputPtr->Allocate();
+      }
+    }
+  else
+    {
+    //
+     Superclass::AllocateOutputs();
+    // copy the content of the input image to the output image (will be done by ImageSource AllocateOutputs Method)
+    // would never occur : inputasoutput condition is always true, since output and input type is TImage for
+   // ShapeAttributesLabelMapFilter class
+    }
+}
 
+template <class TImage, class TLabelImage>
+void
+ShapeAttributesLabelMapFilter<TImage, TLabelImage>
+::GenerateInputRequestedRegion()
+{
+  itk::ImageToImageFilter<TImage,TImage>::GenerateInputRequestedRegion();
 }
 
 
-- 
GitLab