Perfectly Clear SDK Documentation  8.3.4.175
Correction Parameters

Corrections in this SDK

The image corrections available include:

  1. Perfectly Clear Core Corrections
  2. Noise Corrections
  3. Red-eye removal
  4. "Beautify" Corrections (licensed as an optional component)
  5. "V3 Looks" support - Finishing and Graduated Filters, along with several other corrections added in the "V3" versions of our Desktop products. These include:
    1. Color Vibrancy
    2. Neutral Density
    3. Foliage and Sky Enhancement
    4. Input Corrective Filters
    5. Output LOOKs
    6. Finishing Tools
    7. Graduated Filters

V3 LOOKs support is not available at this time on mobile platforms, and is provided via an optional "v3.looks" file. The supported LOOKs are listed here.

These various corrections are best previewed and evaluated in our desktop applications like Perfectly Clear Complete or QuickDesk.

Auto Exposure Parameters

There are several parameters which affect our automatic exposure correction:

PFCCOREPARAM.iStrength is what will actually be applied to the image. When PFCCOREPARAM.bUseAutomaticStrengthSelection is 'true' then iStrength will be set automatically, and is influenced by all the other parameters. The actual value of iStrength will also depend on image content, of course. Attempting to set iStrength to a specific value while bUseAutomaticStrengthSelection is true has no effect.

This last option is not able to be directly set within our Perfectly Clear desktop applications. Instead, it's automatically set to 50, 100, or 150 based on the value of PFCCOREPARAM.eAggressiveness (low, med, or high). However, manually setting PFCCOREPARAM.iMaxStrength can still have an affect on the exposure correction level. Specifically, the recommended exposure level will not exceed the iMaxStrength value you set when FAE is disabled, or when FAE is enabled, but a face is not detected. In FAE exposure cases (enabled and faces are found), the maximum exposure will be (50, 100, 150) based on eAggressiveness.

Face Aware Exposure

There are two operating modes for Face Aware Exposure: High Quality and High Speed. This affects the performance of the face detection process, which is used by Face Aware Exposure to gain insight into the exposure values of the people in your photos. High Quality takes slightly longer to process, but find more faces - especially backlit, small faces. High Speed is quicker, but is not as good at finding smaller faces. The speed difference is between 10% and 20% of total processing time, and the detection rate is about 1% to 2% better on High Quality. The one used by default in this SDK and in our Perfectly Clear desktop software is High Quality. To change this to High Speed, you can:

  1. Set the CALC_FAEHISPEED feature when calling PFC_Calc
  2. Set bFastFAE to false when calling PFC_AutoCorrect

Setting Correction Parameters

There are three ways you can set the correction parameters to be applied in this SDK:

  1. Use one of the pre-defined presets available in the PFCPRESETID enum
  2. Read a .preset file exported from any Perfectly Clear desktop application using PFC_ReadPresets
  3. Manually define all the various parameters in the PFCPARAM struct, which is usually done by copy/pasting code from the 'Export to API' function in our business-related desktop applications.

Let's look at each of these in a little more detail.

1. Using pre-defined presets

The quickest way to get started with this SDK is to use one of our built-in presets to populate the PFCPARAM struct that you'll need when calling PFC_Apply or PFC_AutoCorrect. This is as simple as:

// Declaration of PFCPARAM.
PFCPARAM param;
// Initialize process parameters. If presetID is left blank, default to using Intelligent Auto preset.
PFC_SetParam(param, PRESET_INTELLIGENTAUTO);

Now, the param struct is populated with all the various correction parameters defined with our Intelligent Auto preset. This preset has been carefully designed with years of feedback from our customers, and is used on millions of photos per day. If you want to make a few changes to these parameters, you can set individual parameters:

param.core.bDCF=true;
param.core.eDCFMode=DCF_VIVID;

2. Reading .preset files

All our desktop applications can export presets to XML files which will end in the .preset file extension. These files can then easily be read using PFC_ReadPresets like this:

PFCPARAM param;
char* profilename = "/path/to/approved_parameters.preset";
int ret = PFC_ReadPresets(param, profilename);

Now, the param struct is populated with all the various correction parameters defined with the settings you created in the file /path/to/approved_parameters.preset . Here's a link to the User Guide of Perfectly Clear that explains how to export these .preset files: https://www.athentech.com/help/plugins/PerfectlyClearComplete-v3/index.html?about_the_perfectly_clear_interface.html

This is the quickest way for you to get your custom parameters in use with this SDK.

3. Copy / Pasting Parameter Code

Lastly, you can export the standard C or C# code from Perfectly Clear Complete (with a special 'Workbench' license code) or QuickDesk. Notes on how to do that are here: https://www.athentech.com/help/plugins/PerfectlyClearWorkbench-v3/what-is-workbench_.html

Once you have this exported text file, open it up and you will see various sections for C or C# syntax. Within these major sections, you will find the various parameters for each of the PFCPARAM groups: PFCCOREPARAM, PFCNRPARAM, PFCREPARAM, PFCFBPARAM, and PFCV3PARAM, including layers and masks.

For example, here is the full C code required to set all the parameters for our Intelligent Auto preset (see below). All of the PFCV3PARAM sections are empty or zero value, so these can safely be omitted.

This method allows you to hard-code specific parameters into the applications you compile with this SDK. This can be useful to prevent accidental changes to the parameters, which would be possible if they were being read from an external .presets file.

If your application allows the end-user to change parameters, then this method also allows you change individual parameter programmatically.

param.core.bEnabled=true;
param.core.bAbnormalTintRemoval=false;
param.core.eTintMode=TINTCORRECT_STRONGEST;
param.core.fTintScale=0.50f;
param.core.bVibrancy=true;
param.core.iVibrancy=0;
param.core.bUseAutomaticStrengthSelection=true;
param.core.eAggressiveness=AGGRESSIVENESS_MODERATE;
param.core.iMaxStrength=100;
param.core.iStrength=0;
param.core.bContrast=true;
param.core.iContrast=93;
param.core.eContrastMode=HIGH_DEFINITION;
param.core.iBlackEnhancement=12;
param.core.eBiasMode=BIAS_AVERAGE_PREFERENCE;
param.core.fBiasScale=0.30f;
param.core.bSharpen=true;
param.core.fSharpenScale=0.60f;
param.core.bInfrared=true;
param.core.fInfrared=0.75f;
param.core.bDCF=false;
param.core.eDCFMode=DCF_STANDARD;
param.core.fDCF=0.50f;
param.core.bLightDiffusion=false;
param.core.fLightDiffusion=0.50f;
param.core.bUseFAE=true;
param.core.bDynamicRange=true;
//PFCNRPARAM
param.nr.bEnabled=false;
param.nr.iPreset=0;
param.nr.iStrengthOffset=0;
param.nr.iDetailOffset=0;
//PFCREPARAM
param.re.bEnabled=true;
//PFCFBPARAM
param.fb.bEnabled=true;
param.fb.bSmooth=true;
param.fb.iSmoothLevel=36;
param.fb.eSmoothMode=SKINMODE_FACE;
param.fb.eSmoothType=SKINSMOOTHTYPE_SUBTLE;
param.fb.bEnlarge=false;
param.fb.iEnlargeLevel=0;
param.fb.bEnhance=true;
param.fb.iEnhanceLevel=50;
param.fb.bEyeCirc=true;
param.fb.iEyeCirc=28;
param.fb.bTeeth=false;
param.fb.iTeethLevel=0;
param.fb.bBlemish=false;
param.fb.iBlemish=0;
param.fb.bSlim=false;
param.fb.iSlim=0;
param.fb.bDeFlash=true;
param.fb.iDeFlash=8;
param.fb.bCatchLight=false;
param.fb.iCatchLight=0;
param.fb.iCatchLightMode=1;
param.fb.bSkinToning=false;
param.fb.iSkinToning=0;
param.fb.eSkinToningMode=SKINMODE_FACE;
param.fb.eSkinToningType=SKINTONINGTYPE_PALE;
param.fb.bLipSharpen=false;
param.fb.iLipSharpen=0;
param.fb.eLipSharpenType=LIPSHARPENTYPE_FINE;
param.fb.bBlush=false;
param.fb.iBlush=0;
//PCC V3 ADDITIONS
param.v3.bPreprocessEV=false;
param.v3.iPreprocessEV=0;
param.v3.iNeutralDensity=0;
param.v3.iColorVibrancy=0;
strcpy(param.v3.lutInputCorrective.guid,"00000000000000000000000000000000");
param.v3.lutInputCorrective.strength=0;
strcpy(param.v3.lutInputSky.guid,"00000000000000000000000000000000");
param.v3.lutInputSky.strength=0;
strcpy(param.v3.lutInputFoliageGreen.guid,"00000000000000000000000000000000");
param.v3.lutInputFoliageGreen.strength=0;
strcpy(param.v3.lutInputFoliageBrown.guid,"00000000000000000000000000000000");
param.v3.lutInputFoliageBrown.strength=0;
strcpy(param.v3.lutOutput.guid,"00000000000000000000000000000000");
param.v3.lutOutput.strength=0;
//This layer is DISABLED. Ignore this set of params if you wish
param.layer[0].iFinishTemp=0;
param.layer[0].iFinishTint=0;
param.layer[0].iFinishExposure=0;
param.layer[0].iFinishBlacks=0;
param.layer[0].iFinishShadows=0;
param.layer[0].iFinishHighlights=0;
param.layer[0].iFinishWhites=0;
param.layer[0].iFinishSaturation=0;
param.layer[0].iFinishVibrancy=0;
param.layer[0].iFinishContrast=0;
strcpy(param.layer[0].lutInputSky.guid,"00000000000000000000000000000000");
param.layer[0].lutInputSky.strength=0;
strcpy(param.layer[0].lutInputFoliageGreen.guid,"00000000000000000000000000000000");
param.layer[0].lutInputFoliageGreen.strength=0;
strcpy(param.layer[0].lutInputFoliageBrown.guid,"00000000000000000000000000000000");
param.layer[0].lutInputFoliageBrown.strength=0;
param.mask[0].type=MASK_NONE;
param.mask[0].centerX=0.50000000f;
param.mask[0].centerY=0.50000000f;
param.mask[0].width=1.17910051f;
param.mask[0].height=1.17910051f;
param.mask[0].radius=0.00000000f;
param.mask[0].feather=0.80000001f;
param.mask[0].angle=0.00000000f;
param.mask[0].transparency=0.00000000f;
param.mask[0].invert=false;
//This layer is DISABLED. Ignore this set of params if you wish
param.layer[1].iFinishTemp=0;
param.layer[1].iFinishTint=0;
param.layer[1].iFinishExposure=0;
param.layer[1].iFinishBlacks=0;
param.layer[1].iFinishShadows=0;
param.layer[1].iFinishHighlights=15;
param.layer[1].iFinishWhites=0;
param.layer[1].iFinishSaturation=-20;
param.layer[1].iFinishVibrancy=0;
param.layer[1].iFinishContrast=-25;
strcpy(param.layer[1].lutInputSky.guid,"00000000000000000000000000000000");
param.layer[1].lutInputSky.strength=0;
strcpy(param.layer[1].lutInputFoliageGreen.guid,"00000000000000000000000000000000");
param.layer[1].lutInputFoliageGreen.strength=0;
strcpy(param.layer[1].lutInputFoliageBrown.guid,"00000000000000000000000000000000");
param.layer[1].lutInputFoliageBrown.strength=0;
param.mask[1].type=MASK_NONE;
param.mask[1].centerX=0.50000000f;
param.mask[1].centerY=0.50000000f;
param.mask[1].width=1.17910051f;
param.mask[1].height=1.17910051f;
param.mask[1].radius=0.00000000f;
param.mask[1].feather=0.80000001f;
param.mask[1].angle=0.00000000f;
param.mask[1].transparency=0.00000000f;
param.mask[1].invert=true;
//This layer is DISABLED. Ignore this set of params if you wish
param.layer[2].iFinishTemp=0;
param.layer[2].iFinishTint=0;
param.layer[2].iFinishExposure=0;
param.layer[2].iFinishBlacks=0;
param.layer[2].iFinishShadows=0;
param.layer[2].iFinishHighlights=0;
param.layer[2].iFinishWhites=0;
param.layer[2].iFinishSaturation=0;
param.layer[2].iFinishVibrancy=0;
param.layer[2].iFinishContrast=0;
param.mask[2].type=MASK_NONE;
param.mask[2].centerX=0.50000000f;
param.mask[2].centerY=0.50000000f;
param.mask[2].width=0.00000000f;
param.mask[2].height=0.00000000f;
param.mask[2].radius=0.00000000f;
param.mask[2].feather=0.50000000f;
param.mask[2].angle=0.00000000f;
param.mask[2].transparency=0.00000000f;
param.mask[2].invert=false;