Perfectly Clear SDK Documentation  9.0.1.315
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

NOTES:

  • V3 LOOKs support is provided via an optional "v3.looks" file that should be deployed along with the SDK library files. The supported LOOKs are listed here.
  • Finishing Tools and Graduated Filters are not supported on mobile platforms at this time.
  • These various corrections are best previewed and evaluated in our desktop applications like Perfectly Clear Complete, Workbench or QuickDesk. You can export these settings to be used in the SDK, as described below.

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 the iAuto '21 preset.
PFC_SetParam(param, PRESET_IAUTO_21);

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://eyeq.photos/help/plugins/en/PerfectlyClearWorkbench-v3/index.html?about_the_perfectly_clear_interface.html#presetspanel

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://eyeq.photos/help/plugins/en/PerfectlyClearWorkbench-v3/index.html?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_AGGRESSIVE;
param.core.fTintScale=0.49f;
param.core.bVibrancy=true;
param.core.iVibrancy=0;
param.core.bUseAutomaticStrengthSelection=true;
param.core.eAggressiveness=AGGRESSIVENESS_AGGRESSIVE;
param.core.iMaxStrength=125;
param.core.iStrength=30;
param.core.bContrast=true;
param.core.iContrast=87;
param.core.eContrastMode=HIGH_DEFINITION;
param.core.iBlackEnhancement=12;
param.core.eBiasMode=BIAS_AVERAGE_PREFERENCE;
param.core.fBiasScale=0.09f;
param.core.bSharpen=true;
param.core.fSharpenScale=1.00f;
param.core.bInfrared=true;
param.core.fInfrared=1.00f;
param.core.bDCF=false;
param.core.eDCFMode=DCF_STANDARD;
param.core.fDCF=0.50f;
param.core.bLightDiffusion=false;
param.core.fLightDiffusion=0.20f;
param.core.bUseFAE=true;
param.core.bDynamicRange=true;
// PFCNRPARAM - Noise Removal
param.nr.bEnabled=false;
param.nr.iPreset=0;
param.nr.iStrengthOffset=0;
param.nr.iDetailOffset=0;
// PFCREPARAM - Red Eye Correction
param.re.bEnabled=false;
// PFCFBPARAM - Face Beautification
param.fb.bEnabled=true;
param.fb.bSmooth=false;
param.fb.iSmoothLevel=0;
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=false;
param.fb.iDeFlash=0;
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=10;
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;
//4 params below require PFC SDK 8.4+
param.v3.iFinishPositiveContrast=65;
param.v3.iDeltaR=0;
param.v3.iDeltaG=0;
param.v3.iDeltaB=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.17910004f;
param.mask[0].height=1.17910004f;
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=-25;
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.17910004f;
param.mask[1].height=1.17910004f;
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;

About Specific Correction Parameter Code

Most of the correction parameter code directly corresponds to controls in our EyeQ application user interface. For example, the code param.core.fSharpenScale=1.00f; corresponds to a Sharpness value of 100. The labels in the applications change over time for marketing and user experience reasons, however we do not change the parameter names - in order to preserve backwards compatibility. This section will discuss various differences between our EyeQ application interface and the code use to set these parameters. Please note that it's always safest to use the Export to API feature in Perfectly Clear Workbench to get exact parameter code that corresponds to specific settings as previewed in Workbench.

Color Vibrancy and Color Restore

You'll find a control in Perfectly Clear applications labelled as 'Color Restore'. This control corresponds to iVibrancy in this SDK. The name of this correction was changed when we launched our "V3" products - to make room for the more traditional 'Color Vibrancy' control (which corresponds to iColorVibrancy). Apart from this naming difference there is another important change in the V3 products and this SDK. When iVibrancy is set to zero, this triggers a separate Vibrancy correction algorithm, one designed to be more gentle, especially on low dynamic range images. If iVibrancy is 1 or larger, then our traditional Vibrancy correction is applied. This change of operation was confusing to our customers, so in the user interface for all EyeQ products, we display the value for this setting PLUS ONE. So, in the user interface, 0 is totally off (iVibrancy = -1), 1 uses the new algorithm (iVibrancy = 0) and 2 or higher (iVibrancy = 1 or more) uses the traditional approach. We encourage you to adopt a similar process if you display the iVibrancy parameter value to your customers.

Layers & Masks

There are three sets of parameters grouped into layers - Layer 1 and Layer 2 are the features applied in the "Graduated Filter" tool, and Layer 3 contains the "Finishing Tools". The mask[] parameters control how the gradients are applied, with type=MASK_NONE disabling this layer. These corrections are ususally very specific to a particular image's content - like location of a face or horizon - and as such these are rarely included in presets that will be applied to a broad range of images.

Param Value Mapping

Some correction parameters do not map directly from the user interface of Workbench to the param code used in this SDK. Sometimes, this is to simplify the user experience and sometimes it is to maintain previous SDK backwards compatibility. Below is a list of these non-linear parameters and how to derive the proper SDK values based on the user interface in Workbench:

Workbench Control SDK param code Mapping
Color Restore param.core.iVibrancy (Color Restore + 1) = param.core.iVibrancy
Image Ambulance param.v3.iPreprocessEV Range in Workbench is ±5, value of iPreprocessEV is 120 to 21 and -120 to -21
(Image Ambulance) += (Image Ambulance) >= 0 ? 1 : -1; Param.v3.iPreprocessEV = (int) (-20.0 * (Image Ambulance));

Setting LOOKs with GUIDs

Several parameters use "LOOKs" to apply corrections, and the code to specific which LOOK to apply uses a GUID string like:

strcpy(param.v3.lutInputCorrective.guid,"123451234512345");

This is a hash of the full path and filename of the LOOK file, as packaged in the EyeQ applications and SDK. To determine the GUID string to include in your code, you should run Workbench, preview the LOOK you want to apply, then Export to API as shown above. It is not practical to attempt to determine the GUID hashed outside of the Workbench application.