/*******************************************************************************
* 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_LT
//       ippiRGBToLab_64f_P3R_LT
//       ippiLabToRGB_32f_P3R_LT
//       ippiLabToRGB_64f_P3R_LT
*/
#include "pirgbtolab_tl.h"
IppStatus ippiRGBToLab_32f_P3R_LT_Fun(IppSizeL i, void *arg)
{
    ippiRGBLab_32f_LT_Str *ts = (ippiRGBLab_32f_LT_Str *)arg;
    const Ipp32f** pSrc = (const Ipp32f**)ts->pSrc;
    IppSizeL srcStep[3];
    Ipp32f** pDst = ts->pDst;
    IppSizeL dstStep[3];
    IppiSizeL roiSize = ts->roiSize;
    IppiPointL splitImage = ts->splitImage;
    IppiSizeL tileSize = ts->tileSize;
    IppiSizeL tailSize = ts->tailSize;

    Ipp32f *pSrcRoi[3] = {0, 0, 0};
    Ipp32f       *pDstRoi[3] = {0, 0, 0};
    IppiPointL    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_LT(i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

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

    return ippiRGBToLab_32f_P3R_L((const Ipp32f **)pSrcRoi, srcStep, pDstRoi, dstStep, roiSize);
}
IppStatus ippiRGBToLab_64f_P3R_LT_Fun(IppSizeL i, void *arg)
{
    ippiRGBLab_64f_LT_Str *ts = (ippiRGBLab_64f_LT_Str *)arg;
    const Ipp64f** pSrc = (const Ipp64f**)ts->pSrc;
    IppSizeL srcStep[3];
    Ipp64f** pDst = ts->pDst;
    IppSizeL dstStep[3];
    IppiSizeL roiSize = ts->roiSize;
    IppiPointL splitImage = ts->splitImage;
    IppiSizeL tileSize = ts->tileSize;
    IppiSizeL tailSize = ts->tailSize;

    Ipp64f *pSrcRoi[3] = {0, 0, 0};;
    Ipp64f       *pDstRoi[3] = {0, 0, 0};;
    IppiPointL    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_LT(i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

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

    return ippiRGBToLab_64f_P3R_L((const Ipp64f **)pSrcRoi, srcStep, pDstRoi, dstStep, roiSize);
}
IppStatus ippiLabToRGB_32f_P3R_LT_Fun(IppSizeL i, void *arg)
{
    ippiRGBLab_32f_LT_Str *ts = (ippiRGBLab_32f_LT_Str *)arg;
    const Ipp32f** pSrc = (const Ipp32f**)ts->pSrc;
    IppSizeL srcStep[3];
    Ipp32f** pDst = ts->pDst;
    IppSizeL dstStep[3];
    IppiSizeL roiSize = ts->roiSize;
    IppiPointL splitImage = ts->splitImage;
    IppiSizeL tileSize = ts->tileSize;
    IppiSizeL tailSize = ts->tailSize;

    Ipp32f *pSrcRoi[3] = {0, 0, 0};;
    Ipp32f       *pDstRoi[3] = {0, 0, 0};;
    IppiPointL    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_LT(i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

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

    return ippiLabToRGB_32f_P3R_L((const Ipp32f **)pSrcRoi, srcStep, pDstRoi, dstStep, roiSize);
}
IppStatus ippiLabToRGB_64f_P3R_LT_Fun(IppSizeL i, void *arg)
{
    ippiRGBLab_64f_LT_Str *ts = (ippiRGBLab_64f_LT_Str *)arg;
    const Ipp64f** pSrc = (const Ipp64f**)ts->pSrc;
    IppSizeL srcStep[3];
    Ipp64f** pDst = ts->pDst;
    IppSizeL dstStep[3];
    IppiSizeL roiSize = ts->roiSize;
    IppiPointL splitImage = ts->splitImage;
    IppiSizeL tileSize = ts->tileSize;
    IppiSizeL tailSize = ts->tailSize;

    Ipp64f *pSrcRoi[3] = {0, 0, 0};
    Ipp64f       *pDstRoi[3] = {0, 0, 0};
    IppiPointL    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_LT(i, splitImage, tileSize, tailSize, &roiOffset, &roiSize);

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

    return ippiLabToRGB_64f_P3R_L((const Ipp64f **)pSrcRoi, srcStep, pDstRoi, dstStep, roiSize);
}
IPPFUN(IppStatus, ippiRGBToLab_32f_P3R_LT, (const Ipp32f* pSrc[3], IppSizeL srcStep[3], Ipp32f* pDst[3], IppSizeL dstStep[3], IppiSizeL roiSize))
{
    IppStatus status = ippStsNoErr;
    IppSizeL numTiles = 0;
    IppSizeL pixelSize = 1 * sizeof (Ipp32f);

    IppiPointL splitImage;
    IppiSizeL  tileSize, tailSize;
    IppSizeL   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_LT (roiSize, minTileSize, &splitImage, &tileSize, &tailSize);

    if (splitImage.x == 1 && splitImage.y == 1)
    {
        status = ippiRGBToLab_32f_P3R_L(pSrc, srcStep, pDst, dstStep, roiSize);
    }
    else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiRGBLab_32f_LT_Str ts;
        RGBLabThreadingStructureEncode_32f_LT(pSrc, srcStep, pDst, dstStep, roiSize, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT (numTiles, (void*)&ts, ippiRGBToLab_32f_P3R_LT_Fun);
    }

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

    IppiPointL splitImage;
    IppiSizeL  tileSize, tailSize;
    IppSizeL   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_LT(roiSize, minTileSize, &splitImage, &tileSize, &tailSize);

    if (splitImage.x == 1 && splitImage.y == 1)
    {
        status = ippiRGBToLab_64f_P3R_L(pSrc, srcStep, pDst, dstStep, roiSize);
    }
    else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiRGBLab_64f_LT_Str ts;
        RGBLabThreadingStructureEncode_64f_LT(pSrc, srcStep, pDst, dstStep, roiSize, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT(numTiles, (void*)&ts, ippiRGBToLab_64f_P3R_LT_Fun);
    }

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

    IppiPointL splitImage;
    IppiSizeL  tileSize, tailSize;
    IppSizeL   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_LT(roiSize, minTileSize, &splitImage, &tileSize, &tailSize);

    if (splitImage.x == 1 && splitImage.y == 1)
    {
        status = ippiLabToRGB_32f_P3R_L(pSrc, srcStep, pDst, dstStep, roiSize);
    }
    else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiRGBLab_32f_LT_Str ts;
        RGBLabThreadingStructureEncode_32f_LT(pSrc, srcStep, pDst, dstStep, roiSize, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT(numTiles, (void*)&ts, ippiLabToRGB_32f_P3R_LT_Fun);
    }

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

    IppiPointL splitImage;
    IppiSizeL  tileSize, tailSize;
    IppSizeL   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_LT(roiSize, minTileSize, &splitImage, &tileSize, &tailSize);

    if (splitImage.x == 1 && splitImage.y == 1)
    {
        status = ippiLabToRGB_64f_P3R_L(pSrc, srcStep, pDst, dstStep, roiSize);
    }
    else
    {
        numTiles = splitImage.x * splitImage.y;
        ippiRGBLab_64f_LT_Str ts;
        RGBLabThreadingStructureEncode_64f_LT(pSrc, srcStep, pDst, dstStep, roiSize, splitImage, tileSize, tailSize, &ts);
        status = ippParallelFor_LT(numTiles, (void*)&ts, ippiLabToRGB_64f_P3R_LT_Fun);
    }

    return status;
}

