/* 
// Copyright 2016-2017 Intel Corporation All Rights Reserved.
// 
// The source code, information and material ("Material") contained herein is
// owned by Intel Corporation or its suppliers or licensors, and title
// to such Material remains with Intel Corporation or its suppliers or
// licensors. The Material contains proprietary information of Intel
// or its suppliers and licensors. The Material is protected by worldwide
// copyright laws and treaty provisions. No part of the Material may be used,
// copied, reproduced, modified, published, uploaded, posted, transmitted,
// distributed or disclosed in any way without Intel's prior express written
// permission. No license under any patent, copyright or other intellectual
// property rights in the Material is granted to or conferred upon you,
// either expressly, by implication, inducement, estoppel or otherwise.
// Any license under such intellectual property rights must be express and
// approved by Intel in writing.
// 
// Unless otherwise agreed by Intel in writing,
// you may not remove or alter this notice or any other notice embedded in
// Materials by Intel or Intel's suppliers or licensors in any way.
// 
*/

#if !defined( __IPP_IWPP_IMAGE_OP__ )
#define __IPP_IWPP_IMAGE_OP__

#include "iw/iw_image_op.h"
#include "iw++/iw_image.hpp"

namespace ipp
{

/**/////////////////////////////////////////////////////////////////////////////
//                   iwiCopy
///////////////////////////////////////////////////////////////////////////// */

// Auxiliary parameters class
// C API descriptions has more details
class IwiCopyParams: public ::IwiCopyParams
{
public:
    IW_BASE_PARAMS_CONSTRUCTORS(IwiCopyParams, iwiCopy_SetDefaultParams)
    IwiCopyParams() {}
};

// Copies image data to destination image with masking.
// If mask is NULL, then calls iwiCopy function.
// For masked operation, the function writes pixel values in the destination buffer only if the spatially corresponding
// mask array value is non-zero.
// C API descriptions has more details.
// Throws:
//      ippStsNotSupportedModeErr           selected function mode is not supported
//      ippStsSizeErr                       size fields values are illegal
//      ippStsInplaceModeNotSupportedErr    doesn't support output into the source buffer
//      ippStsNullPtrErr                    unexpected NULL pointer
// Returns:
//      ippStsNoErr                         no errors
IW_DECL_CPP(IppStatus) iwiCopy(
    const IwiImage      &srcImage,                      // [in]     Reference to the source image
    IwiImage            &dstImage,                      // [in,out] Reference to the destination image
    const IwiImage      &maskImage   = IwiImage(),      // [in]     Reference to the mask image. Mask must be 8-bit, 1 channel image
    const IwiCopyParams &auxParams   = IwiCopyParams(), // [in]     Reference to the auxiliary parameters structure
    const IwiTile       &tile        = IwiTile()        // [in,out] Reference to the IwiTile object for tiling. By default no tiling is used
)
{
    IppStatus ippStatus = ::iwiCopy(&srcImage, &dstImage, &maskImage, &auxParams, &tile);
    OWN_ERROR_CHECK(ippStatus)
    return ippStatus;
}

/**/////////////////////////////////////////////////////////////////////////////
//                   iwiCopyChannel
///////////////////////////////////////////////////////////////////////////// */

// Auxiliary parameters class
// C API descriptions has more details
class IwiCopyChannelParams: public ::IwiCopyChannelParams
{
public:
    IW_BASE_PARAMS_CONSTRUCTORS(IwiCopyChannelParams, iwiCopyChannel_SetDefaultParams)
    IwiCopyChannelParams() {}
};

// Copies selected channel from one image to another.
// C API descriptions has more details.
// Throws:
//      ippStsDataTypeErr                   data type is illegal
//      ippStsNumChannelsErr                channels value is illegal
//      ippStsSizeErr                       size fields values are illegal
//      ippStsInplaceModeNotSupportedErr    doesn't support output into the source buffer
//      ippStsNullPtrErr                    unexpected NULL pointer
// Returns:
//      ippStsNoErr                         no errors
IW_DECL_CPP(IppStatus) iwiCopyChannel(
    const IwiImage             &srcImage,                               // [in]     Reference to the source image
    int                         srcChannel,                             // [in]     Source channel to copy from (starting from 0)
    IwiImage                   &dstImage,                               // [in,out] Reference to the destination image
    int                         dstChannel,                             // [in]     Destination channel to copy to (starting from 0)
    const IwiCopyChannelParams &auxParams   = IwiCopyChannelParams(),   // [in]     Reference to the auxiliary parameters structure
    const IwiTile              &tile        = IwiTile()                 // [in,out] Reference to the IwiTile object for tiling. By default no tiling is used
)
{
    IppStatus ippStatus = ::iwiCopyChannel(&srcImage, srcChannel, &dstImage, dstChannel, &auxParams, &tile);
    OWN_ERROR_CHECK(ippStatus)
    return ippStatus;
}

/**/////////////////////////////////////////////////////////////////////////////
//                   iwiCopySplit
///////////////////////////////////////////////////////////////////////////// */

// Auxiliary parameters class
// C API descriptions has more details
class IwiCopySplitParams: public ::IwiCopySplitParams
{
public:
    IW_BASE_PARAMS_CONSTRUCTORS(IwiCopySplitParams, iwiCopySplit_SetDefaultParams)
    IwiCopySplitParams() {}
};

// Splits multi-channel image into array of single channel images.
// C API descriptions has more details.
// Throws:
//      ippStsDataTypeErr                   data type is illegal
//      ippStsNumChannelsErr                channels value is illegal
//      ippStsSizeErr                       size fields values are illegal
//      ippStsNullPtrErr                    unexpected NULL pointer
// Returns:
//      ippStsNoErr                         no errors
IW_DECL_CPP(IppStatus) iwiCopySplit(
    const IwiImage              &srcImage,                          // [in]     Reference to the source image
          IwiImageArray          dstImages,                         // [in,out] The array object of destination images. Uninitialized images will be skipped
    const IwiCopySplitParams    &auxParams  = IwiCopySplitParams(), // [in]     Reference to the auxiliary parameters structure
    const IwiTile               &tile       = IwiTile()             // [in,out] Reference to the IwiTile object for tiling. By default no tiling is used
)
{
    ::IwiImage* const pDstImages[] = {&dstImages.imArray[0], &dstImages.imArray[1], &dstImages.imArray[2], &dstImages.imArray[3]};
    IppStatus ippStatus = ::iwiCopySplit(&srcImage, pDstImages, &auxParams, &tile);
    OWN_ERROR_CHECK(ippStatus)
    return ippStatus;
}

/**/////////////////////////////////////////////////////////////////////////////
//                   iwiCopyMerge
///////////////////////////////////////////////////////////////////////////// */

// Auxiliary parameters class
// C API descriptions has more details
class IwiCopyMergeParams: public ::IwiCopyMergeParams
{
public:
    IW_BASE_PARAMS_CONSTRUCTORS(IwiCopyMergeParams, iwiCopyMerge_SetDefaultParams)
    IwiCopyMergeParams() {}
};

// Merges array of single channel images into one multi-channel image.
// C API descriptions has more details.
// Throws:
//      ippStsDataTypeErr                   data type is illegal
//      ippStsNumChannelsErr                channels value is illegal
//      ippStsSizeErr                       size fields values are illegal
//      ippStsNullPtrErr                    unexpected NULL pointer
// Returns:
//      ippStsNoErr                         no errors
IW_DECL_CPP(IppStatus) iwiCopyMerge(
    const IwiImageArray         &srcImages,                         // [in]     Reference to the array object of source images. Uninitialized images will be skipped
    IwiImage                    &dstImage,                          // [in,out] Reference to the destination image
    const IwiCopyMergeParams    &auxParams  = IwiCopyMergeParams(), // [in]     Reference to the auxiliary parameters structure
    const IwiTile               &tile       = IwiTile()             // [in,out] Reference to the IwiTile object for tiling. By default no tiling is used
)
{
    const ::IwiImage* const pSrcImages[] = {&srcImages.imArray[0], &srcImages.imArray[1], &srcImages.imArray[2], &srcImages.imArray[3]};
    IppStatus ippStatus = ::iwiCopyMerge(pSrcImages, &dstImage, &auxParams, &tile);
    OWN_ERROR_CHECK(ippStatus)
    return ippStatus;
}

/**/////////////////////////////////////////////////////////////////////////////
//                   iwiCopyMakeBorder
///////////////////////////////////////////////////////////////////////////// */

// Auxiliary parameters class
// C API descriptions has more details
class IwiCopyMakeBorderParams: public ::IwiCopyMakeBorderParams
{
public:
    IW_BASE_PARAMS_CONSTRUCTORS(IwiCopyMakeBorderParams, iwiCopyMakeBorder_SetDefaultParams)
    IwiCopyMakeBorderParams() {}
};

// Copies image data to destination image and constructs border of specified size.
// Destination image must have enough memory for a border according to inMemSize member.
// C API descriptions has more details.
// Throws:
//      ippStsNotSupportedModeErr           selected function mode is not supported
//      ippStsSizeErr                       1) size fields values are illegal
//                                          2) border.top or border.left are greater than corresponding inMemSize values of destination image
//                                          3) dst_width  + dst_inMemSize.right  < min_width  + border.right
//                                          4) dst_height + dst_inMemSize.bottom < min_height + border.bottom
//      ippStsNullPtrErr                    unexpected NULL pointer
// Returns:
//      ippStsNoErr                         no errors
IW_DECL_CPP(IppStatus) iwiCopyMakeBorder(
    const IwiImage                 &srcImage,                                   // [in]     Reference to the source image
    IwiImage                       &dstImage,                                   // [in,out] Reference to the destination image actual data start
    IwiBorderSize                   borderSize,                                 // [in]     Size of border to reconstruct
    IwiBorderType                   border,                                     // [in]     Extrapolation algorithm and value for out of image pixels: ippBorderConst, ippBorderRepl, ippBorderMirror, ippBorderWrap
    const IwiCopyMakeBorderParams  &auxParams   = IwiCopyMakeBorderParams(),    // [in]     Reference to the auxiliary parameters structure
    const IwiTile                  &tile        = IwiTile()                     // [in,out] Reference to the IwiTile object for tiling. By default no tiling is used
)
{
    IppStatus ippStatus = ::iwiCopyMakeBorder(&srcImage, &dstImage, borderSize, border.m_type, border.m_value, &auxParams, &tile);
    OWN_ERROR_CHECK(ippStatus)
    return ippStatus;
}

/**/////////////////////////////////////////////////////////////////////////////
//                   iwiSet
///////////////////////////////////////////////////////////////////////////// */

// Auxiliary parameters class
// C API descriptions has more details
class IwiSetParams: public ::IwiSetParams
{
public:
    IW_BASE_PARAMS_CONSTRUCTORS(IwiSetParams, iwiSet_SetDefaultParams)
    IwiSetParams() {}
};

// Sets each channel of the image to the specified values with masking.
// If mask is NULL, then calls iwiSet function.
// For masked operation, the function writes pixel values in the destination buffer only if the spatially corresponding
// mask array value is non-zero.
// C API descriptions has more details.
// Throws:
//      ippStsDataTypeErr                   data type is illegal
//      ippStsNumChannelsErr                channels value is illegal
//      ippStsSizeErr                       size fields values are illegal
//      ippStsNullPtrErr                    unexpected NULL pointer
// Returns:
//      ippStsNoErr                         no errors
IW_DECL_CPP(IppStatus) iwiSet(
    IwValueFloat        values,                         // [in]     Values to set to
    IwiImage           &dstImage,                       // [in,out] Reference to the destination image
    const IwiImage     &maskImage   = IwiImage(),       // [in]     Reference to the mask image. Mask must be 8-bit, 1 channel image
    const IwiSetParams &auxParams   = IwiSetParams(),   // [in]     Reference to the auxiliary parameters structure
    const IwiTile      &tile        = IwiTile()         // [in,out] Reference to the IwiTile object for tiling. By default no tiling is used
)
{
    IppStatus ippStatus = ::iwiSet(values, values.ValuesNum(), &dstImage, &maskImage, &auxParams, &tile);
    OWN_ERROR_CHECK(ippStatus)
    return ippStatus;
}

/**/////////////////////////////////////////////////////////////////////////////
//                   iwiSetChannel
///////////////////////////////////////////////////////////////////////////// */

// Auxiliary parameters class
// C API descriptions has more details
class IwiSetChannelParams: public ::IwiSetChannelParams
{
public:
    IW_BASE_PARAMS_CONSTRUCTORS(IwiSetChannelParams, iwiSetChannel_SetDefaultParams)
    IwiSetChannelParams() {}
};

// Sets selected channel of the multi-channel image to the specified value.
// C API descriptions has more details.
// Throws:
//      ippStsDataTypeErr                   data type is illegal
//      ippStsNumChannelsErr                channels value is illegal
//      ippStsSizeErr                       size fields values are illegal
//      ippStsNullPtrErr                    unexpected NULL pointer
// Returns:
//      ippStsNoErr                         no errors
IW_DECL_CPP(IppStatus) iwiSetChannel(
    double                      value,                                  // [in]     Value to set to
    IwiImage                   &dstImage,                               // [in,out] Reference to the destination image
    int                         channelNum,                             // [in]     Number of channel to be set (starting from 0)
    const IwiSetChannelParams  &auxParams   = IwiSetChannelParams(),    // [in]     Reference to the auxiliary parameters structure
    const IwiTile              &tile        = IwiTile()                 // [in,out] Reference to the IwiTile object for tiling. By default no tiling is used
)
{
    IppStatus ippStatus = ::iwiSetChannel(value, &dstImage, channelNum, &auxParams, &tile);
    OWN_ERROR_CHECK(ippStatus)
    return ippStatus;
}

/**/////////////////////////////////////////////////////////////////////////////
//                   iwiAdd
///////////////////////////////////////////////////////////////////////////// */

// Auxiliary parameters class
// C API descriptions has more details
class IwiAddParams: public ::IwiAddParams
{
public:
    IW_BASE_PARAMS_CONSTRUCTORS(IwiAddParams, iwiAdd_SetDefaultParams)
    IwiAddParams(int _scaleFactor = 0, IwiChDescriptor _chDesc = iwiChDesc_None)
    {
        this->scaleFactor = _scaleFactor;
        this->chDesc      = _chDesc;
    }
};

// Performs addition of one image to another and writes result to the output.
// C API descriptions has more details.
// Throws:
//      ippStsDataTypeErr                   data type is illegal
//      ippStsNumChannelsErr                channels value is illegal
//      ippStsSizeErr                       size fields values are illegal
//      ippStsNullPtrErr                    unexpected NULL pointer
// Returns:
//      ippStsNoErr                         no errors
IW_DECL_CPP(IppStatus) iwiAdd(
    const IwiImage      &src1Image,                     // [in]     Reference to the first addend image
    const IwiImage      &src2Image,                     // [in]     Reference to the second addend image
    IwiImage            &dstImage,                      // [in,out] Reference to the result image (can be same as the second addend)
    const IwiAddParams  &auxParams  = IwiAddParams(),   // [in]     Reference to the auxiliary parameters structure
    const IwiTile       &tile       = IwiTile()         // [in]     Reference to the IwiTile structure for tiling. By default no tiling is used
)
{
    IppStatus ippStatus = ::iwiAdd(&src1Image, &src2Image, &dstImage, &auxParams, &tile);
    OWN_ERROR_CHECK(ippStatus)
    return ippStatus;
}

/**/////////////////////////////////////////////////////////////////////////////
//                   iwiAddC
///////////////////////////////////////////////////////////////////////////// */

// Auxiliary parameters class
// C API descriptions has more details
class IwiAddCParams: public ::IwiAddCParams
{
public:
    IW_BASE_PARAMS_CONSTRUCTORS(IwiAddCParams, iwiAddC_SetDefaultParams)
    IwiAddCParams(int _scaleFactor = 0, IwiChDescriptor _chDesc = iwiChDesc_None)
    {
        this->scaleFactor = _scaleFactor;
        this->chDesc      = _chDesc;
    }
};

// Performs addition of the constant to the image another and writes result to the output.
// C API descriptions has more details.
// Returns:
//      ippStsDataTypeErr                   data type is illegal
//      ippStsNumChannelsErr                channels value is illegal
//      ippStsSizeErr                       size fields values are illegal
//      ippStsNullPtrErr                    unexpected NULL pointer
//      ippStsNoErr                         no errors
IW_DECL_CPP(IppStatus) iwiAddC(
    IwValueFloat         values,                        // [in]     Addends. One element for each channel
    const IwiImage      &srcImage,                      // [in]     Reference to the addend image
    IwiImage            &dstImage,                      // [in,out] Reference to the difference image (can be same as addend image)
    const IwiAddCParams &auxParams  = IwiAddCParams(),  // [in]     Reference to the auxiliary parameters structure
    const IwiTile       &tile       = IwiTile()         // [in]     Reference to the IwiTile structure for tiling. By default no tiling is used
)
{
    IppStatus ippStatus = ::iwiAddC(values, &srcImage, &dstImage, &auxParams, &tile);
    OWN_ERROR_CHECK(ippStatus)
    return ippStatus;
}

/**/////////////////////////////////////////////////////////////////////////////
//                   iwiSub
///////////////////////////////////////////////////////////////////////////// */

// Auxiliary parameters class
// C API descriptions has more details
class IwiSubParams: public ::IwiSubParams
{
public:
    IW_BASE_PARAMS_CONSTRUCTORS(IwiSubParams, iwiSub_SetDefaultParams)
    IwiSubParams(int _scaleFactor = 0, IwiChDescriptor _chDesc = iwiChDesc_None)
    {
        this->scaleFactor = _scaleFactor;
        this->chDesc      = _chDesc;
    }
};

// Performs subtraction of the first image from the second image and writes result to the output.
// C API descriptions has more details.
// Throws:
//      ippStsDataTypeErr                   data type is illegal
//      ippStsNumChannelsErr                channels value is illegal
//      ippStsSizeErr                       size fields values are illegal
//      ippStsNullPtrErr                    unexpected NULL pointer
// Returns:
//      ippStsNoErr                         no errors
IW_DECL_CPP(IppStatus) iwiSub(
    const IwiImage      &src1Image,                     // [in]     Reference to the subtrahend image
    const IwiImage      &src2Image,                     // [in]     Reference to the minuend image
    IwiImage            &dstImage,                      // [in,out] Reference to the difference image (can be same as minuend)
    const IwiSubParams  &auxParams  = IwiSubParams(),   // [in]     Reference to the auxiliary parameters structure
    const IwiTile       &tile       = IwiTile()         // [in]     Reference to the IwiTile structure for tiling. By default no tiling is used
)
{
    IppStatus ippStatus = ::iwiSub(&src1Image, &src2Image, &dstImage, &auxParams, &tile);
    OWN_ERROR_CHECK(ippStatus)
    return ippStatus;
}

/**/////////////////////////////////////////////////////////////////////////////
//                   iwiSubC
///////////////////////////////////////////////////////////////////////////// */

// Auxiliary parameters class
// C API descriptions has more details
class IwiSubCParams: public ::IwiSubCParams
{
public:
    IW_BASE_PARAMS_CONSTRUCTORS(IwiSubCParams, iwiSubC_SetDefaultParams)
    IwiSubCParams(int _scaleFactor = 0, IwiChDescriptor _chDesc = iwiChDesc_None)
    {
        this->scaleFactor = _scaleFactor;
        this->chDesc      = _chDesc;
    }
};

// Performs subtraction of the constant from the image and writes result to the output.
// C API descriptions has more details.
// Returns:
//      ippStsDataTypeErr                   data type is illegal
//      ippStsNumChannelsErr                channels value is illegal
//      ippStsSizeErr                       size fields values are illegal
//      ippStsNullPtrErr                    unexpected NULL pointer
//      ippStsNoErr                         no errors
IW_DECL_CPP(IppStatus) iwiSubC(
    IwValueFloat         values,                        // [in]     Subtrahends. One element for each channel
    const IwiImage      &srcImage,                      // [in]     Reference to the minuend image
    IwiImage            &dstImage,                      // [in,out] Reference to the difference image (can be same as minuend)
    const IwiSubCParams &auxParams  = IwiSubCParams(),  // [in]     Reference to the auxiliary parameters structure
    const IwiTile       &tile       = IwiTile()         // [in]     Reference to the IwiTile structure for tiling. By default no tiling is used
)
{
    IppStatus ippStatus = ::iwiSubC(values, &srcImage, &dstImage, &auxParams, &tile);
    OWN_ERROR_CHECK(ippStatus)
    return ippStatus;
}

/**/////////////////////////////////////////////////////////////////////////////
//                   iwiMul
///////////////////////////////////////////////////////////////////////////// */

// Auxiliary parameters class
// C API descriptions has more details
class IwiMulParams: public ::IwiMulParams
{
public:
    IW_BASE_PARAMS_CONSTRUCTORS(IwiMulParams, iwiMul_SetDefaultParams)
    IwiMulParams(int _scaleFactor = 0, IppHintAlgorithm _algoMode = ippAlgHintNone, IwiChDescriptor _chDesc = iwiChDesc_None)
    {
        this->algoMode          = _algoMode;
        this->scaleFactor       = _scaleFactor;
        this->chDesc            = _chDesc;
    }
};

// Performs multiplication of one image by another and writes result to the output
// C API descriptions has more details.
// Throws:
//      ippStsDataTypeErr                   data type is illegal
//      ippStsNumChannelsErr                channels value is illegal
//      ippStsSizeErr                       size fields values are illegal
//      ippStsNullPtrErr                    unexpected NULL pointer
// Returns:
//      ippStsNoErr                         no errors
IW_DECL_CPP(IppStatus) iwiMul(
    const IwiImage     &src1Image,                      // [in]     Reference to the first factor image
    const IwiImage     &src2Image,                      // [in]     Reference to the second factor image
    IwiImage           &dstImage,                       // [in,out] Reference to the product image (can be same as the second factor)
    const IwiMulParams &auxParams   = IwiMulParams(),   // [in]     Reference to the auxiliary parameters structure
    const IwiTile      &tile        = IwiTile()         // [in]     Reference to the IwiTile structure for tiling. By default no tiling is used
)
{
    IppStatus ippStatus = ::iwiMul(&src1Image, &src2Image, &dstImage, &auxParams, &tile);
    OWN_ERROR_CHECK(ippStatus)
    return ippStatus;
}

/**/////////////////////////////////////////////////////////////////////////////
//                   iwiMulC
///////////////////////////////////////////////////////////////////////////// */

// Auxiliary parameters class
// C API descriptions has more details
class IwiMulCParams: public ::IwiMulCParams
{
public:
    IW_BASE_PARAMS_CONSTRUCTORS(IwiMulCParams, iwiMulC_SetDefaultParams)
    IwiMulCParams(int _scaleFactor = 0, IppHintAlgorithm _algoMode = ippAlgHintNone, IppRoundMode _round = ippRndNear, IwiChDescriptor _chDesc = iwiChDesc_None)
    {
        this->roundMode   = _round;
        this->algoMode    = _algoMode;
        this->scaleFactor = _scaleFactor;
        this->chDesc      = _chDesc;
    }
};

// Performs multiplication of one image by constant and writes result to the output.
// C API descriptions has more details.
// Returns:
//      ippStsDataTypeErr                   data type is illegal
//      ippStsNumChannelsErr                channels value is illegal
//      ippStsSizeErr                       size fields values are illegal
//      ippStsNullPtrErr                    unexpected NULL pointer
//      ippStsNoErr                         no errors
IW_DECL_CPP(IppStatus) iwiMulC(
    IwValueFloat         values,                        // [in]     Factors. One element for each channel
    const IwiImage      &srcImage,                      // [in]     Reference to the factor image
    IwiImage            &dstImage,                      // [in,out] Reference to the product image (can be same as factor image)
    const IwiMulCParams &auxParams  = IwiMulCParams(),  // [in]     Reference to the auxiliary parameters structure
    const IwiTile       &tile       = IwiTile()         // [in]     Reference to the IwiTile structure for tiling. By default no tiling is used
)
{
    IppStatus ippStatus = ::iwiMulC(values, &srcImage, &dstImage, &auxParams, &tile);
    OWN_ERROR_CHECK(ippStatus)
    return ippStatus;
}

/**/////////////////////////////////////////////////////////////////////////////
//                   iwiDiv
///////////////////////////////////////////////////////////////////////////// */

// Auxiliary parameters class
// C API descriptions has more details
class IwiDivParams: public ::IwiDivParams
{
public:
    IW_BASE_PARAMS_CONSTRUCTORS(IwiDivParams, iwiDiv_SetDefaultParams)
    IwiDivParams(int _scaleFactor = 0, IppHintAlgorithm _algoMode = ippAlgHintNone, IwiChDescriptor _chDesc = iwiChDesc_None)
    {
        this->algoMode          = _algoMode;
        this->scaleFactor       = _scaleFactor;
        this->chDesc            = _chDesc;
    }
};

// Performs division of the second image by the first image and writes result to the output.
// C API descriptions has more details.
// Throws:
//      ippStsDataTypeErr                   data type is illegal
//      ippStsNumChannelsErr                channels value is illegal
//      ippStsSizeErr                       size fields values are illegal
//      ippStsNullPtrErr                    unexpected NULL pointer
// Returns:
//      ippStsNoErr                         no errors
IW_DECL_CPP(IppStatus) iwiDiv(
    const IwiImage     &src1Image,                      // [in]     Reference to the denominator image
    const IwiImage     &src2Image,                      // [in]     Reference to the numerator image
    IwiImage           &dstImage,                       // [in,out] Reference to the fraction image (can be same as numerator)
    const IwiDivParams &auxParams   = IwiDivParams(),   // [in]     Reference to the auxiliary parameters structure
    const IwiTile      &tile        = IwiTile()         // [in]     Reference to the IwiTile structure for tiling. By default no tiling is used
)
{
    IppStatus ippStatus = ::iwiDiv(&src1Image, &src2Image, &dstImage, &auxParams, &tile);
    OWN_ERROR_CHECK(ippStatus)
    return ippStatus;
}

/**/////////////////////////////////////////////////////////////////////////////
//                   iwiDivC
///////////////////////////////////////////////////////////////////////////// */

// Auxiliary parameters class
// C API descriptions has more details
class IwiDivCParams: public ::IwiDivCParams
{
public:
    IW_BASE_PARAMS_CONSTRUCTORS(IwiDivCParams, iwiDivC_SetDefaultParams)
    IwiDivCParams(int _scaleFactor = 0, IppHintAlgorithm _algoMode = ippAlgHintNone, IppRoundMode _round = ippRndNear, IwiChDescriptor _chDesc = iwiChDesc_None)
    {
        this->roundMode   = _round;
        this->algoMode    = _algoMode;
        this->scaleFactor = _scaleFactor;
        this->chDesc      = _chDesc;
    }
};

// Performs division of the second image by constant and writes result to the output.
// C API descriptions has more details.
// Returns:
//      ippStsDataTypeErr                   data type is illegal
//      ippStsNumChannelsErr                channels value is illegal
//      ippStsSizeErr                       size fields values are illegal
//      ippStsNullPtrErr                    unexpected NULL pointer
//      ippStsNoErr                         no errors
IW_DECL_CPP(IppStatus) iwiDivC(
    IwValueFloat         values,                        // [in]     Denominators. One element for each channel
    const IwiImage      &srcImage,                      // [in]     Reference to the numerator image
    IwiImage            &dstImage,                      // [in,out] Reference to the fraction image (can be same as numerator)
    const IwiDivCParams &auxParams  = IwiDivCParams(),  // [in]     Reference to the auxiliary parameters structure
    const IwiTile       &tile       = IwiTile()         // [in]     Reference to the IwiTile structure for tiling. By default no tiling is used
)
{
    IppStatus ippStatus = ::iwiDivC(values, &srcImage, &dstImage, &auxParams, &tile);
    OWN_ERROR_CHECK(ippStatus)
    return ippStatus;
}

/**/////////////////////////////////////////////////////////////////////////////
//                   iwiSwapChannels
///////////////////////////////////////////////////////////////////////////// */

// Auxiliary parameters class
// C API descriptions has more details
class IwiSwapChannelsParams: public ::IwiSwapChannelsParams
{
public:
    IW_BASE_PARAMS_CONSTRUCTORS(IwiSwapChannelsParams, iwiSwapChannels_SetDefaultParams)
    IwiSwapChannelsParams(IwiChDescriptor _chDesc = iwiChDesc_None)
    {
        this->chDesc = _chDesc;
    }
};

// Swaps image channels according to the destination order parameter.
// C API descriptions has more details.
// Throws:
//      ippStsChannelOrderErr               destination order is out of the range
//      ippStsDataTypeErr                   data type is illegal
//      ippStsNumChannelsErr                channels value is illegal
//      ippStsSizeErr                       size fields values are illegal
//      ippStsNullPtrErr                    unexpected NULL pointer
// Returns:
//      ippStsNoErr                         no errors
IW_DECL_CPP(IppStatus) iwiSwapChannels(
    const IwiImage              &srcImage,                              // [in]     Reference to the source image
    IwiImage                    &dstImage,                              // [in,out] Reference to the destination image
    const IwValueInt            &dstOrder,                              // [in]     Destination image channels order: dst[channel] = src[dstOrder[channel]]
    double                       value      = IwValueMax,               // [in]     Value to fill the destination channel if number of destination channels is bigger than number of source channels
    const IwiSwapChannelsParams &auxParams  = IwiSwapChannelsParams(),  // [in]     Reference to the auxiliary parameters structure
    const IwiTile               &tile       = IwiTile()                 // [in]     Reference to the IwiTile structure for tiling. By default no tiling is used
)
{
    IppStatus ippStatus   = ::iwiSwapChannels(&srcImage, &dstImage, dstOrder, value, &auxParams, &tile);
    OWN_ERROR_CHECK(ippStatus)
    return ippStatus;
}

/**/////////////////////////////////////////////////////////////////////////////
//                   iwiScale
///////////////////////////////////////////////////////////////////////////// */

// Auxiliary parameters class
// C API descriptions has more details
class IwiScaleParams: public ::IwiScaleParams
{
public:
    IW_BASE_PARAMS_CONSTRUCTORS(IwiScaleParams, iwiScale_SetDefaultParams)
    IwiScaleParams(IppHintAlgorithm _algoMode = ippAlgHintNone)
    {
        this->algoMode = _algoMode;
    }
};

// Converts image from one data type to another with specified scaling and shifting
// DST = saturate(SRC*mulVal + addVal)
// C API descriptions has more details.
// Throws:
//      ippStsDataTypeErr                   data type is illegal
//      ippStsSizeErr                       size fields values are illegal
//      ippStsInplaceModeNotSupportedErr    doesn't support output into the source buffer. If data types are different
//      ippStsNullPtrErr                    unexpected NULL pointer
// Returns:
//      ippStsNoErr                         no errors
IW_DECL_CPP(IppStatus) iwiScale(
    const IwiImage         &srcImage,                       // [in]     Reference to the source image
    IwiImage               &dstImage,                       // [in,out] Reference to the destination image
    Ipp64f                  mulVal,                         // [in]     Multiplier
    Ipp64f                  addVal,                         // [in]     Addend
    const IwiScaleParams   &auxParams   = IwiScaleParams(), // [in]     Reference to the auxiliary parameters structure
    const IwiTile          &tile        = IwiTile()         // [in]     Reference to the IwiTile object for tiling. By default no tiling is used
)
{
    IppStatus ippStatus = ::iwiScale(&srcImage, &dstImage, mulVal, addVal, &auxParams, &tile);
    OWN_ERROR_CHECK(ippStatus)
    return ippStatus;
}

// Returns multiplication and addend values for iwiScale function to perform accurate data range scaling between two data types
// Data range for float values is considered to be from 0 to 1
// Throws:
//      ippStsDataTypeErr                   data type is illegal
// Returns:
//      ippStsNoErr                         no errors
IW_DECL_CPP(IppStatus) iwiScale_GetScaleVals(
    IppDataType srcType,    // [in]     Source data type
    IppDataType dstType,    // [in]     Destination data type
    Ipp64f     &mulVal,     // [out]    Pointer to multiplier
    Ipp64f     &addVal      // [out]    Pointer to addend
)
{
    IppStatus ippStatus = ::iwiScale_GetScaleVals(srcType, dstType, &mulVal, &addVal);
    OWN_ERROR_CHECK(ippStatus)
    return ippStatus;
}

}

#endif
