.NET/C# Quickstart
Getting started with Perfectly Clear SDK in .NET/C#
This guide walks you through correcting your first image using the Perfectly Clear SDK. This is a very simple example - it AI Scene Detection with the default Universal model. See the Sample projects section later in this guide for more complex examples, including using single presets, re-processing the same image with different correction parameters, and different I/O methods.
Prerequisites
Before you begin, ensure that you have:
- Windows operating system (x64)
- .NET 8 SDK installed on your PC.
Verify your installation by running dotnet --version in your terminal.
Project structure
Set up your project directory with the SDK extracted alongside your source files:
my-project/
├── Program.cs
├── sample.jpg
├── my-preset.preset
├── quick-dotnet.csproj
└── perfectly-clear-sdk/
├── Win/
│ └── bin/
│ └── x64/
│ ├── PerfectlyClearAdapter.dll
│ ├── PerfectlyClearPro.dll
│ ├── PFCImageFile.dll
│ ├── exiv2.dll
│ └── v3.looks
└── sdk_license/
└── (license files)Activate the SDK license
Create a PerfectlyClear instance with the path to your license files. The constructor activates the license automatically.
using PerfectlyClearAdapter;
string exePath = AppDomain.CurrentDomain.BaseDirectory;
string licensePath = Path.Combine(exePath, "sdk_license");
PerfectlyClear pfc = new PerfectlyClear(licensePath);
if (pfc == null)
{
Console.WriteLine("License activation failed");
return;
}
Console.WriteLine("SDK license activated successfully");The license files are copied to the output directory during build, so use AppDomain.CurrentDomain.BaseDirectory to locate them relative to the executable.
Load an image
Use standard .NET file I/O to read an image from disk.
Bitmap bm = new Bitmap(inputFile);
// Check if image opened successfully.
if (bm == null)
{
Console.WriteLine("Unable to open image.");
return;
}Apply auto-correction with Universal AI Model
Create an engine and call PFC_AutoCorrect().
// Load AI engine (assuming all dlls and models are in exe folder):
string execPath = AppDomain.CurrentDomain.BaseDirectory;
Pfc.LoadAiEngine(PFCAIFEATURE.AI_SCENE_DETECTION | PFCAIFEATURE.AI_CORRECTIONS | PFCAIFEATURE.AI_COLOR | PFCAIFEATURE.AI_FACEMESH, execPath);
// then apply auto correction, including loading and applying the default Universal model:
Pfc.AutoCorrect(ref bm);Save output
Save the corrected image using .NET file I/O.
bm.Save("output.jpg");Complete example
Create Program.cs:
using System;
using System.Drawing;
using System.IO;
using PerfectlyClearAdapter;
class Program
{
static void Main(string[] args)
{
if (args.Length < 2)
{
Console.WriteLine("Usage: quick-dotnet <input.jpg> <output.jpg>");
return;
}
string inputFile = args[0];
string outputFile = args[1];
string exePath = AppDomain.CurrentDomain.BaseDirectory;
string licensePath = Path.Combine(exePath, "sdk_license");
PerfectlyClear pfc = new PerfectlyClear(licensePath);
if (pfc == null)
{
Console.WriteLine("License activation failed");
return;
}
Console.WriteLine("SDK license activated successfully");
Bitmap bm = new Bitmap(inputFile);
// Check if image opened successfully.
if (bm == null)
{
Console.WriteLine("Unable to open image.");
return;
}
// Load AI engine (assuming all dlls and models are in exe folder):
string execPath = AppDomain.CurrentDomain.BaseDirectory;
Pfc.LoadAiEngine(PFCAIFEATURE.AI_SCENE_DETECTION | PFCAIFEATURE.AI_CORRECTIONS | PFCAIFEATURE.AI_COLOR | PFCAIFEATURE.AI_FACEMESH, execPath);
// then apply auto correction, including loading and applying the default Universal model:
int aret = Pfc.AutoCorrect(ref bm);
// Check if there's any warning
if (aret > 0)
{
// In case of warnings, query LastStatus for individual return code
Console.WriteLine("Noise removal return code: " + Pfc.LastStatus.NR_Status.ToString());
Console.WriteLine("Perfectly Clear core return code: " + Pfc.LastStatus.CORE_Status.ToString());
Console.WriteLine("Face beautification return code: " + Pfc.LastStatus.FB_Status.ToString());
Console.WriteLine("Red eye removal return code: " + Pfc.LastStatus.RE_Status.ToString());
}
else if (aret < 0)
{
// In case of general process error (negative return code)
Console.WriteLine("Perfectly Clear return code: " + aret.ToString());
}
// Save processed image.
bm.Save(outputFile);
}
}Create quick-dotnet.csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Platform>x64</Platform>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>disable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
</PropertyGroup>
<PropertyGroup>
<SdkPath>.\perfectly-clear-sdk</SdkPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="Program.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="PerfectlyClearAdapter">
<HintPath>$(SdkPath)\Win\bin\x64\PerfectlyClearAdapter.dll</HintPath>
</Reference>
<PackageReference Include="System.Drawing.Common" Version="8.0.0" />
</ItemGroup>
<Target Name="CopyDependencies" BeforeTargets="Build">
<Copy SourceFiles="$(SdkPath)\Win\bin\x64\PerfectlyClearPro.dll" DestinationFolder="$(OutputPath)" />
<Copy SourceFiles="$(SdkPath)\Win\bin\x64\PerfectlyClearAdapter.dll" DestinationFolder="$(OutputPath)" />
<Copy SourceFiles="$(SdkPath)\Win\bin\x64\PFCImageFile.dll" DestinationFolder="$(OutputPath)" />
<Copy SourceFiles="$(SdkPath)\Win\bin\x64\exiv2.dll" DestinationFolder="$(OutputPath)" />
<Copy SourceFiles="$(SdkPath)\Win\bin\x64\v3.looks" DestinationFolder="$(OutputPath)" />
</Target>
<Target Name="CopyLicense" AfterTargets="Build">
<ItemGroup>
<LicenseFiles Include="$(SdkPath)\sdk_license\**\*" />
</ItemGroup>
<Copy SourceFiles="@(LicenseFiles)" DestinationFolder="$(OutputPath)\sdk_license\%(RecursiveDir)" />
</Target>
</Project>Build and run:
dotnet build
dotnet run -- input.jpg output.jpgExpected output:
SDK license activated successfully
Image corrected successfully
Saved to: output.jpgPFC-SDK Version 10.7.3.1317 built from df9dbc8727c92fb9b1d2c68b21e60ea9c7229e1a on 03-23-2026.
Copyright © 2026 EyeQ Imaging Inc. All rights reserved.