/*
// Copyright 2015 2016 Intel Corporation All Rights Reserved.
// 
// The source code, information and material ("Material") contained herein is
// owned by Intel Corporation or its suppliers or licensors, and title
// to such Material remains with Intel Corporation or its suppliers or
// licensors. The Material contains proprietary information of Intel
// or its suppliers and licensors. The Material is protected by worldwide
// copyright laws and treaty provisions. No part of the Material may be used,
// copied, reproduced, modified, published, uploaded, posted, transmitted,
// distributed or disclosed in any way without Intel's prior express written
// permission. No license under any patent, copyright or other intellectual
// property rights in the Material is granted to or conferred upon you,
// either expressly, by implication, inducement, estoppel or otherwise.
// Any license under such intellectual property rights must be express and
// approved by Intel in writing.
// 
// Unless otherwise agreed by Intel in writing,
// you may not remove or alter this notice or any other notice embedded in
// Materials by Intel or Intel's suppliers or licensors in any way.
*/

// A simple example of restoring damaged image area by direct inpainting
// using Intel 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 IPP function returned status different from ippStsNoErr */

/* Results of ippMalloc() are not validated because Intel(R) Integrated Performance Primitives 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;
}