/*******************************************************************************
* Copyright 2015-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.
*******************************************************************************/

#ifndef PIRESIZEN_TL_H__
#define PIRESIZEN_TL_H__

#include "ippcore.h"
#include "owndefs_tl.h"
#include "ippcore_tl.h"
#include "ipps.h"
#include "ippi.h"
#include "owni_tl.h"
#include "ownisplit_tl.h"

#ifdef USE_OMP
 #include <omp.h>
#endif

/* Heuristic constants for image tiling */
#define RESIZE_NEAREST_MIN_PIX_NUMBER     (256 * 128)
#define RESIZE_LINEAR_MIN_PIX_NUMBER      (256 * 224)
#define RESIZE_CUBIC_MIN_PIX_NUMBER       (256 * 224)
#define RESIZE_LANCZOS_MIN_PIX_NUMBER     RESIZE_CUBIC_MIN_PIX_NUMBER
#define RESIZE_SUPER_MIN_PIX_NUMBER       (256 * 192)

/* Image size restrictions for tiling */
#define RESIZE_TILE_THRESHOLD       (1280 * 720)

typedef struct
{
    IppiPointL             split;
    IppiSizeL             tileSize;
    IppiSizeL             lastTile;
    IppDataType           dataType;
    IppiSizeL             srcSize;
    IppiSizeL             dstSize;
    Ipp32u                numChannels;
    IppiBorderSize        borderSize;
    IppiInterpolationType interp;
}
ResizeInfo;

/* ////////////// 8u ////////////////////// */


typedef struct _ippiResize_8u_LT_Str
{
    Ipp8u* pSrc;
    IppSizeL srcStep;
    Ipp8u* pDst;
    IppSizeL dstStep;
    IppiBorderType border;
    Ipp8u* pBorderValue;
    Ipp8u* pBuffer;
    Ipp32u numChannels;
    IppSizeL tileBufferSize;
    IppiResizeSpec *pResizeSpec;
    ResizeInfo *pResizeInfo;
} ippiResize_8u_LT_Str;

static void resizeThreadingStructureEncode_8u(
    Ipp8u* pSrc,
    IppSizeL srcStep,
    Ipp8u* pDst,
    IppSizeL dstStep,
    IppiBorderType border,
    Ipp8u* pBorderValue,
    Ipp8u* pBuffer,
    Ipp32u numChannels,
    IppSizeL tileBufferSize,
    IppiResizeSpec *pResizeSpec,
    ResizeInfo *pResizeInfo,
    ippiResize_8u_LT_Str *ts
)
{
    ts->pSrc = pSrc;
    ts->srcStep = srcStep;
    ts->pDst = pDst;
    ts->dstStep = dstStep;
    ts->border = border;
    ts->pBorderValue = pBorderValue;
    ts->pBuffer = pBuffer;
    ts->numChannels = numChannels;
    ts->tileBufferSize = tileBufferSize;
    ts->pResizeSpec = pResizeSpec;
    ts->pResizeInfo = pResizeInfo;
}

/* ////////////// 16u ////////////////////// */

typedef struct _ippiResize_16u_LT_Str
{
    Ipp16u* pSrc;
    IppSizeL srcStep;
    Ipp16u* pDst;
    IppSizeL dstStep;
    IppiBorderType border;
    Ipp16u* pBorderValue;
    Ipp8u* pBuffer;
    Ipp32u numChannels;
    IppSizeL tileBufferSize;
    IppiResizeSpec *pResizeSpec;
    ResizeInfo *pResizeInfo;
} ippiResize_16u_LT_Str;

static void resizeThreadingStructureEncode_16u(
    Ipp16u* pSrc,
    IppSizeL srcStep,
    Ipp16u* pDst,
    IppSizeL dstStep,
    IppiBorderType border,
    Ipp16u* pBorderValue,
    Ipp8u* pBuffer,
    Ipp32u numChannels,
    IppSizeL tileBufferSize,
    IppiResizeSpec *pResizeSpec,
    ResizeInfo *pResizeInfo,
    ippiResize_16u_LT_Str *ts
)
{
    ts->pSrc = pSrc;
    ts->srcStep = srcStep;
    ts->pDst = pDst;
    ts->dstStep = dstStep;
    ts->border = border;
    ts->pBorderValue = pBorderValue;
    ts->pBuffer = pBuffer;
    ts->numChannels = numChannels;
    ts->tileBufferSize = tileBufferSize;
    ts->pResizeSpec = pResizeSpec;
    ts->pResizeInfo = pResizeInfo;
}

/* ////////////// 16s ////////////////////// */

typedef struct _ippiResize_16s_LT_Str
{
    Ipp16s* pSrc;
    IppSizeL srcStep;
    Ipp16s* pDst;
    IppSizeL dstStep;
    IppiBorderType border;
    Ipp16s* pBorderValue;
    Ipp8u* pBuffer;
    Ipp32u numChannels;
    IppSizeL tileBufferSize;
    IppiResizeSpec *pResizeSpec;
    ResizeInfo *pResizeInfo;
} ippiResize_16s_LT_Str;

static void resizeThreadingStructureEncode_16s(
    Ipp16s* pSrc,
    IppSizeL srcStep,
    Ipp16s* pDst,
    IppSizeL dstStep,
    IppiBorderType border,
    Ipp16s* pBorderValue,
    Ipp8u* pBuffer,
    Ipp32u numChannels,
    IppSizeL tileBufferSize,
    IppiResizeSpec *pResizeSpec,
    ResizeInfo *pResizeInfo,
    ippiResize_16s_LT_Str *ts
)
{
    ts->pSrc = pSrc;
    ts->srcStep = srcStep;
    ts->pDst = pDst;
    ts->dstStep = dstStep;
    ts->border = border;
    ts->pBorderValue = pBorderValue;
    ts->pBuffer = pBuffer;
    ts->numChannels = numChannels;
    ts->tileBufferSize = tileBufferSize;
    ts->pResizeSpec = pResizeSpec;
    ts->pResizeInfo = pResizeInfo;
}

/* ////////////// 32f ////////////////////// */

typedef struct _ippiResize_32f_LT_Str
{
    Ipp32f* pSrc;
    IppSizeL srcStep;
    Ipp32f* pDst;
    IppSizeL dstStep;
    IppiBorderType border;
    Ipp32f* pBorderValue;
    Ipp8u* pBuffer;
    Ipp32u numChannels;
    IppSizeL tileBufferSize;
    IppiResizeSpec *pResizeSpec;
    ResizeInfo *pResizeInfo;
} ippiResize_32f_LT_Str;

static void resizeThreadingStructureEncode_32f(
    Ipp32f* pSrc,
    IppSizeL srcStep,
    Ipp32f* pDst,
    IppSizeL dstStep,
    IppiBorderType border,
    Ipp32f* pBorderValue,
    Ipp8u* pBuffer,
    Ipp32u numChannels,
    IppSizeL tileBufferSize,
    IppiResizeSpec *pResizeSpec,
    ResizeInfo *pResizeInfo,
    ippiResize_32f_LT_Str *ts
)
{
    ts->pSrc = pSrc;
    ts->srcStep = srcStep;
    ts->pDst = pDst;
    ts->dstStep = dstStep;
    ts->border = border;
    ts->pBorderValue = pBorderValue;
    ts->pBuffer = pBuffer;
    ts->numChannels = numChannels;
    ts->tileBufferSize = tileBufferSize;
    ts->pResizeSpec = pResizeSpec;
    ts->pResizeInfo = pResizeInfo;
}

/* ////////////// 64f ////////////////////// */

typedef struct _ippiResize_64f_LT_Str
{
    Ipp64f* pSrc;
    IppSizeL srcStep;
    Ipp64f* pDst;
    IppSizeL dstStep;
    IppiBorderType border;
    Ipp64f* pBorderValue;
    Ipp8u* pBuffer;
    Ipp32u numChannels;
    IppSizeL tileBufferSize;
    IppiResizeSpec *pResizeSpec;
    ResizeInfo *pResizeInfo;
} ippiResize_64f_LT_Str;

static void resizeThreadingStructureEncode_64f(
    Ipp64f* pSrc,
    IppSizeL srcStep,
    Ipp64f* pDst,
    IppSizeL dstStep,
    IppiBorderType border,
    Ipp64f* pBorderValue,
    Ipp8u* pBuffer,
    Ipp32u numChannels,
    IppSizeL tileBufferSize,
    IppiResizeSpec *pResizeSpec,
    ResizeInfo *pResizeInfo,
    ippiResize_64f_LT_Str *ts
)
{
    ts->pSrc = pSrc;
    ts->srcStep = srcStep;
    ts->pDst = pDst;
    ts->dstStep = dstStep;
    ts->border = border;
    ts->pBorderValue = pBorderValue;
    ts->pBuffer = pBuffer;
    ts->numChannels = numChannels;
    ts->tileBufferSize = tileBufferSize;
    ts->pResizeSpec = pResizeSpec;
    ts->pResizeInfo = pResizeInfo;
}

/* ///////////////////////////////////////// */

int owniGetThreadNumber();

int owniResizeGetDataSize(IppDataType dataType);

void owniResizeGetTileByIndex(int index, IppiPointL splitImage, IppiSizeL tileSize, IppiSizeL tailSize, IppiPointL *pTileOffset, IppiSizeL *pTileSize);

IppStatus owniResizeGetCopySize(const IppiResizeSpec_LT* pSpec, IppSizeL srcStep, IppSizeL dstStep, IppiSizeL* srcTileCopy, IppiSizeL* dstTileCopy);

IppStatus owniResizeCopyRoi(const Ipp8u* pSrc, IppSizeL srcStep, Ipp8u* pDst, IppSizeL dstStep, int numChannels, IppDataType dataType, IppiSizeL roi);

IppStatus owniResizeCopyRoiWithBorder(const Ipp8u* pSrc, IppSizeL srcStep, Ipp8u* pDst, IppSizeL dstStep, int numChannels, IppDataType dataType, IppiSizeL roi, IppiBorderSize borderSize);

IppStatus owniResizeGetTileBufferSize(const IppiResizeSpec_LT* pSpec, int numChannels, IppSizeL *pBufferSize);

IppStatus owniResizeCorrectBorderSize(const ResizeInfo * pResizeInfo, IppiPointL roiOffset, IppiSizeL roiSize, IppiBorderType borderType, IppiBorderSize* pBorderSize);

IppStatus owniResizeGetSrcRoi_LP(const void* pSpec, IppiPointL dstRoiOffset, IppiSizeL dstRoiSize, IppDataType dataType, IppiPointL* pSrcRoiOffset, IppiSizeL* pSrcRoiSize);

IppStatus owniResizeGetBufferSize_LP(const void* pSpec, IppiSizeL dstSize, Ipp32u numChannels, IppDataType dataType, int* pBufSize);

IppStatus owniResizeGetBorderSize_LP (const void* pSpec, IppDataType dataType, IppiBorderSize* pBorderSize);
#endif // PIRESIZEN_TL_H__
