/*=========================================================================
*
*  Copyright NumFOCUS
*
*  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.txt
*
*  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.
*
*=========================================================================*/
#ifndef sitkGradientAnisotropicDiffusionImageFilter_h
#define sitkGradientAnisotropicDiffusionImageFilter_h

/*
 * WARNING: DO NOT EDIT THIS FILE!
 * THIS FILE IS AUTOMATICALLY GENERATED BY THE SIMPLEITK BUILD PROCESS.
 * Please look at sitkImageFilterTemplate.h.in to make changes.
 */

#include <memory>

#include "sitkBasicFilters.h"
#include "sitkImageFilter.h"

namespace itk::simple {

    /**\class GradientAnisotropicDiffusionImageFilter
\brief This filter performs anisotropic diffusion on a scalar itk::Image using the classic Perona-Malik, gradient magnitude based equation.

For detailed information on anisotropic diffusion, see itkAnisotropicDiffusionFunction and itkGradientNDAnisotropicDiffusionFunction.

\par Inputs and Outputs
The input to this filter should be a scalar itk::Image of any dimensionality. The output image will be a diffused copy of the input.


\par Parameters
Please see the description of parameters given in itkAnisotropicDiffusionImageFilter.


\see AnisotropicDiffusionImageFilter 


\see AnisotropicDiffusionFunction 


\see GradientAnisotropicDiffusionFunction
\sa itk::simple::GradientAnisotropicDiffusion for the procedural interface
\sa itk::GradientAnisotropicDiffusionImageFilter for the Doxygen on the original ITK class.
     */
    class SITKBasicFilters_EXPORT GradientAnisotropicDiffusionImageFilter : public ImageFilter {
    public:
      using Self = GradientAnisotropicDiffusionImageFilter;

      /** Destructor */
      virtual ~GradientAnisotropicDiffusionImageFilter();

      /** Default Constructor that takes no arguments and initializes
       * default parameters */
      GradientAnisotropicDiffusionImageFilter();

      /** Define the pixels types supported by this filter */
      using PixelIDTypeList = RealPixelIDTypeList;
\

      /**
       */
      SITK_RETURN_SELF_TYPE_HEADER SetTimeStep ( double TimeStep ) { this->m_TimeStep = TimeStep; return *this; }

      /**
       */
      double GetTimeStep() const { return this->m_TimeStep; }\

      /**
       */
      SITK_RETURN_SELF_TYPE_HEADER SetConductanceParameter ( double ConductanceParameter ) { this->m_ConductanceParameter = ConductanceParameter; return *this; }

      /**
       */
      double GetConductanceParameter() const { return this->m_ConductanceParameter; }\

      /**
       */
      SITK_RETURN_SELF_TYPE_HEADER SetConductanceScalingUpdateInterval ( unsigned int ConductanceScalingUpdateInterval ) { this->m_ConductanceScalingUpdateInterval = ConductanceScalingUpdateInterval; return *this; }

      /**
       */
      unsigned int GetConductanceScalingUpdateInterval() const { return this->m_ConductanceScalingUpdateInterval; }\

      /**
       */
      SITK_RETURN_SELF_TYPE_HEADER SetNumberOfIterations ( uint32_t NumberOfIterations ) { this->m_NumberOfIterations = NumberOfIterations; return *this; }

      /**
       */
      uint32_t GetNumberOfIterations() const { return this->m_NumberOfIterations; }

      /** Name of this class */
      std::string GetName() const { return std::string ("GradientAnisotropicDiffusionImageFilter"); }

      /** Print ourselves out */
      std::string ToString() const;


      /** Execute the filter on the input image */
#ifndef SWIG
      Image Execute ( Image&& image1 );
#endif
      Image Execute ( const Image& image1 );


      /** This method autmatically  sets the optimal timestep for an image given its spacing. */
      double EstimateOptimalTimeStep(Image & inImage );

    private:

      /** Setup for member function dispatching */

      using MemberFunctionType = Image (Self::*)( const Image& image1 );
      template <class TImageType> Image ExecuteInternal ( const Image& image1 );


      friend struct detail::MemberFunctionAddressor<MemberFunctionType>;

      std::unique_ptr<detail::MemberFunctionFactory<MemberFunctionType> > m_MemberFactory;


      /* Time step for PDE solver */
      double  m_TimeStep{0.125};

      /* Conductance parameter governing sensitivity of the conductance equation. */
      double  m_ConductanceParameter{3};

      /* Interval at which a new scaling for the conductance term is calculated. */
      unsigned int  m_ConductanceScalingUpdateInterval{1u};

      /* Number of iterations to run */
      uint32_t  m_NumberOfIterations{5u};


      bool m_InPlace{false};
    };

    /**\
     * \brief This filter performs anisotropic diffusion on a scalar itk::Image using the classic Perona-Malik, gradient magnitude based equation.
     *
     * This function directly calls the execute method of GradientAnisotropicDiffusionImageFilter
     * in order to support a procedural API
     *
     * \sa itk::simple::GradientAnisotropicDiffusionImageFilter for the object oriented interface
     * @{
     */
#ifndef SWIG
     SITKBasicFilters_EXPORT Image GradientAnisotropicDiffusion ( Image&& image1, double timeStep = 0.125, double conductanceParameter = 3, unsigned int conductanceScalingUpdateInterval = 1u, uint32_t numberOfIterations = 5u );
#endif
     SITKBasicFilters_EXPORT Image GradientAnisotropicDiffusion ( const Image& image1, double timeStep = 0.125, double conductanceParameter = 3, unsigned int conductanceScalingUpdateInterval = 1u, uint32_t numberOfIterations = 5u );

     /** @} */
}
#endif
