/*=========================================================================
*
*  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 sitkHistogramMatchingImageFilter_h
#define sitkHistogramMatchingImageFilter_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 HistogramMatchingImageFilter
\brief Normalize the grayscale values for a source image by matching the shape of the source image histogram to a reference histogram.

HistogramMatchingImageFilter normalizes the grayscale values of a source image based on the grayscale values of either a reference image or a reference histogram. This filter uses a histogram matching technique where the histograms of the are matched only at a specified number of quantile values.

This filter was originally designed to normalize MR images of the same MR protocol and same body part. The algorithm works best if background pixels are excluded from both the source and reference histograms. A simple background exclusion method is to exclude all pixels whose grayscale values are smaller than the mean grayscale value. ThresholdAtMeanIntensityOn() switches on this simple background exclusion method. With ThresholdAtMeanIntensityOn() , The reference histogram returned from this filter will expand the first and last bin bounds to include the minimum and maximum intensity values of the entire reference image, but only intensity values greater than the mean will be used to populate the histogram.

The source image can be set via either SetInput() or SetSourceImage(). The reference object used is selected with can be set via SetReferenceImage() or SetReferenceHistogram().

SetNumberOfHistogramLevels() sets the number of bins used when creating histograms of the source and reference images. SetNumberOfMatchPoints() governs the number of quantile values to be matched.

This filter assumes that both the source and reference are of the same type and that the input and output image type have the same number of dimension and have scalar pixel types.

\par REFERENCE
Laszlo G. Nyul, Jayaram K. Udupa, and Xuan Zhang, "New Variants of a Method
of MRI Scale Standardization", IEEE Transactions on Medical Imaging, 19(2):143-150, 2000.
\sa itk::simple::HistogramMatching for the procedural interface
\sa itk::HistogramMatchingImageFilter for the Doxygen on the original ITK class.
     */
    class SITKBasicFilters_EXPORT HistogramMatchingImageFilter : public ImageFilter {
    public:
      using Self = HistogramMatchingImageFilter;

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

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

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

      /**
       * Set/Get the number of histogram levels used.
       */
      SITK_RETURN_SELF_TYPE_HEADER SetNumberOfHistogramLevels ( uint32_t NumberOfHistogramLevels ) { this->m_NumberOfHistogramLevels = NumberOfHistogramLevels; return *this; }

      /**
       * Set/Get the number of histogram levels used.
       */
      uint32_t GetNumberOfHistogramLevels() const { return this->m_NumberOfHistogramLevels; }\

      /**
       * Set/Get the number of match points used.
       */
      SITK_RETURN_SELF_TYPE_HEADER SetNumberOfMatchPoints ( uint32_t NumberOfMatchPoints ) { this->m_NumberOfMatchPoints = NumberOfMatchPoints; return *this; }

      /**
       * Set/Get the number of match points used.
       */
      uint32_t GetNumberOfMatchPoints() const { return this->m_NumberOfMatchPoints; }\

      /**
       * Set/Get the threshold at mean intensity flag. If true, only source (reference) pixels which are greater than the mean source (reference) intensity is used in the histogram matching. If false, all pixels are used.
       */
      SITK_RETURN_SELF_TYPE_HEADER SetThresholdAtMeanIntensity ( bool ThresholdAtMeanIntensity ) { this->m_ThresholdAtMeanIntensity = ThresholdAtMeanIntensity; return *this; }

      /** Set the value of ThresholdAtMeanIntensity to true or false respectfully. */
      SITK_RETURN_SELF_TYPE_HEADER ThresholdAtMeanIntensityOn() { return this->SetThresholdAtMeanIntensity(true); }
      SITK_RETURN_SELF_TYPE_HEADER ThresholdAtMeanIntensityOff() { return this->SetThresholdAtMeanIntensity(false); }

      /**
       * Set/Get the threshold at mean intensity flag. If true, only source (reference) pixels which are greater than the mean source (reference) intensity is used in the histogram matching. If false, all pixels are used.
       */
      bool GetThresholdAtMeanIntensity() const { return this->m_ThresholdAtMeanIntensity; }

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

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


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

      Image Execute ( const Image & image, const Image & referenceImage );

    private:

      /** Setup for member function dispatching */

      using MemberFunctionType = Image (Self::*)( const Image * image, const Image * referenceImage );
      template <class TImageType> Image ExecuteInternal ( const Image * image, const Image * referenceImage );


      friend struct detail::MemberFunctionAddressor<MemberFunctionType>;

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


      uint32_t  m_NumberOfHistogramLevels{256u};

      uint32_t  m_NumberOfMatchPoints{1u};

      bool  m_ThresholdAtMeanIntensity{true};


    };

    /**\
     * \brief Normalize the grayscale values for a source image by matching the shape of the source image histogram to a reference histogram.
     *
     * This function directly calls the execute method of HistogramMatchingImageFilter
     * in order to support a procedural API
     *
     * \sa itk::simple::HistogramMatchingImageFilter for the object oriented interface
     * @{
     */

     SITKBasicFilters_EXPORT Image HistogramMatching ( const Image & image, const Image & referenceImage, uint32_t numberOfHistogramLevels = 256u, uint32_t numberOfMatchPoints = 1u, bool thresholdAtMeanIntensity = true );

     /** @} */
}
#endif
