#ifndef __MINMAXFILTER_H
#define __MINMAXFILTER_H

/**
 *******************************************************************************
 *
 * @file minMaxFilter.h
 *
 * \class CMinMaxFilterBase
 * \date  Tue Oct 13, 2009
 * \author Hernan Badino (hernan.badino@gmail.com)
 *
 * \brief Defines a min/max (erosion/dilation) operator class.
 *
 * Separate methods for horizontal and vertical filtering are provided. The
 * filter size is specified when calling the corresponding filtering method.
 * Methods for handling invalid values are also provided.
 *
 *******************************************************************************/

/* INCLUDES */

/* CONSTANTS */

namespace VIC
{
    class CMinMaxFilterBase
    {
    private:
        
        CMinMaxFilterBase();
        virtual ~CMinMaxFilterBase();

    /// Public data types.
    public:
        typedef enum
        {
            FM_IGNORE_INVALID,
            FM_MASK_INVALID,
            FM_NO_INVALID /// Not implemented so far.
        } EFilterMode;
    };


    template <class _SrcType, class _TgtType = _SrcType>
    class CMinMaxFilter: public CMinMaxFilterBase
    {
    private:
        
        CMinMaxFilter();
        virtual ~CMinMaxFilter();


    /// Public operations.
    public:

        ///////// Standard function not considering invalid values.
        /// Apply Min filter horizontal.
        static bool 
        filterMinHorizontal ( const CTypedImage<_SrcType> &f_src,
                              CTypedImage<_TgtType>       &fr_dst,
                              const unsigned int           f_kernelWidth_ui );
        
        /// Apply Max filter horizontal.
        static bool 
        filterMaxHorizontal ( const CTypedImage<_SrcType> &f_src,
                              CTypedImage<_TgtType>       &fr_dst,
                              const unsigned int           f_kernelWidth_ui );
        
        /// Apply Min filter vertical.
        static bool 
        filterMinVertical ( const CTypedImage<_SrcType> &f_src,
                            CTypedImage<_TgtType>       &fr_dst,
                            const unsigned int          f_kernelHeight_ui );
        
        /// Apply Max filter vertical.
        static bool 
        filterMaxVertical ( const CTypedImage<_SrcType> &f_src,
                            CTypedImage<_TgtType>       &fr_dst,
                            const unsigned int          f_kernelHeight_ui );
        

        /// Apply Min filter horizontal and vertical.        
        static bool 
        filterMinimum ( const CTypedImage<_SrcType> &f_src,
                        CTypedImage<_TgtType>       &fr_dst,
                        const unsigned int          f_kernelWidth_ui,
                        const unsigned int          f_kernelHeight_ui );

        /// Apply Max filter horizontal and vertical.        
        static bool 
        filterMaximum ( const CTypedImage<_SrcType> &f_src,
                        CTypedImage<_TgtType>       &fr_dst,
                        const unsigned int          f_kernelWidth_ui,
                        const unsigned int          f_kernelHeight_ui );

        /// Apply Min filter horizontal.
        static bool 
        filterMinHorizontal ( const CTypedImage<_SrcType>     &f_src,
                              CTypedImage<_TgtType>           &fr_dst,
                              const unsigned int               f_kernelWidth_ui,
                              const _SrcType                   f_invalid,
                              const CMinMaxFilterBase::EFilterMode 
                              f_filterMode_e = FM_IGNORE_INVALID );
        
        /// Apply Max filter horizontal.
        static bool 
        filterMaxHorizontal ( const CTypedImage<_SrcType>  &f_src,
                              CTypedImage<_TgtType>        &fr_dst,
                              const unsigned int            f_kernelWidth_ui,
                              const _SrcType                f_invalid,
                              const CMinMaxFilterBase::EFilterMode 
                              f_filterMode_e = FM_IGNORE_INVALID );

        /// Apply Min filter vertical.
        static bool 
        filterMinVertical ( const CTypedImage<_SrcType>  &f_src,
                            CTypedImage<_TgtType>        &fr_dst,
                            const unsigned int            f_kernelHeight_ui,
                            const _SrcType                f_invalid,
                            const CMinMaxFilterBase::EFilterMode 
                            f_filterMode_e = FM_IGNORE_INVALID );

        /// Apply Max filter vertical.
        static bool 
        filterMaxVertical ( const CTypedImage<_SrcType>  &f_src,
                            CTypedImage<_TgtType>        &fr_dst,
                            const unsigned int           f_kernelHeight_ui,
                            const _SrcType               f_invalid,
                            const CMinMaxFilterBase::EFilterMode f_filterMode_e = FM_IGNORE_INVALID );

        /// Apply Min filter horizontal and vertical.        
        static bool 
        filterMinimum ( const CTypedImage<_SrcType>  &f_src,
                        CTypedImage<_TgtType>        &fr_dst,
                        const unsigned int            f_kernelWidth_ui,
                        const unsigned int            f_kernelHeight_ui,
                        const _SrcType                f_invalid,
                        const CMinMaxFilterBase::EFilterMode f_filterMode_e = FM_IGNORE_INVALID );

        /// Apply Max filter horizontal and vertical.        
        static bool 
        filterMaximum ( const CTypedImage<_SrcType>  &f_src,
                        CTypedImage<_TgtType>        &fr_dst,
                        const unsigned int            f_kernelWidth_ui,
                        const unsigned int            f_kernelHeight_ui,
                        const _SrcType                f_invalid,
                        const CMinMaxFilterBase::EFilterMode 
                        f_filterMode_e = FM_IGNORE_INVALID );

    /// Private Help methods
    private:
        
        ///////// Mask version
        /// Apply Min filter horizontal.
        static bool 
        filterMinHorizontal_Mask ( const CTypedImage<_SrcType> &f_src,
                                   CTypedImage<_TgtType>       &fr_dst,
                                   const unsigned int           f_kernelWidth_ui,
                                   const _SrcType               f_invalid );


        /// Apply Min filter vertical.
        static bool 
        filterMinVertical_Mask ( const CTypedImage<_SrcType> &f_src,
                                 CTypedImage<_TgtType>       &fr_dst,
                                 const unsigned int           f_kernelHeight_ui,
                                 const _SrcType               f_invalid );

        /// Apply Min filter horizontal.
        static bool 
        filterMaxHorizontal_Mask ( const CTypedImage<_SrcType> &f_src,
                                   CTypedImage<_TgtType>       &fr_dst,
                                   const unsigned int           f_kernelWidth_ui,
                                   const _SrcType               f_invalid );
 

        /// Apply Min filter vertical.
        static bool 
        filterMaxVertical_Mask ( const CTypedImage<_SrcType> &f_src,
                                 CTypedImage<_TgtType>       &fr_dst,
                                 const unsigned int           f_kernelHeight_ui,
                                 const _SrcType               f_invalid );
        
        ///////// Ignore Invalid
        /// Apply Min filter horizontal.
        static bool 
        filterMinHorizontal_IgnoreInvalid ( const CTypedImage<_SrcType> &f_src,
                                            CTypedImage<_TgtType>       &fr_dst,
                                            const unsigned int           f_kernelWidth_ui,
                                            const _SrcType               f_invalid );
        
        /// Apply Max filter horizontal.
        static bool 
        filterMaxHorizontal_IgnoreInvalid ( const CTypedImage<_SrcType> &f_src,
                                            CTypedImage<_TgtType>       &fr_dst,
                                            const unsigned int           f_kernelWidth_ui,
                                            const _SrcType               f_invalid );
        
        /// Apply Min filter vertical.
        static bool 
        filterMinVertical_IgnoreInvalid ( const CTypedImage<_SrcType> &f_src,
                                          CTypedImage<_TgtType>       &fr_dst,
                                          const unsigned int           f_kernelHeight_ui,
                                          const _SrcType               f_invalid );
        
        /// Apply Max filter vertical.
        static bool 
        filterMaxVertical_IgnoreInvalid ( const CTypedImage<_SrcType> &f_src,
                                          CTypedImage<_TgtType>       &fr_dst,
                                          const unsigned int           f_kernelHeight_ui,
                                          const _SrcType               f_invalid );

    /// Class members.
    public:
        static CTypedImage<_TgtType> m_bufferMin_s;
        static CTypedImage<_TgtType> m_bufferMax_s;


    };

    #include "minMaxFilter_inline.h"
}




#endif // __MINMAXFILTER_H

/* ////////////  Version History ///////////////
 *  $Log: minMaxFilter.h,v $
 *  Revision 1.2  2009/11/18 15:51:01  badino
 *  badino: documentation added. Some other global changes.
 *
 *//////////////////////////////////////////////
