EyeQ Docs

Using the .NET/C# API

In-depth guide to using the Perfectly Clear CLI

The .NET API provides a managed wrapper around the native Perfectly Clear library. It's designed for Windows applications using C# or VB.NET and integrates with standard .NET types like Bitmap and MemoryStream.

Core classes

The .NET API provides two main classes: PerfectlyClear for correction operations and PFCImageFile for image loading with color management.

The PerfectlyClear class is the main entry point for image correction. It manages the native engine and provides methods for analysis and correction.

using PerfectlyClearAdapter;

// Single-threaded: pass license path to constructor
PerfectlyClear Pfc = new PerfectlyClear("C:\\path\\to\\sdk_license");

// Multi-threaded: set path once, then create instances without arguments
PerfectlyClear.SetProtectionPath("C:\\path\\to\\sdk_license");
PerfectlyClear Pfc = new PerfectlyClear();
// ... use Pfc ...
Pfc.Dispose();
PerfectlyClear.ReleaseProtectionPath();

Key methods:

MethodDescription
LoadScenePresetsLoad AI Scene Detection presets
AutoCorrectSingle-call correction with optional preset
CalcAnalyze image and calculate correction profile
ApplyApply corrections using calculated profile
LoadAiEngineLoad AI models for scene detection
ReadPresetsLoad parameters from a .preset file

The PFCImageFile class handles image loading with automatic color space conversion and metadata preservation.

PFCImageFile file = new PFCImageFile();
file.LoadImage("input.jpg");

// Process with PerfectlyClear
Pfc.AutoCorrect(ref file, "preset.preset");

// Save with quality setting
file.SaveImage("output.jpg", 90);

Key methods:

MethodDescription
LoadImageLoad image from file path
SaveImageSave image to file path
ExpandImageBufferLoad from MemoryStream
CompressImageBufferSave to MemoryStream

Parameter mapping

The .NET API uses the same parameter structures as the C API. The PFCPARAM struct and its nested components map directly, making it straightforward to translate between C and C# code.

The main parameter structure contains nested structs for each correction category:

public struct PFCPARAM {
    public PFCCOREPARAM core;
    public PFCFBPARAM fb;
    public PFCNRPARAM nr;
    public PFCREPARAM re;
    public PFCV3PARAM v3;
    public DP2PARAM dp2;
}

The following table shows how C types map to .NET types:

C type.NET typeNotes
BOOLbool
intint
floatfloat
PFCPARAMPFCPARAMStruct, accessed via Pfc.m_Param
PFCCOREPARAMPFCCOREPARAMStruct
PFCFBPARAMPFCFBPARAMStruct
PFCNRPARAMPFCNRPARAMStruct
PFCPRESETIDPFCPRESETIDEnum
PFCFEATUREPFCFEATUREEnum/flags
PFCAIFEATUREPFCAIFEATUREEnum/flags
PFCAPPLYSTATUSPFCAPPLYSTATUSEnum
TINTCORRECTIONTINTCORRECTIONEnum
CONTRASTMODECONTRASTMODEEnum
BIASMODEBIASMODEEnum

After creating a PerfectlyClear instance, access parameters through m_Param:

PerfectlyClear Pfc = new PerfectlyClear("C:\\path\\to\\sdk_license");

// Access and modify parameters
Pfc.m_Param.core.bEnabled = true;
Pfc.m_Param.core.iStrength = 120;
Pfc.m_Param.core.bContrast = true;
Pfc.m_Param.core.iContrast = 50;

// Face beautification
Pfc.m_Param.fb.bEnabled = true;
Pfc.m_Param.fb.bSmooth = true;
Pfc.m_Param.fb.iSmoothLevel = 30;

Examples

The following examples demonstrate common integration patterns for .NET applications, from simple single-call correction to multi-threaded batch processing.

The simplest approach uses AutoCorrect which handles analysis and correction in one call.

using System.Drawing;
using PerfectlyClearAdapter;

// Create instance with license
PerfectlyClear Pfc = new PerfectlyClear("C:\\path\\to\\sdk_license");

// Load image
Bitmap bm = new Bitmap("input.jpg");

// Apply corrections
int result = Pfc.AutoCorrect(ref bm);

if (result >= 0) {
    bm.Save("output.jpg");
}

For more control, use separate Calc and Apply calls.

PerfectlyClear Pfc = new PerfectlyClear("C:\\path\\to\\sdk_license");
Bitmap bm = new Bitmap("input.jpg");

// Step 1: Analyze
ADPTRRETURNCODE calcResult = Pfc.Calc(ref bm, PFCFEATURE.CALC_ALL, -1, null);

// Modify parameters before applying
Pfc.m_Param.core.iStrength = 130;
Pfc.m_Param.core.eContrastMode = CONTRASTMODE.HIGH_DEFINITION;

// Step 2: Apply
PFCAPPLYSTATUS applyResult = Pfc.Apply(ref bm, 100);

bm.Save("output.jpg");

Load AI models for automatic scene detection.

PerfectlyClear Pfc = new PerfectlyClear("C:\\path\\to\\sdk_license");

// Load AI engine
string binPath = AppDomain.CurrentDomain.BaseDirectory;
int aiStatus = Pfc.LoadAiEngine(
    PFCAIFEATURE.AI_SCENE_DETECTION | 
    PFCAIFEATURE.AI_CORRECTIONS | 
    PFCAIFEATURE.AI_COLOR | 
    PFCAIFEATURE.AI_FACEMESH,
    binPath);

// Verify features loaded
if ((aiStatus & (int)PFCAIFEATURE.AI_SCENE_DETECTION) == 0) {
    Console.WriteLine("Scene detection not loaded");
}

// Correct with scene detection
Bitmap bm = new Bitmap("input.jpg");
int result = Pfc.AutoCorrect(ref bm);

bm.Save("output.jpg");

Load correction parameters from a preset file exported from Workbench.

PerfectlyClear Pfc = new PerfectlyClear("C:\\path\\to\\sdk_license");

// Load preset
int rc = Pfc.ReadPresets("path\\to\\corrections.preset");
if (rc != 0) {
    Console.WriteLine("Failed to load preset: " + rc);
    return;
}

// Apply with loaded preset
Bitmap bm = new Bitmap("input.jpg");
Pfc.AutoCorrect(ref bm);
bm.Save("output.jpg");

Use PFCImageFile for automatic color space handling and metadata preservation.

PerfectlyClear Pfc = new PerfectlyClear("C:\\path\\to\\sdk_license");

// Load with PFCImageFile
PFCImageFile file = new PFCImageFile();
file.LoadImage("input.jpg");

// Correct
Pfc.Calc(ref file, PFCFEATURE.CALC_ALL, -1, null);
Pfc.Apply(ref file, 100);

// Save with metadata preserved
file.SaveImage("output.jpg", 90);

For multi-threaded scenarios, set the protection path once and create separate instances per thread.

// At application startup
PerfectlyClear.SetProtectionPath("C:\\path\\to\\sdk_license", "");

// In each thread
void ProcessImages(string[] paths) {
    PerfectlyClear Pfc = new PerfectlyClear();
    
    foreach (string path in paths) {
        Bitmap bm = new Bitmap(path);
        Pfc.AutoCorrect(ref bm);
        bm.Save(GetOutputPath(path));
        bm.Dispose();
    }
    
    Pfc.Dispose();
}

// At application shutdown
PerfectlyClear.ReleaseProtectionPath();

MemoryStream usage

For applications that work with in-memory image data, see the I/O patterns page which covers MemoryStream integration with PFCImageFile.ExpandImageBuffer and CompressImageBuffer.

Status and error handling

The SDK uses integer return codes to indicate success, warnings, or errors. Understanding these codes helps you handle edge cases and debug issues.

The AutoCorrect method returns an integer status code:

ValueMeaning
0Success (APPLY_SUCCESS)
> 0Partial success with warnings
< 0Error (see PFCAPPLYSTATUS enum)

After Calc or Apply, check LastStatus for detailed component statuses:

int result = Pfc.AutoCorrect(ref bm);

if (result > 0) {
    Console.WriteLine("NR: " + Pfc.LastStatus.NR_Status);
    Console.WriteLine("Core: " + Pfc.LastStatus.CORE_Status);
    Console.WriteLine("FB: " + Pfc.LastStatus.FB_Status);
    Console.WriteLine("RE: " + Pfc.LastStatus.RE_Status);
}

Common error codes:

CodeEnumMeaning
-1APPLY_ERROR_PROFILE_MISSINGProfile pointer is null
-2APPLY_ERROR_ENGINE_MISSINGEngine pointer is null
-4APPLY_NOSOURCESource image is null
-5APPLY_BADFORMATUnsupported pixel format
-6APPLY_INVALIDLICENSELicense validation failed

PFC-SDK Version 10.7.2.1269 built from 4fa849d8101945eea725a08dd0dae5101f090fa0 on 11-10-2025.

Copyright © 2026 EyeQ Imaging Inc. All rights reserved.

On this page