/*******************************************************************************
* Copyright 2016-2020 Intel Corporation.
*
* This software and the related documents are Intel copyrighted  materials,  and
* your use of  them is  governed by the  express license  under which  they were
* provided to you (License).  Unless the License provides otherwise, you may not
* use, modify, copy, publish, distribute,  disclose or transmit this software or
* the related documents without Intel's prior written permission.
*
* This software and the related documents  are provided as  is,  with no express
* or implied  warranties,  other  than those  that are  expressly stated  in the
* License.
*******************************************************************************/

#if !defined( __IPP_RESIZE_IPP__ )
#define __IPP_RESIZE_IPP__

#include "ipps.h"
#include "iw_resize_base.h"

class ResizeLinear_8u_C1: public ResizeBase
{
public:
    ResizeLinear_8u_C1(ParallelInterface parallel = PARALLEL_NONE)
    {
        m_pSpec     = 0;
        m_className = "ResizeLinear_8u_C1";
        SetParallelInterface(parallel);
    }

    ~ResizeLinear_8u_C1()
    {
        if(m_pSpec)
        {
            ippsFree(m_pSpec);
            m_pSpec = 0;
        }
    }

    Status Init(Image &src, Image &dst, IppiInterpolationType)
    {
        IppStatus       ippSts;
        IppSizeL        iSpecSize = 0;
        IppSizeL        iInitSize = 0;

        IppiSizeL srcSize = ImageSizeToIpp(src.m_size);
        IppiSizeL dstSize = ImageSizeToIpp(dst.m_size);

        // Get sizes for internal and initialization buffers
        ippSts = ippiResizeGetSize_L(srcSize, dstSize, ipp8u, ippLinear, 0, &iSpecSize, &iInitSize);
        CHECK_STATUS_PRINT_AC(ippSts, "ippiResizeGetSize_L()", ippGetStatusString(ippSts), return STS_ERR_FAILED);

        // allocate internal buffer
        m_pSpec = (IppiResizeSpec*)ippsMalloc_8u_L(iSpecSize);
        if(iSpecSize && !m_pSpec)
        {
            PRINT_MESSAGE("Cannot allocate memory for resize spec");
            return STS_ERR_ALLOC;
        }

        // init ipp resizer
        ippSts = ippiResizeLinearInit_L(srcSize, dstSize, ipp8u, m_pSpec);
        CHECK_STATUS_PRINT_AC(ippSts, "ippiResizeLinearInit_L()", ippGetStatusString(ippSts), return STS_ERR_FAILED);

        return STS_OK;
    }

    Status Run(Image &src, Image &dst, Rect roi)
    {
        IppStatus   ippSts;

        IppiPointL   dstRoiOffset = {(IppSizeL)roi.x, (IppSizeL)roi.y};
        IppiSizeL    dstRoiSize   = {(IppSizeL)roi.width, (IppSizeL)roi.height};
        IppiPointL   srcRoiOffset;
        IppiSizeL    srcRoiSize;

        unsigned char *pSrcPtr = 0;
        unsigned char *pDstPtr = 0;
        unsigned char *pBuffer = 0;
        IppSizeL       iBufferSize = 0;

        if(!m_pSpec)
            return STS_ERR_NOT_INITIALIZED;

        // get src ROI from dst ROI
        ippSts = ippiResizeGetSrcRoi_L(m_pSpec, dstRoiOffset, dstRoiSize, &srcRoiOffset, &srcRoiSize);
        CHECK_STATUS_PRINT_AC(ippSts, "ippiResizeGetSrcRoi_L()", ippGetStatusString(ippSts), return STS_ERR_FAILED);

        // adjust input and output buffers to current ROI
        pSrcPtr = (unsigned char*)src.ptr(srcRoiOffset.y, srcRoiOffset.x);
        pDstPtr = (unsigned char*)dst.ptr(dstRoiOffset.y, dstRoiOffset.x);

        ippSts = ippiResizeGetBufferSize_L(m_pSpec, dstRoiSize, src.m_samples, &iBufferSize);
        CHECK_STATUS_PRINT_AC(ippSts, "ippiResizeGetBufferSize_L()", ippGetStatusString(ippSts), return STS_ERR_FAILED);

        pBuffer = ippsMalloc_8u_L(iBufferSize);
        if(iBufferSize && !pBuffer)
        {
            PRINT_MESSAGE("Cannot allocate memory for resize buffer");
            return STS_ERR_ALLOC;
        }

        // perform resize
        ippSts = ippiResizeLinear_8u_C1R_L(pSrcPtr, (IppSizeL)src.m_step, pDstPtr, (IppSizeL)dst.m_step, dstRoiOffset, dstRoiSize, ippBorderRepl, 0, m_pSpec, pBuffer);
        CHECK_STATUS_PRINT_AC(ippSts, "ippiResizeLinear_8u_C1RL()", ippGetStatusString(ippSts), return STS_ERR_FAILED);

        if(pBuffer)
            ippsFree(pBuffer);

        return STS_OK;
    }

protected:
    IppiResizeSpec *m_pSpec;
};

#endif
