/*=========================================================================
*
*  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 sitkBilateralImageFilter_h
#define sitkBilateralImageFilter_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 BilateralImageFilter
\brief Blurs an image while preserving edges.

This filter uses bilateral filtering to blur an image using both domain and range "neighborhoods". Pixels that are close to a pixel in the image domain and similar to a pixel in the image range are used to calculate the filtered value. Two gaussian kernels (one in the image domain and one in the image range) are used to smooth the image. The result is an image that is smoothed in homogeneous regions yet has edges preserved. The result is similar to anisotropic diffusion but the implementation in non-iterative. Another benefit to bilateral filtering is that any distance metric can be used for kernel smoothing the image range. Hence, color images can be smoothed as vector images, using the CIE distances between intensity values as the similarity metric (the Gaussian kernel for the image domain is evaluated using CIE distances). A separate version of this filter will be designed for color and vector images.

Bilateral filtering is capable of reducing the noise in an image by an order of magnitude while maintaining edges.

The bilateral operator used here was described by Tomasi and Manduchi (Bilateral Filtering for Gray and ColorImages. IEEE ICCV. 1998.)

\see GaussianOperator 


\see RecursiveGaussianImageFilter 


\see DiscreteGaussianImageFilter 


\see AnisotropicDiffusionImageFilter 


\see Image 


\see Neighborhood 


\see NeighborhoodOperator 


TodoSupport color images 

Support vector images
\sa itk::simple::Bilateral for the procedural interface
\sa itk::BilateralImageFilter for the Doxygen on the original ITK class.
     */
    class SITKBasicFilters_EXPORT BilateralImageFilter : public ImageFilter {
    public:
      using Self = BilateralImageFilter;

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

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

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

      /**
       * Convenience get/set methods for setting all domain parameters to the same values.
       */
      SITK_RETURN_SELF_TYPE_HEADER SetDomainSigma ( double DomainSigma ) { this->m_DomainSigma = DomainSigma; return *this; }

      /**
       * Standard get/set macros for filter parameters. DomainSigma is specified in the same units as the Image spacing. RangeSigma is specified in the units of intensity.
       */
      double GetDomainSigma() const { return this->m_DomainSigma; }\

      /**
       * Standard get/set macros for filter parameters. DomainSigma is specified in the same units as the Image spacing. RangeSigma is specified in the units of intensity.
       */
      SITK_RETURN_SELF_TYPE_HEADER SetRangeSigma ( double RangeSigma ) { this->m_RangeSigma = RangeSigma; return *this; }

      /**
       * Standard get/set macros for filter parameters. DomainSigma is specified in the same units as the Image spacing. RangeSigma is specified in the units of intensity.
       */
      double GetRangeSigma() const { return this->m_RangeSigma; }\

      /**
       * Set/Get the number of samples in the approximation to the Gaussian used for the range smoothing. Samples are only generated in the range of [0, 4*m_RangeSigma]. Default is 100.
       */
      SITK_RETURN_SELF_TYPE_HEADER SetNumberOfRangeGaussianSamples ( unsigned int NumberOfRangeGaussianSamples ) { this->m_NumberOfRangeGaussianSamples = NumberOfRangeGaussianSamples; return *this; }

      /**
       * Set/Get the number of samples in the approximation to the Gaussian used for the range smoothing. Samples are only generated in the range of [0, 4*m_RangeSigma]. Default is 100.
       */
      unsigned int GetNumberOfRangeGaussianSamples() const { return this->m_NumberOfRangeGaussianSamples; }

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

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


      /** Execute the filter on the input image */

      Image Execute ( const Image& image1 );

    private:

      /** Setup for member function dispatching */

      using MemberFunctionType = Image (Self::*)( const Image& image1 );
      template <class TImageType> Image ExecuteInternal ( const Image& image1 );
      /** Dispatched methods which calls ExecuteInternal on each component */
      template <class TImageType> Image ExecuteInternalVectorImage ( const Image& image );

      friend struct detail::MemberFunctionAddressor<MemberFunctionType>;
      friend struct detail::ExecuteInternalVectorImageAddressor<MemberFunctionType>;
      std::unique_ptr<detail::MemberFunctionFactory<MemberFunctionType> > m_MemberFactory;


      double  m_DomainSigma{4.0};

      double  m_RangeSigma{50.0};

      unsigned int  m_NumberOfRangeGaussianSamples{100u};


    };

    /**\
     * \brief Blurs an image while preserving edges.
     *
     * This function directly calls the execute method of BilateralImageFilter
     * in order to support a procedural API
     *
     * \sa itk::simple::BilateralImageFilter for the object oriented interface
     * @{
     */

     SITKBasicFilters_EXPORT Image Bilateral ( const Image& image1, double domainSigma = 4.0, double rangeSigma = 50.0, unsigned int numberOfRangeGaussianSamples = 100u );

     /** @} */
}
#endif
