/*=========================================================================
*
*  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 sitkResampleImageFilter_h
#define sitkResampleImageFilter_h

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

#include <memory>

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

namespace itk::simple {

    /**\class ResampleImageFilter
\brief Resample an image via a coordinate transform.

ResampleImageFilter resamples an existing image through some coordinate transform, interpolating via some image function. The class is templated over the types of the input and output images.

Note that the choice of interpolator function can be important. This function is set via SetInterpolator() . The default is LinearInterpolateImageFunction <InputImageType, TInterpolatorPrecisionType>, which is reasonable for ordinary medical images. However, some synthetic images have pixels drawn from a finite prescribed set. An example would be a mask indicating the segmentation of a brain into a small number of tissue types. For such an image, one does not want to interpolate between different pixel values, and so NearestNeighborInterpolateImageFunction < InputImageType, TCoordRep > would be a better choice.

If an sample is taken from outside the image domain, the default behavior is to use a default pixel value. If different behavior is desired, an extrapolator function can be set with SetExtrapolator() .

Output information (spacing, size and direction) for the output image should be set. This information has the normal defaults of unit spacing, zero origin and identity direction. Optionally, the output information can be obtained from a reference image. If the reference image is provided and UseReferenceImage is On, then the spacing, origin and direction of the reference image will be used.

Since this filter produces an image which is a different size than its input, it needs to override several of the methods defined in ProcessObject in order to properly manage the pipeline execution model. In particular, this filter overrides ProcessObject::GenerateInputRequestedRegion() and ProcessObject::GenerateOutputInformation() .

This filter is implemented as a multithreaded filter. It provides a DynamicThreadedGenerateData() method for its implementation. \warning For multithreading, the TransformPoint method of the user-designated coordinate transform must be threadsafe.

\sa itk::ResampleImageFilter for the Doxygen on the original ITK class.
     */
    class SITKBasicFilters_EXPORT ResampleImageFilter : public ImageFilter {
    public:
      using Self = ResampleImageFilter;

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

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

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

\

      /**
       * Get/Set the size of the output image.
       */
      SITK_RETURN_SELF_TYPE_HEADER SetSize ( std::vector<uint32_t> Size ) { this->m_Size = std::move(Size); return *this; }

      /**
       * Get/Set the size of the output image.
       */
      std::vector<uint32_t> GetSize() const { return this->m_Size; }\

      /**
       */
      SITK_RETURN_SELF_TYPE_HEADER SetTransform ( Transform Transform ) { this->m_Transform = Transform; return *this; }

      /**
       */
      Transform GetTransform() const { return this->m_Transform; }\

      /**
       * Get/Set the interpolator function. The default is LinearInterpolateImageFunction <InputImageType, TInterpolatorPrecisionType>. Some other options are NearestNeighborInterpolateImageFunction (useful for binary masks and other images with a small number of possible pixel values), and BSplineInterpolateImageFunction (which provides a higher order of interpolation).
       */
      SITK_RETURN_SELF_TYPE_HEADER SetInterpolator ( InterpolatorEnum Interpolator ) { this->m_Interpolator = Interpolator; return *this; }

      /**
       * Get/Set the interpolator function. The default is LinearInterpolateImageFunction <InputImageType, TInterpolatorPrecisionType>. Some other options are NearestNeighborInterpolateImageFunction (useful for binary masks and other images with a small number of possible pixel values), and BSplineInterpolateImageFunction (which provides a higher order of interpolation).
       */
      InterpolatorEnum GetInterpolator() const { return this->m_Interpolator; }\

      /**
       * Set the output image origin.
       */
      SITK_RETURN_SELF_TYPE_HEADER SetOutputOrigin ( std::vector<double> OutputOrigin ) { this->m_OutputOrigin = std::move(OutputOrigin); return *this; }

      /**
       * Get the output image origin.
       */
      std::vector<double> GetOutputOrigin() const { return this->m_OutputOrigin; }\

      /**
       * Set the output image spacing.
       */
      SITK_RETURN_SELF_TYPE_HEADER SetOutputSpacing ( std::vector<double> OutputSpacing ) { this->m_OutputSpacing = std::move(OutputSpacing); return *this; }

      /**
       * Get the output image spacing.
       */
      std::vector<double> GetOutputSpacing() const { return this->m_OutputSpacing; }\

      /**
       * Set the output direction cosine matrix.
       */
      SITK_RETURN_SELF_TYPE_HEADER SetOutputDirection ( std::vector<double> OutputDirection ) { this->m_OutputDirection = OutputDirection; return *this; }

      /**
       * Set the output direction cosine matrix.
       */
      std::vector<double> GetOutputDirection() const { return this->m_OutputDirection; }\

      /**
       * Get/Set the pixel value when a transformed pixel is outside of the image. The default default pixel value is 0.
       */
      SITK_RETURN_SELF_TYPE_HEADER SetDefaultPixelValue ( double DefaultPixelValue ) { this->m_DefaultPixelValue = DefaultPixelValue; return *this; }

      /**
       * Get/Set the pixel value when a transformed pixel is outside of the image. The default default pixel value is 0.
       */
      double GetDefaultPixelValue() const { return this->m_DefaultPixelValue; }\

      /**
       * \brief Set the output pixel type, if sitkUnknown then the input type is used.
       */
      SITK_RETURN_SELF_TYPE_HEADER SetOutputPixelType ( PixelIDValueEnum OutputPixelType ) { this->m_OutputPixelType = OutputPixelType; return *this; }

      /**
       * \brief Get the ouput pixel type.
       */
      PixelIDValueEnum GetOutputPixelType() const { return this->m_OutputPixelType; }\

      /**
       * \brief Enables the nearest neighbor extrapolator as opposed to the constant pixel value.
       */
      SITK_RETURN_SELF_TYPE_HEADER SetUseNearestNeighborExtrapolator ( bool UseNearestNeighborExtrapolator ) { this->m_UseNearestNeighborExtrapolator = UseNearestNeighborExtrapolator; return *this; }

      /** Set the value of UseNearestNeighborExtrapolator to true or false respectfully. */
      SITK_RETURN_SELF_TYPE_HEADER UseNearestNeighborExtrapolatorOn() { return this->SetUseNearestNeighborExtrapolator(true); }
      SITK_RETURN_SELF_TYPE_HEADER UseNearestNeighborExtrapolatorOff() { return this->SetUseNearestNeighborExtrapolator(false); }

      /**
       */
      bool GetUseNearestNeighborExtrapolator() const { return this->m_UseNearestNeighborExtrapolator; }

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

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


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

      Image Execute ( const Image& image1 );


      /** This methods sets the output size, origin, spacing and direction to that of the provided image */
      void SetReferenceImage(const Image & refImage );


    private:
      /** Setup for member function dispatching */
      using MemberFunctionType = Image (Self::*)( const Image& image1 );

      friend struct detail::DualExecuteInternalAddressor<MemberFunctionType>;
      template <class TImageType1, class TImageType2> Image DualExecuteInternal ( const Image& image1 );
      friend struct detail::DualExecuteInternalVectorAddressor<MemberFunctionType>;
      template <class TImageType1, class TImageType2> Image DualExecuteInternalVector ( const Image& image1 );

      std::unique_ptr<detail::DualMemberFunctionFactory<MemberFunctionType> > m_DualMemberFactory;



      /*  */
      std::vector<uint32_t>  m_Size{std::vector<uint32_t>(3, 0)};

      Transform  m_Transform{itk::simple::Transform()};

      /*  */
      InterpolatorEnum  m_Interpolator{itk::simple::sitkLinear};

      /*  */
      std::vector<double>  m_OutputOrigin{std::vector<double>(3, 0.0)};

      /*  */
      std::vector<double>  m_OutputSpacing{std::vector<double>(3, 1.0)};

      /* Passing a zero sized array, defaults to identiy matrix. The size of the array must exactly match the direction matrix for the dimension of the image. */
      std::vector<double>  m_OutputDirection{std::vector<double>()};

      double  m_DefaultPixelValue{0.0};

      PixelIDValueEnum  m_OutputPixelType{itk::simple::sitkUnknown};

      bool  m_UseNearestNeighborExtrapolator{false};


    };


}
#endif
