Perfectly Clear SDK Documentation  10.0.1.537
Examples (Windows)

Sample code for both C and C# projects are provided along with the SDK. The examples below demonstrate the general usage of the Perfectly Clear SDK.

Simple AI Sample - Using Scene Detection

The simplest way to use Perfectly Clear AI. See the "SimpleAiSample" sample for a full implementation of this.

  1. Setup the license protection
    // if you have a license key, then call PFC_SetProtectionPath with the path
    // to your license files
    int code = PFC_SetProtectionPath("C:\\Protection\\sdk");
    if (bVerbose)
    printf("License Code Status is %d\n", code);
  2. Load image to correct:
    Bitmap *pBM = Bitmap::FromFile(inname);
    if (pBM == NULL)
    {
    printf("Unable to open input file.\n");
    exit(0);
    }
    BitmapData *pbd = new BitmapData;
    pBM->LockBits(&Rect(0, 0, pBM->GetWidth(), pBM->GetHeight()), ImageLockModeWrite, pBM->GetPixelFormat(), pbd);
    int width, height;
    width = pbd->Width;
    height = pbd->Height;
  3. Initialize the AI Engines
    // Use AI-enabled PFCENGINE to do scene detection and apply a scene preset accordingly.
    // IMPORTANT: initialization of AI engine takes time, so better keep a SINGLE INSTANCE of the AI-enabled
    // engine per worker thread throughout your app session.
    // Note that an Engine is not thread or reentry safe and should *not* be shared accross threads.
    PFCENGINE *pAiEngine = PFC_CreateEngine();
    // Load AI engine (assuming all dlls and models are in exe folder):
    std::string binPath = ".";
    int aistatus = PFC_LoadAIEngine(pAiEngine, AI_SCENE_DETECTION | AI_CORRECTIONS, binPath.c_str());
    if ((aistatus & AI_SCENE_DETECTION) == 0) {
    printf("Cannot load AI Scene Detection. Make sure the eff_1.pnn file, PFCAI and onnx libraries are in the executable directory or change binPath in code and re-compile.\n");
    printf("status %d\n", aistatus);
    exit(1);
    }
    if ((aistatus & AI_CORRECTIONS) == 0) {
    printf("Cannot load AI Corrections. Make sure the dynamic.pnn file, PFCAI and onnx libraries are in the executable directory or change binPath in code and re-compile.\n");
    printf("status %d\n", aistatus);
    exit(1);
    }
  4. Perform full correction using the auto function:
    // AutoCorrect with a valid AiEngine will ignore PFCPARAM and use AI determined presets instead
    PFCPARAM ignoredParam;
    int status = PFC_AutoCorrect(&im, NULL, ignoredParam, -1, NULL, false, NULL, pAiEngine);
    if (status == APPLY_SUCCESS && bVerbose)
    {
    printf("Image processed successfully.\n");
    }
    else if (status > APPLY_SUCCESS && bVerbose)
    {
    // Check return code for Noise Removal
    printf("Noise removal status %d\n", NRRETCODE(status));
    // Check return code for Perfectly Clear Core correction
    printf("Perfectly Clear correction status %d\n", CORERETCODE(status));
    // Check return code for Face Beautification
    printf("Face beautification status %d\n", FBRETCODE(status));
    // Check return code for Red Eye Removal
    printf("Red eye removal status %d\n", RERETCODE(status));
    }
    else if (status < APPLY_SUCCESS)
    {
    printf("Image processing failed with return code: %d\n", status);
    }
  5. Save the corrected image
    SaveImage(pBM, outname);

Detailed AI Sample - Using Scene Detection

To extend the example shown above, you can load custom AI Presets to apply, instead of using the default presets provided by this SDK. See the "DetailedAiSample" sample for a full implementation of this.

// AI Scene Detection includes default presets for all scenes it defines.
// These presets are immediately available after the call to PFC_LoadAIEngine().
// One can return to these presets calling with a null pointer like
//
// <code>
// bool retLoadPresets = PFC_LoadScenePresets(pAiEngine, nullptr);
// <code>
// You may modify these presets by editing them in Workbench, then exporting
// a Scene Detection compatible .preset file then load those presets
// with the following code.
if (profilename == NULL)
{
if (bVerbose) {
printf("Using default presets for detected scenes\n");
}
} else {
char* scenePresetPath = NULL;
std::string profilenameUtf8;
if (profilename) {
profilenameUtf8 = utf8FromW(std::wstring(profilename));
scenePresetPath = (char*)profilenameUtf8.c_str();
}
bool retLoadPresets = PFC_LoadScenePresets(pAiEngine, scenePresetPath);
if (0 != retLoadPresets) {
printf("Cannot load scene presets file '%s' error '%i'\n", scenePresetPath, retLoadPresets);
exit(1);
}
else {
printf("Loaded scene presets file '%s'\n", scenePresetPath);
}
}

And you can determine the scene ID and label:

// After detectionn the scene id and model version can be optained through PFC_GetScene/
// The specific meaning depends on the model loaded.
int version = 0;
int detectedScene = PFC_GetScene(pProfile, &version);
printf("AI version '%i' assigned scene '%i' to the image.\n", version, detectedScene);

AI Image Correction without Scene Detection

You can correct photos without scene detection, but still using the AI Image corrections that are new in this V10 SDK. This is implemented in the "PresetSample" sample code provided with this SDK.

  1. load the correction parameters to apply from a .preset file
    // Set process parameters.
    PFCPARAM param;
    if (profilename != NULL)
    {
    // Optionally, the process parameters can be imported from a .preset file.
    // (The .preset file can be exported from Athentech's desktop applications. e.g. Workbench.)
    std::string profilenameUtf8 = utf8FromW(std::wstring(profilename));
    int ret = PFC_ReadPresets(param, (char*)profilenameUtf8.c_str());
    if (bVerbose)
    printf("PFC_ReadPresets returns %d\n", ret);
    if (ret != 0)
    {
    if (ret == -2) // preset file not found
    {
    // Use default parameters if preset file not found.
    PFC_SetParam(param);
    printf("Unable to open preset file %s. Using default settings.\n", profilename);
    }
    else if (ret == -8)
    {
    printf("Invalid preset file.\n");
    exit(0);
    }
    else
    {
    printf("Unable to read preset file.\n");
    exit(0);
    }
    }
    }
    else
    {
    // Use default parameters.
    PFC_SetParam(param);
    }
  2. then use these parameters when correcting the image
    // Process image with parameters.
    PFCAPPLYSTATUS status = PFC_Apply(&im, pEngine, pProfile, param, bVerbose ? myStatus : NULL);
    // Optionally, check process status.
    if (bVerbose)
    {
    if (status == APPLY_SUCCESS)
    {
    printf("Image processed successfully.\n");
    }
    else if (status > APPLY_SUCCESS)
    {
    int code;
    // Check return code for Noise Removal
    code = NRRETCODE(status);
    printf("Noise removal status %d\n", code);
    // Check return code for Perfectly Clear Core correction
    code = CORERETCODE(status);
    printf("Perfectly Clear correction status %d\n", code);
    // Check return code for Face Beautification
    code = FBRETCODE(status);
    printf("Face beautification status %d\n", code);
    // Check return code for Red Eye Removal
    code = RERETCODE(status);
    printf("Red eye removal status %d\n", code);
    }
    else
    {
    printf("Image processing failed with return code: %d\n", status);
    }
    }

Image Resizing

This sample loads and corrects the image, but also resizes the output images, as seen in "ResizeSample".

// Allocate a destination image with the final dimensions you want after resizing
// Setting width, height, bytes per pixel, stride
Bitmap *pResizedBM = new Bitmap(800, 600, pbd->PixelFormat);
// Populate PFCIMAGE struct
BitmapData *pbdrs = new BitmapData;
pResizedBM->LockBits(&Rect(0, 0, pResizedBM->GetWidth(), pResizedBM->GetHeight()), ImageLockModeWrite, pResizedBM->GetPixelFormat(), pbdrs);
PFCIMAGE imageResized;
imageResized.width = pbdrs->Width;
imageResized.height = pbdrs->Height;
imageResized.format = im.format;
imageResized.stride = pbdrs->Stride;
imageResized.data = (LPBYTE)pbdrs->Scan0;
status = (PFCAPPLYSTATUS)PFC_Resize(&im, &imageResized);
if (status == APPLY_SUCCESS) {
// Save resized image to file
if (names[1] == NULL) {
names[1] = GetDefaultName(names[0]);
}
SaveImage(pResizedBM, names[1]);
} else {
printf("Image couldn't be resized, failed with return code: %d\n", status);
}

PDF Image Correcting

This sample loads a PDF file and corrects the images it finds, replaces them into the file and saves it back, as seen in "PDFSample".

  1. First load the PDF file and setup the correction engine
    // One opens a pdf file through calling the "load" function which Ok on success
    // or an error code on error.
    if(file.load(inputPath) != PFCPDFImageIterator::LoadStatus::Ok) {
    printf("Cannot load path %s\n", inputPath);
    return 1;
    }
    int i = 0;
  2. Then, iterate over the images, correcting each one
    // nextImage returns all the PFC-compatible images and its contects are substituted to the
    // open in-memory element when the next call to nextImage is done.
    while(PFCPDFImage* pdfImage = file.nextImage()) {
    PFCImageFile* imgFile = pdfImage->imageFile;
    printf(" working on image %d\n", i);
    PFCPARAM param;
    PFC_SetParam(param); // default auto preset
    im.width = imgFile->width;
    im.height = imgFile->height;
    im.stride = imgFile->stride;
    im.format = (PFCPIXELFORMAT)imgFile->pfcImageFormat();
    im.data = imgFile->raw_image;
    PFCPROFILE pProfile = PFC_Calc(&im, NULL, pEngine, CALC_ALL, -1, NULL, NULL, NULL);
    PFCAPPLYSTATUS status = PFC_Apply(&im, pEngine, pProfile, param, NULL);
    printf(" -status %d\n", status);
    i++;
    PFC_ReleaseProfile(pProfile);
    }
  3. Last, write the new PDF containing all the corrected images to disk:
    if(file.save(outputPath) != PFCPDFImageIterator::SaveStatus::Ok) {
    printf("Cannot save to %s\n", outputPath);
    return 1;
    }

Loading From Bitmaps or with PfCImageFile

You can either load image data using our PFCImageFile class, or you can use standard Windows bitmaps. SimpleAiSample shows the bitmap method. If you are incorporating Perfectly Clear into an application that already is using Bitmaps, then this method will make it easy to incorporate Perfectly Clear into this.

Bitmap *pBM = Bitmap::FromFile(inname);
if (pBM == NULL)
{
printf("Unable to open input file.\n");
exit(0);
}
BitmapData *pbd = new BitmapData;
pBM->LockBits(&Rect(0, 0, pBM->GetWidth(), pBM->GetHeight()), ImageLockModeWrite, pBM->GetPixelFormat(), pbd);
int width, height;
width = pbd->Width;
height = pbd->Height;

In DotNetCore_PFCImageFile, we use the PfCImageFile class instead, shown in a simplified form here:

// Load image buffer from file using helper library PFCImageFile.
PFCImageFile originalImageFile;
bool bConvertToSRGB = true; // sRGB is a recommended working space for PFC
const char* pathToSupportFilesFolder = NULL;
#ifdef WIN32
std::string innameUtf8 = utf8FromW(std::wstring(inname));
PFC_FILE_LOAD_STATUS st = originalImageFile.LoadImageFile(innameUtf8.c_str(), bConvertToSRGB, pathToSupportFilesFolder);
#else
PFC_FILE_LOAD_STATUS st = originalImageFile.LoadImageFile(inname, bConvertToSRGB, pathToSupportFilesFolder);
#endif
if (st != LOAD_OK) {
printf("Unable to convert input file to sRGB, processing in original color space\n");
} else {
printf("Unable to open input file, ABORTING.\n");
exit(1);
}
}

PfCImageFile class will handle color space conversion and metadata management automatically.

PFC_GetScene
int PFC_GetScene(PFCPROFILE precalc, int *version)
Get scene detection label from profile obtained with PFC_Calc For this to work you need to pass AI_SC...
PFC_SetProtectionPath
int PFC_SetProtectionPath(const char *utf8FolderPath, const char *liceseCode=NULL)
Set path to location of SDK License files This enables license protection and allows activation using...
APPLY_SUCCESS
@ APPLY_SUCCESS
0 Success.
Definition: PerfectlyClearPro.h:384
PFC_LoadAIEngine
int PFC_LoadAIEngine(PFCENGINE *pEngineAI, unsigned int aifeatures, const char *binPath)
Load AI models into engine. Takes time and memory. Use single PFCENGINE with loaded modules,...
PFCPDFImage
Represents an image extracted from a PDF file, thru use of a PFCPDFImageIterator.
Definition: PFCPDFImage.h:30
CORERETCODE
#define CORERETCODE(x)
Decode return status of Core correction from master return code.
Definition: PerfectlyClearPro.h:21
PFCPARAM
Struct PFCPARAM the master structure of all processing parameters.
Definition: PerfectlyClearPro.h:580
AI_CORRECTIONS
@ AI_CORRECTIONS
Loads AI-basedd corrections model.
Definition: PerfectlyClearPro.h:1034
PFCIMAGE::height
int height
Pixel height of image.
Definition: PerfectlyClearPro.h:249
CALC_ALL
@ CALC_ALL
Calculates for all classic features, all of the above.
Definition: PerfectlyClearPro.h:163
PFCPDFImageIterator::load
LoadStatus load(const char *path)
load() loads the file and returns true if succesful.
RERETCODE
#define RERETCODE(x)
Decode return status of Red Eye correction from master return code.
Definition: PerfectlyClearPro.h:25
PFC_FILE_LOAD_STATUS
PFC_FILE_LOAD_STATUS
Return status values.
Definition: PFCImageFile.h:19
PFCIMAGE::stride
int stride
Byte width of each scanline.
Definition: PerfectlyClearPro.h:250
PFCAPPLYSTATUS
PFCAPPLYSTATUS
Enumeration defining return code from the Apply() function.
Definition: PerfectlyClearPro.h:383
LOAD_FAILED_CONVERT_SRGB
@ LOAD_FAILED_CONVERT_SRGB
Error: failed to convert to sRGB.
Definition: PFCImageFile.h:23
PFCImageFile::raw_image
unsigned char * raw_image
Definition: PFCImageFile.h:167
PFCPROFILE
#define PFCPROFILE
Define.
Definition: PerfectlyClearPro.h:614
PFCIMAGE::width
int width
Pixel width of image.
Definition: PerfectlyClearPro.h:248
PFCIMAGE::data
unsigned char * data
Pointer pointing to the first byte of image data buffer.
Definition: PerfectlyClearPro.h:252
PFCPDFImageIterator::save
SaveStatus save(const char *path)
save() loads the file and returns true if succesful.
PFCIMAGE
Struct defining an image to be used in PFC library.
Definition: PerfectlyClearPro.h:247
PFCENGINE
Struct defining an PFC engine instance.
Definition: PerfectlyClearPro.h:241
PFCImageFile::stride
int stride
Definition: PFCImageFile.h:175
PFC_ReleaseProfile
void PFC_ReleaseProfile(PFCPROFILE pProfile)
Release PFCPROFILE instance.
PFC_Apply
PFCAPPLYSTATUS PFC_Apply(PFCIMAGE *pImage, PFCENGINE *pEngine, PFCPROFILE pImageProfile, PFCPARAM &param, PFC_PROGRESS progfn=NULL, int iOpacity=100, void *pBGProfile=NULL)
Correct image with parameters.
NRRETCODE
#define NRRETCODE(x)
Decode return status of Noise Removal from master return code.
Definition: PerfectlyClearPro.h:19
AI_SCENE_DETECTION
@ AI_SCENE_DETECTION
Loads scene detection model.
Definition: PerfectlyClearPro.h:1033
PFC_CreateEngine
PFCENGINE * PFC_CreateEngine()
Create PFCENGINE instance.
PFCIMAGE::format
PFCPIXELFORMAT format
Defines byte order of input buffer.
Definition: PerfectlyClearPro.h:251
PFCPDFImageIterator::LoadStatus::Ok
@ Ok
Success, file opened successfully.
PFCPDFImageIterator::SaveStatus::Ok
@ Ok
Success, file saved successfully.
PFC_Resize
PFCAPPLYSTATUS PFC_Resize(PFCIMAGE *pImageSrc, PFCIMAGE *pImageDst)
Resizes the input image to the dimensions specificed in by the output image. The output image must be...
PFC_LoadScenePresets
int PFC_LoadScenePresets(PFCENGINE *pEngine, const char *filePath, int groupUUID=0, int *arrProfileUUID=NULL, int arrProfileUUIDLen=0)
Loads scene optimized presets from presets file. Engine may be AI-enabled with PFC_LoadAIEngine()....
PFC_Calc
PFCPROFILE PFC_Calc(PFCIMAGE *pImage, PFCIMAGE *pImageds, PFCENGINE *pEngine, unsigned int feature=CALC_ALL, int iISO=-1, char *pCameraModel=NULL, PFCPROFILE pImageProfile=NULL, PFC_PROGRESS progfn=NULL, int iRejectOption=PFC_REJECT_CLIPART, PFCENGINE *pEngineAI=NULL)
Perform initial analysis on images.
PFCImageFile::height
int height
Definition: PFCImageFile.h:171
PFCPDFImageIterator::nextImage
PFCPDFImage * nextImage()
Primary use of the iterator. It'll return a pointer to a PFCPDFImage until the document containes no ...
PFCPDFImageIterator
PFCPDFImageIterator allows the user to iterate over the PFC-supported images of a PDF file....
Definition: PFCPDFImageIterator.h:28
PFCImageFile::width
int width
Definition: PFCImageFile.h:169
PFCPIXELFORMAT
PFCPIXELFORMAT
defines the format of the image data
Definition: PerfectlyClearPro.h:35
PFC_AutoCorrect
int PFC_AutoCorrect(PFCIMAGE *pImage, PFCIMAGE *pImageds, PFCPARAM &param, int iISO=-1, char *pCameraModel=NULL, BOOL bFastFAE=FALSE, PFC_PROGRESS progfn=NULL, PFCENGINE *pEngineAI=NULL)
Single function to perform Perfectly Clear correction.
PFC_SetParam
void PFC_SetParam(PFCPARAM &param, PFCPRESETID id=PRESET_IAUTO_21)
Initialize a PFCPARAM structure.
LOAD_OK
@ LOAD_OK
Success.
Definition: PFCImageFile.h:20
PFCImageFile
PFCImageFile Class to encapsulate file handling.
Definition: PFCImageFile.h:69
PFC_ReadPresets
int PFC_ReadPresets(PFCPARAM &param, char *filename)
Load image processing settings from a .preset file. Use this function to load image processing settin...
FBRETCODE
#define FBRETCODE(x)
Decode return status of Face Beautification from master return code.
Definition: PerfectlyClearPro.h:23
PFCImageFile::LoadImageFile
PFC_FILE_LOAD_STATUS LoadImageFile(const char *filename, bool bConvertToSRGB, const char *iccFolderPath)
Load JPEG, PNG or RAW from file on disk.