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

// A simple example of restoring damaged image area by direct inpainting
// using Intel(R) Integrated Primitives (Intel(R) IPP) functions:
//     ippiFastMarchingGetBufferSize_8u32f_C1R
//     ippiFastMarching_8u32f_C1R
//     ippiInpaintGetSize
//     ippiInpaintInit_8u_C1R
//     ippiInpaint_8u_C1R

#include <stdio.h>
#include "ipp.h"

#define WIDTH  128  /* Image width*/
#define HEIGHT 128  /* Image height*/
#define RADIUS 3.f  /* Neighborhood radius*/
#define INPAINT_FLAGS IPP_INPAINT_NS /* Specifies algorithm for image inpainting*/

/* Next two defines are created to simplify code reading and understanding */
#define EXIT_MAIN exitLine:                                  /* Label for Exit */
#define check_sts(st) if((st) != ippStsNoErr) goto exitLine; /* Go to Exit if Intel(R) IPP function returned status different from ippStsNoErr */

/* Results of ippMalloc() are not validated because Intel(R) IPP functions perform bad arguments check and will return an appropriate status  */

int main(void)
{
    IppStatus status = ippStsNoErr;

    Ipp8u   *pSrc = NULL, *pDst = NULL;     /* Pointers to source/destination images */
    int      srcStep = 0,  dstStep = 0;     /* Steps, in bytes, through the source/destination images */
    IppiSize roiSize = { WIDTH, HEIGHT };   /* Size of source/destination ROI in pixels */

    Ipp8u *pMask = NULL;    /* Pointer to mask image */
    int    maskStep;        /* Step, in bytes, through the mask image */

    Ipp32f *pFMDist      = NULL; /* Pointer to distances image */
    int     fmDistStep   = 0;    /* Step, in bytes, through the distances image */
    Ipp8u  *pFMBuffer    = NULL; /* Pointer to the Fast marching work buffer */
    int     fmBufferSize = 0;

    IppiInpaintState_8u_C1R *pInpState = NULL; /* Pointer to inpainting structure */
    Ipp8u *pInpBuffer    = NULL; /* Pointer to the Inpaint work buffer */
    int    inpBufferSize = 0;
    Ipp8u *pInpStateBuf  = NULL; /* Pointer to the Inpaint structure buffer */
    int    inpStateSize  = 0;

    pSrc  = ippiMalloc_8u_C1(roiSize.width, roiSize.height, &srcStep);
    pDst  = ippiMalloc_8u_C1(roiSize.width, roiSize.height, &dstStep);
    pMask = ippiMalloc_8u_C1(roiSize.width, roiSize.height, &maskStep);

    pFMDist = ippiMalloc_32f_C1(roiSize.width, roiSize.height, &fmDistStep);

    /* Compute the temporary work buffer size for Fast Marching */
    check_sts( status = ippiFastMarchingGetBufferSize_8u32f_C1R(roiSize, &fmBufferSize) )
    
    pFMBuffer = ippsMalloc_8u(fmBufferSize);

    /* Calculate distance by the Fast Marching Method */
    check_sts( status = ippiFastMarching_8u32f_C1R(pMask, maskStep, pFMDist, fmDistStep, roiSize, RADIUS, pFMBuffer) )

    /* Calculate State and work buffer sizes for Inpaint */
    check_sts( status = ippiInpaintGetSize(pMask, maskStep, roiSize, RADIUS, INPAINT_FLAGS, ippC1, &inpStateSize, &inpBufferSize) )

    /* Memory allocation for State and work buffer */
    pInpStateBuf = ippsMalloc_8u(inpStateSize);
    pInpBuffer   = ippsMalloc_8u(inpBufferSize);

    /* Initialize the Inpaint State for direct methods of image inpainting */
    check_sts( status = ippiInpaintInit_8u_C1R(&pInpState, pFMDist, fmDistStep, pMask, maskStep, roiSize, RADIUS, INPAINT_FLAGS, pInpStateBuf, pInpBuffer) )

    /* Restores damaged image area by direct inpainting */
    check_sts( status = ippiInpaint_8u_C1R(pSrc, srcStep, pDst, dstStep, roiSize, pInpState, pInpBuffer) )

EXIT_MAIN
    ippsFree(pFMBuffer);
    ippsFree(pFMDist);
    ippsFree(pInpBuffer);
    ippiFree(pInpStateBuf);
    ippiFree(pSrc);
    ippiFree(pDst);
    ippiFree(pMask);
    printf("Exit status %d (%s)\n", (int)status, ippGetStatusString(status));
    return (int)status;
}