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

/*
//   Purpose: Functions of Addition operation
//   Contents:
//       ippiRGBToLab_32f_P3R_T
//       ippiRGBToLab_64f_P3R_T
//       ippiLabToRGB_32f_P3R_T
//       ippiLabToRGB_64f_P3R_T
*/
#include "pirgbtolab_t.h"
IppStatus ippiRGBToLab_32f_P3R_T_Fun(int i, void *arg)
{
    ippiRGBLab_32f_T_Str *ts = (ippiRGBLab_32f_T_Str *)arg;
    const Ipp32f** pSrc = (const Ipp32f**)ts->pSrc;
    int srcStep[3];
    Ipp32f** pDst = ts->pDst;
    int dstStep[3];
    IppiSize roiSize = ts->roiSize;
    IppiPoint splitImage = ts->splitImage;
    IppiSize tileSize = ts->tileSize;
    IppiSize tailSize = ts->tailSize;

    Ipp32f *pSrcRoi[3] = {0, 0, 0};;
    Ipp32f       *pDstRoi[3] = {0, 0, 0};;
    IppiPoint    roiOffset;
    srcStep[0] = ts->srcStep[0];
    srcStep[1] = ts->srcStep[1];
    srcStep[2] = ts->srcStep[2];
    dstStep[0] = ts->dstStep[0];
    dstStep[1] = ts->dstStep[1];
    dstStep[2] = ts->dstStep[2];

    ippiGetTileParamsByIndex_T(i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    ippiGetTilePointer_32f_T(pSrc[0], &(pSrcRoi[0]), srcStep[0], roiOffset.x, roiOffset.y, (Ipp32s)1);
    ippiGetTilePointer_32f_T(pSrc[1], &(pSrcRoi[1]), srcStep[1], roiOffset.x, roiOffset.y, (Ipp32s)1);
    ippiGetTilePointer_32f_T(pSrc[2], &(pSrcRoi[2]), srcStep[2], roiOffset.x, roiOffset.y, (Ipp32s)1);
    ippiGetTilePointer_32f_T(pDst[0], &(pDstRoi[0]), dstStep[0], roiOffset.x, roiOffset.y, (Ipp32s)1);
    ippiGetTilePointer_32f_T(pDst[1], &(pDstRoi[1]), dstStep[1], roiOffset.x, roiOffset.y, (Ipp32s)1);
    ippiGetTilePointer_32f_T(pDst[2], &(pDstRoi[2]), dstStep[2], roiOffset.x, roiOffset.y, (Ipp32s)1);

    return ippiRGBToLab_32f_P3R((const Ipp32f **)pSrcRoi, srcStep, pDstRoi, dstStep, roiSize);
}
IppStatus ippiRGBToLab_64f_P3R_T_Fun(int i, void *arg)
{
    ippiRGBLab_64f_T_Str *ts = (ippiRGBLab_64f_T_Str *)arg;
    const Ipp64f** pSrc = (const Ipp64f**)ts->pSrc;
    int srcStep[3];
    Ipp64f** pDst = ts->pDst;
    int dstStep[3];
    IppiSize roiSize = ts->roiSize;
    IppiPoint splitImage = ts->splitImage;
    IppiSize tileSize = ts->tileSize;
    IppiSize tailSize = ts->tailSize;

    Ipp64f *pSrcRoi[3] = {0, 0, 0};;
    Ipp64f       *pDstRoi[3] = {0, 0, 0};;
    IppiPoint    roiOffset;

    srcStep[0] = ts->srcStep[0];
    srcStep[1] = ts->srcStep[1];
    srcStep[2] = ts->srcStep[2];
    dstStep[0] = ts->dstStep[0];
    dstStep[1] = ts->dstStep[1];
    dstStep[2] = ts->dstStep[2];

    ippiGetTileParamsByIndex_T(i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    ippiGetTilePointer_64f_T(pSrc[0], &(pSrcRoi[0]), srcStep[0], roiOffset.x, roiOffset.y, (Ipp32s)1);
    ippiGetTilePointer_64f_T(pSrc[1], &(pSrcRoi[1]), srcStep[1], roiOffset.x, roiOffset.y, (Ipp32s)1);
    ippiGetTilePointer_64f_T(pSrc[2], &(pSrcRoi[2]), srcStep[2], roiOffset.x, roiOffset.y, (Ipp32s)1);
    ippiGetTilePointer_64f_T(pDst[0], &(pDstRoi[0]), dstStep[0], roiOffset.x, roiOffset.y, (Ipp32s)1);
    ippiGetTilePointer_64f_T(pDst[1], &(pDstRoi[1]), dstStep[1], roiOffset.x, roiOffset.y, (Ipp32s)1);
    ippiGetTilePointer_64f_T(pDst[2], &(pDstRoi[2]), dstStep[2], roiOffset.x, roiOffset.y, (Ipp32s)1);

    return ippiRGBToLab_64f_P3R((const Ipp64f **)pSrcRoi, srcStep, pDstRoi, dstStep, roiSize);
}
IppStatus ippiLabToRGB_32f_P3R_T_Fun(int i, void *arg)
{
    ippiRGBLab_32f_T_Str *ts = (ippiRGBLab_32f_T_Str *)arg;
    const Ipp32f** pSrc = (const Ipp32f**)ts->pSrc;
    int srcStep[3];
    Ipp32f** pDst = ts->pDst;
    int dstStep[3];
    IppiSize roiSize = ts->roiSize;
    IppiPoint splitImage = ts->splitImage;
    IppiSize tileSize = ts->tileSize;
    IppiSize tailSize = ts->tailSize;

    Ipp32f *pSrcRoi[3] = {0, 0, 0};;
    Ipp32f       *pDstRoi[3] = {0, 0, 0};;
    IppiPoint    roiOffset;

    srcStep[0] = ts->srcStep[0];
    srcStep[1] = ts->srcStep[1];
    srcStep[2] = ts->srcStep[2];
    dstStep[0] = ts->dstStep[0];
    dstStep[1] = ts->dstStep[1];
    dstStep[2] = ts->dstStep[2];

    ippiGetTileParamsByIndex_T(i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    ippiGetTilePointer_32f_T(pSrc[0], &(pSrcRoi[0]), srcStep[0], roiOffset.x, roiOffset.y, (Ipp32s)1);
    ippiGetTilePointer_32f_T(pSrc[1], &(pSrcRoi[1]), srcStep[1], roiOffset.x, roiOffset.y, (Ipp32s)1);
    ippiGetTilePointer_32f_T(pSrc[2], &(pSrcRoi[2]), srcStep[2], roiOffset.x, roiOffset.y, (Ipp32s)1);
    ippiGetTilePointer_32f_T(pDst[0], &(pDstRoi[0]), dstStep[0], roiOffset.x, roiOffset.y, (Ipp32s)1);
    ippiGetTilePointer_32f_T(pDst[1], &(pDstRoi[1]), dstStep[1], roiOffset.x, roiOffset.y, (Ipp32s)1);
    ippiGetTilePointer_32f_T(pDst[2], &(pDstRoi[2]), dstStep[2], roiOffset.x, roiOffset.y, (Ipp32s)1);

    return ippiLabToRGB_32f_P3R((const Ipp32f **)pSrcRoi, srcStep, pDstRoi, dstStep, roiSize);
}
IppStatus ippiLabToRGB_64f_P3R_T_Fun(int i, void *arg)
{
    ippiRGBLab_64f_T_Str *ts = (ippiRGBLab_64f_T_Str *)arg;
    const Ipp64f** pSrc = (const Ipp64f**)ts->pSrc;
    int srcStep[3];
    Ipp64f** pDst = ts->pDst;
    int dstStep[3];
    IppiSize roiSize = ts->roiSize;
    IppiPoint splitImage = ts->splitImage;
    IppiSize tileSize = ts->tileSize;
    IppiSize tailSize = ts->tailSize;

    Ipp64f *pSrcRoi[3] = {0, 0, 0};;
    Ipp64f       *pDstRoi[3] = {0, 0, 0};;
    IppiPoint    roiOffset;
    srcStep[0] = ts->srcStep[0];
    srcStep[1] = ts->srcStep[1];
    srcStep[2] = ts->srcStep[2];
    dstStep[0] = ts->dstStep[0];
    dstStep[1] = ts->dstStep[1];
    dstStep[2] = ts->dstStep[2];

    ippiGetTileParamsByIndex_T(i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

    /* compute pointers to ROIs */
    ippiGetTilePointer_64f_T(pSrc[0], &(pSrcRoi[0]), srcStep[0], roiOffset.x, roiOffset.y, (Ipp32s)1);
    ippiGetTilePointer_64f_T(pSrc[1], &(pSrcRoi[1]), srcStep[1], roiOffset.x, roiOffset.y, (Ipp32s)1);
    ippiGetTilePointer_64f_T(pSrc[2], &(pSrcRoi[2]), srcStep[2], roiOffset.x, roiOffset.y, (Ipp32s)1);
    ippiGetTilePointer_64f_T(pDst[0], &(pDstRoi[0]), dstStep[0], roiOffset.x, roiOffset.y, (Ipp32s)1);
    ippiGetTilePointer_64f_T(pDst[1], &(pDstRoi[1]), dstStep[1], roiOffset.x, roiOffset.y, (Ipp32s)1);
    ippiGetTilePointer_64f_T(pDst[2], &(pDstRoi[2]), dstStep[2], roiOffset.x, roiOffset.y, (Ipp32s)1);

    return ippiLabToRGB_64f_P3R((const Ipp64f **)pSrcRoi, srcStep, pDstRoi, dstStep, roiSize);
}

IPPFUN(IppStatus, ippiRGBToLab_32f_P3R_T, (const Ipp32f* pSrc[3], int srcStep[3], Ipp32f* pDst[3], int dstStep[3], IppiSize roiSize))
{
    IppStatus status = ippStsNoErr;
    int numTiles = 0;
    int pixelSize = 1 * sizeof(Ipp32f);

    IppiPoint splitImage;
    IppiSize  tileSize, tailSize;
    int   minTileSize = IPP64_MIN_RGBLAB_2D / pixelSize;

    if (pSrc == 0 || pDst == 0)     return ippStsNullPtrErr;
    if (pSrc[0] == 0 || pSrc[1] == 0 || pSrc[2] == 0)     return ippStsNullPtrErr;
    if (roiSize.width <= 0 || roiSize.height <= 0) return ippStsSizeErr;

    /* split the image to tiles */
    ippiSplitUniform2D_T(roiSize, minTileSize, &splitImage, &tileSize, &tailSize);

    if (splitImage.x == 1 && splitImage.y == 1)
    {
        status = ippiRGBToLab_32f_P3R(pSrc, srcStep, pDst, dstStep, roiSize);
    }
    else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiRGBLab_32f_T_Str ts;
        RGBLabThreadingStructureEncode_32f_T(pSrc, srcStep, pDst, dstStep, roiSize, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_T(numTiles, (void*)&ts, ippiRGBToLab_32f_P3R_T_Fun);
    }

    return status;
}
IPPFUN(IppStatus, ippiRGBToLab_64f_P3R_T, (const Ipp64f* pSrc[3], int srcStep[3], Ipp64f* pDst[3], int dstStep[3], IppiSize roiSize))
{
    IppStatus status = ippStsNoErr;
    int numTiles = 0;
    int pixelSize = 1 * sizeof(Ipp64f);

    IppiPoint splitImage;
    IppiSize  tileSize, tailSize;
    int   minTileSize = IPP64_MIN_RGBLAB_2D / pixelSize;

    if (pSrc == 0 || pDst == 0)     return ippStsNullPtrErr;
    if (pSrc[0] == 0 || pSrc[1] == 0 || pSrc[2] == 0)     return ippStsNullPtrErr;
    if (roiSize.width <= 0 || roiSize.height <= 0) return ippStsSizeErr;

    /* split the image to tiles */
    ippiSplitUniform2D_T(roiSize, minTileSize, &splitImage, &tileSize, &tailSize);

    if (splitImage.x == 1 && splitImage.y == 1)
    {
        status = ippiRGBToLab_64f_P3R(pSrc, srcStep, pDst, dstStep, roiSize);
    }
    else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiRGBLab_64f_T_Str ts;
        RGBLabThreadingStructureEncode_64f_T(pSrc, srcStep, pDst, dstStep, roiSize, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_T(numTiles, (void*)&ts, ippiRGBToLab_64f_P3R_T_Fun);
    }

    return status;
}
IPPFUN(IppStatus, ippiLabToRGB_32f_P3R_T, (const Ipp32f* pSrc[3], int srcStep[3], Ipp32f* pDst[3], int dstStep[3], IppiSize roiSize))
{
    IppStatus status = ippStsNoErr;
    int numTiles = 0;
    int pixelSize = 1 * sizeof(Ipp32f);

    IppiPoint splitImage;
    IppiSize  tileSize, tailSize;
    int   minTileSize = IPP64_MIN_RGBLAB_2D / pixelSize;

    if (pSrc == 0 || pDst == 0)     return ippStsNullPtrErr;
    if (pSrc[0] == 0 || pSrc[1] == 0 || pSrc[2] == 0)     return ippStsNullPtrErr;
    if (roiSize.width <= 0 || roiSize.height <= 0) return ippStsSizeErr;

    /* split the image to tiles */
    ippiSplitUniform2D_T(roiSize, minTileSize, &splitImage, &tileSize, &tailSize);

    if (splitImage.x == 1 && splitImage.y == 1)
    {
        status = ippiLabToRGB_32f_P3R(pSrc, srcStep, pDst, dstStep, roiSize);
    }
    else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiRGBLab_32f_T_Str ts;
        RGBLabThreadingStructureEncode_32f_T(pSrc, srcStep, pDst, dstStep, roiSize, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_T(numTiles, (void*)&ts, ippiLabToRGB_32f_P3R_T_Fun);
    }

    return status;
}
IPPFUN(IppStatus, ippiLabToRGB_64f_P3R_T, (const Ipp64f* pSrc[3], int srcStep[3], Ipp64f* pDst[3], int dstStep[3], IppiSize roiSize))
{
    IppStatus status = ippStsNoErr;
    int numTiles = 0;
    int pixelSize = 1 * sizeof(Ipp64f);

    IppiPoint splitImage;
    IppiSize  tileSize, tailSize;
    int   minTileSize = IPP64_MIN_RGBLAB_2D / pixelSize;

    if (pSrc == 0 || pDst == 0)     return ippStsNullPtrErr;
    if (pSrc[0] == 0 || pSrc[1] == 0 || pSrc[2] == 0)     return ippStsNullPtrErr;
    if (roiSize.width <= 0 || roiSize.height <= 0) return ippStsSizeErr;

    /* split the image to tiles */
    ippiSplitUniform2D_T(roiSize, minTileSize, &splitImage, &tileSize, &tailSize);

    if (splitImage.x == 1 && splitImage.y == 1)
    {
        status = ippiLabToRGB_64f_P3R(pSrc, srcStep, pDst, dstStep, roiSize);
    }
    else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiRGBLab_64f_T_Str ts;
        RGBLabThreadingStructureEncode_64f_T(pSrc, srcStep, pDst, dstStep, roiSize, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_T(numTiles, (void*)&ts, ippiLabToRGB_64f_P3R_T_Fun);
    }

    return status;
}

