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:
| Method | Description |
|---|---|
LoadScenePresets | Load AI Scene Detection presets |
AutoCorrect | Single-call correction with optional preset |
Calc | Analyze image and calculate correction profile |
Apply | Apply corrections using calculated profile |
LoadAiEngine | Load AI models for scene detection |
ReadPresets | Load 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:
| Method | Description |
|---|---|
LoadImage | Load image from file path |
SaveImage | Save image to file path |
ExpandImageBuffer | Load from MemoryStream |
CompressImageBuffer | Save 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 type | Notes |
|---|---|---|
BOOL | bool | |
int | int | |
float | float | |
PFCPARAM | PFCPARAM | Struct, accessed via Pfc.m_Param |
PFCCOREPARAM | PFCCOREPARAM | Struct |
PFCFBPARAM | PFCFBPARAM | Struct |
PFCNRPARAM | PFCNRPARAM | Struct |
PFCPRESETID | PFCPRESETID | Enum |
PFCFEATURE | PFCFEATURE | Enum/flags |
PFCAIFEATURE | PFCAIFEATURE | Enum/flags |
PFCAPPLYSTATUS | PFCAPPLYSTATUS | Enum |
TINTCORRECTION | TINTCORRECTION | Enum |
CONTRASTMODE | CONTRASTMODE | Enum |
BIASMODE | BIASMODE | Enum |
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:
| Value | Meaning |
|---|---|
0 | Success (APPLY_SUCCESS) |
> 0 | Partial success with warnings |
< 0 | Error (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:
| Code | Enum | Meaning |
|---|---|---|
-1 | APPLY_ERROR_PROFILE_MISSING | Profile pointer is null |
-2 | APPLY_ERROR_ENGINE_MISSING | Engine pointer is null |
-4 | APPLY_NOSOURCE | Source image is null |
-5 | APPLY_BADFORMAT | Unsupported pixel format |
-6 | APPLY_INVALIDLICENSE | License validation failed |
PFC-SDK Version 10.7.2.1269 built from 4fa849d8101945eea725a08dd0dae5101f090fa0 on 11-10-2025.
Copyright © 2026 EyeQ Imaging Inc. All rights reserved.