Perfectly Clear SDK Documentation  10.0.1.537
Examples (OSX / Linux)

Sample source code is provided in this SDK for several applications that are ready to build on linux and OSX systems. These examples each show different usage models and provide a starting point for adapting these into ready-for-production command line applications. These example applications are:

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("/home/user/sdk_license");
    if (bVerbose)
    printf("License Code Status is %d\n", code);
  2. Load image to correct:
    // Load image buffer from file using helper library PFCImageFile (currently supports RGB JPEGs, PNG and WEBP)
    PFCImageFile originalImageFile;
    bool bConvertToSRGB = true; // sRGB is a recommended working space for PFC
    PFC_FILE_LOAD_STATUS st = originalImageFile.LoadImageFile(inname, bConvertToSRGB, NULL);
  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.
    PFCENGINE *pAiEngine = PFC_CreateEngine();
    // Load AI engine (assuming all dlls and models are in exe folder):
    std::string exePath = std::string(argv[0]);
    std::string binPath = exePath.substr(0, exePath.find_last_of('/')).c_str();
    int aistatus = PFC_LoadAIEngine(pAiEngine, AI_SCENE_DETECTION | AI_CORRECTIONS, binPath.c_str());
  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");
    }
  5. Save the corrected image
    // Save image to file.
    // Convert to original color space if processing was done in sRGB, and preserve metadata
    bool bConvertToOriginalColorSpace = bConvertToSRGB;
    bool bPreserveOriginalMetadata = true;
    originalImageFile.SaveImageFile(oname, quality, bConvertToOriginalColorSpace, bPreserveOriginalMetadata);

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 {
bool retLoadPresets = PFC_LoadScenePresets(pAiEngine, profilename);
if (0 != retLoadPresets) {
printf("Cannot load scene presets file '%s' error '%i'\n", profilename, retLoadPresets);
exit(1);
} else {
printf("Loaded scene presets file '%s'\n", profilename);
}
}

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);
// Apply scene preset for detected scene by getting the params to apply from the AI-enabled
PFCPARAM param;
if (detectedScene >= 0) {
PFCPARAM sceneParam;
if (0 == PFC_ReadScenePreset(sceneParam, pAiEngine, detectedScene)) {
param = sceneParam;
}
}
// Its name can be obtained through PFC_GetSceneDescription. This should *not* be done in a tight loop.
if(bVerbose) {
PFCSCENEDESCRIPTION description;
int i = 0;
while(PFC_GetSceneDescription(pAiEngine, i, &description)) {
if(description.profileUUID == detectedScene) {
printf("Scene '%i' is named '%s'.\n", detectedScene, description.name);
}
++i;
}
}

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
    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.)
    int ret = PFC_ReadPresets(param, profilename);
    if (bVerbose)
    printf("PFC_ReadPresets returns %d\n", ret);
    if (ret != 0) {
    if (ret == -2) {
    // Use default parameters if preset file not found.
    PFC_SetParam(param);
    printf("Unable to open preset file %s. Using default settings.\n", argv[3]);
    } else {
    printf("Unable to read preset file.\n");
    exit(1);
    }
    }
    } else {
    // Use default parameters.
    PFC_SetParam(param);
    }
  2. then use these parameters when correcting the image
    // Process image with user parameters.
    PFCAPPLYSTATUS status = PFC_Apply(&im, pEngine, pProfile, param, bVerbose? myStatus : NULL);
    // Optional display of status.
    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);
    }

Standard I/O to read and write images

Instead of operating with files on disk, you can read and write image content from standard I/O, as seen in the "Standard-IO" sample project.

  1. Setup input buffer to read
    fseek(stdin, 0, SEEK_END);
    const long inSize = ftell(stdin);
    fseek(stdin, 0, SEEK_SET);
    if(inSize < 0) {
    printf("No image piped.");
    exit(1);
    }
    //Allocate memory
    char* inBuffer = (char *)malloc(inSize);
    if (!inBuffer)
    {
    printf("Unable to create buffer");
    exit(1);
    }
    //Read file contents into buffer
    fread(inBuffer, inSize, 1, stdin);
  2. Uncompress the incoming image data
    // Load image buffer from file using helper library PFCImageFile (currently supports only RGB JPEGs).
    PFCImageFile originalImageFile;
    bool bConvertToSRGB = true; // sRGB is a recommended working space for PFC
    const char* pathToSupportFilesFolder = NULL; // Some JPEGs may be in AdobeRGB without AdobeRGB being actually embedded
    // then path to folder containing AdobeRGB1998.icc should be passed here
    // otherwise PFCImageFile would fail to convert such JPEGs to sRGB
    PFC_FILE_LOAD_STATUS st = originalImageFile.ExpandImageBuffer(inBuffer, inSize, inType, bConvertToSRGB, pathToSupportFilesFolder);
    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);
    }
    }
    free(inBuffer);
  3. Correct the image as usual, then compress and encode the data
    // Output image to stdout
    // Convert to original color space if processing was done in sRGB, and preserve metadata
    bool bConvertToOriginalColorSpace = bConvertToSRGB;
    bool bPreserveOriginalMetadata = true;
    unsigned char* outBuffer = NULL;
    unsigned long outSize = originalImageFile.CompressImageBuffer(&outBuffer, outType, 90, bConvertToOriginalColorSpace, bPreserveOriginalMetadata);
    fwrite(outBuffer, outSize, 1, stdout);
    free(outBuffer);

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
PFCImageFile fileResized(800, 600, 3, 3 * 800);
// Populate PFCIMAGE struct
PFCIMAGE imageResized;
imageResized.width = fileResized.width;
imageResized.height = fileResized.height;
imageResized.format = im.format;
imageResized.stride = fileResized.stride;
imageResized.data = fileResized.raw_image;
// Perform the resizing
status = (PFCAPPLYSTATUS)PFC_Resize(&im, &imageResized);
if (status == APPLY_SUCCESS) {
// Save resized image
char outResized[1000];
sprintf(outResized, "%s.%dx%d.jpg", inname, imageResized.width, imageResized.height);
fileResized.SaveImageFile(outResized, 90, false, false);
} 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;
    }
  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;
    }
PFCSCENEDESCRIPTION::profileUUID
int profileUUID
utf8-encoded name
Definition: PerfectlyClearPro.h:1094
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
PFCImageFile::CompressImageBuffer
int CompressImageBuffer(unsigned char **destination, PFC_FILETYPE type, int quality, bool bConvertToOriginalColorSpace, bool bEmbedOriginalMetadata)
Compresses the image to the given type and writes compressed data to destination buffer.
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.
PFCSCENEDESCRIPTION
Scene description.
Definition: PerfectlyClearPro.h:1092
PFCImageFile::ExpandImageBuffer
PFC_FILE_LOAD_STATUS ExpandImageBuffer(char *data, long size, PFC_FILETYPE type, bool bConvertToSRGB, const char *iccFolderPath)
Expands the image file data provided in a buffer.
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
PFC_ReadScenePreset
int PFC_ReadScenePreset(PFCPARAM &param, PFCENGINE *pEngineAI, int scene)
Fill param for the scene from the engine with previously loaded scene presets with PFC_LoadScenePrese...
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_GetSceneDescription
bool PFC_GetSceneDescription(PFCENGINE *pEngine, int index, PFCSCENEDESCRIPTION *sceneDescription)
Get the scene description for the given index number.
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.
PFCImageFile::SaveImageFile
bool SaveImageFile(const char *filename, int quality, bool bConvertToOriginalColorSpace, bool bEmbedOriginalMetadata)
Write image data to file - specify file type with filename extension.
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.