IRONSOFTWAREHOME
MIGRATION GUIDES

Migrating from Kofax OmniPage to IronOCR

Kannaopat Udonpant
Kannapat Udonpant
Updated: August 1, 2026

This guide is for .NET developers who are moving OCR workloads off the Kofax OmniPage Capture SDK (now marketed as Tungsten Automation) and onto IronOCR. It covers the complete migration path: removing the SDK installer dependency, eliminating the engine lifecycle ceremony, replacing zone-based recognition patterns, and modernizing error handling. No prior reading of the comparison article is required.

Why Migrate from Kofax OmniPage (Tungsten)

The OmniPage Capture SDK was designed for enterprise document management infrastructure in an era before NuGet, Docker, and CI/CD pipelines. Each of its architectural choices that made sense in 2005 creates friction in 2026.

The SDK installer has no place in a NuGet world. Every development machine, build agent, and production server that runs OmniPage code requires the Tungsten SDK installer to execute before compilation. There is no .csproj package reference to restore. Upgrading the SDK version means re-running the installer across the entire fleet. A new developer cannot run the project without contacting whoever manages the SDK license and waiting for installer access.

The license file is an operational liability. A .lic file must be present at a specific path on every machine that calls engine.Initialize(). Deploy to a new server and forget the file, and every OCR call fails with a license exception - not an OCR error. Use floating licenses and a network partition between your application server and the license server means every Initialize() call fails until connectivity restores, regardless of whether that machine successfully validated its license yesterday.

Engine lifecycle management leaks resources on error paths. OmniPageEngine.Shutdown() must be called in every possible code path - including exception handlers, early returns, and timeouts - or a floating license seat stays locked until the license server's checkout timeout expires. Writing defensively around this constraint means wrapping every integration point in IDisposable patterns that exist solely to protect against the engine shutdown being skipped.

Hardware fingerprinting conflicts with modern deployment. OmniPage activation ties to hardware. Container restarts, VM migrations, and cloud autoscaling all involve hardware identity changes that trigger reactivation requirements. A deployment model incompatible with autoscaling is a deployment model incompatible with cloud infrastructure.

Per-page pricing is unpredictable at scale. A document processing spike - a new client onboarded, a backlog batch submitted - generates an overage invoice against a quota nobody budgeted for. IronOCR is perpetual and unlimited within the licensed tier: no per-page meter, no quota, no overage invoices.

The procurement process blocks shipping. The OmniPage SDK is sales-gated. Evaluation access, pricing, and contract terms all require a sales engagement that runs 4-12 weeks. Teams building OCR features under a product delivery deadline cannot wait for an enterprise procurement cycle. dotnet add package IronOcr resolves in 30 seconds. See the IronOCR licensing page for published, self-service pricing - $999 Lite through $2,999 Enterprise, all perpetual.

The Fundamental Problem

OmniPage requires a full initialization ceremony before the first byte is read, and a shutdown ceremony after the last - every call site must manage both:

// OmniPage: Ceremony required on EVERY entry point — init, process, shutdown
using var engine = new OmniPageEngine();
engine.SetLicenseFile(@"C:\Program Files\OmniPage\license.lic"); // File must exist here
engine.Initialize();   // Network call to license server — can fail for license reasons, not OCR reasons

var document = engine.CreateDocument();
document.AddPage("invoice.jpg");
document.Recognize(new RecognitionSettings { Language = "English" });
string text = document.GetText();
document.Dispose();    // Must not be skipped
engine.Shutdown();     // Must not be skipped — omitting this locks a floating seat
C#
// IronOCR: One NuGet package, one line at startup, one call to read
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"; // At app startup — once, ever
var text = new IronTesseract().Read("invoice.jpg").Text;
C#

The OmniPage version has eight distinct steps, two mandatory cleanup calls, a network dependency, and a file system dependency. The IronOCR version has two.

IronOCR vs Kofax OmniPage (Tungsten): Feature Comparison

The table below covers the capabilities most relevant to teams evaluating this migration.

FeatureKofax OmniPage SDKIronOCR
Installation methodCustom SDK installer (no NuGet)dotnet add package IronOcr
Time to first OCR call4-12 weeks (procurement) + hours (setup)30 seconds
License mechanism.lic file on disk + optional license serverString key at app startup
Hardware fingerprintingYes (reactivation on VM migration)No
License server requiredYes (for floating licenses)No
Per-page runtime billingAvailable (variable)No
Published pricingNo (contact sales)Yes ($999 / $1,499 / $2,999 perpetual)
Annual maintenance fees18-25% of license costOptional
Engine lifecycle managementRequired (Initialize / Shutdown)Not required
Windows x64YesYes
LinuxYes (added January 2026)Yes (all versions)
macOSNoYes
Docker / KubernetesDifficult (installer + license file in image)Straightforward (NuGet package only)
Azure / AWS LambdaComplex (license server reachability)Straightforward
Image input formatsYesJPG, PNG, BMP, TIFF, GIF, and more
Native PDF inputYes (may require module license)Yes (built-in, no extra license)
Multi-page TIFFYesYes
Searchable PDF outputYesYes (result.SaveAsSearchablePdf())
Automatic preprocessingSettings-object configurationBuilt-in + explicit pipeline API
Languages supported120+125+ (separate NuGet packages)
Structured data outputYes (word coordinates)Pages, Paragraphs, Lines, Words, Characters with coordinates
Confidence scoringYesYes (result.Confidence, per-word)
Barcode readingAdd-on module (separate license)Built-in (ocr.Configuration.ReadBarCodes = true)
Thread safetyComplex (engine sharing constraints)Full (one IronTesseract per thread)
CI/CD pipeline supportRequires installer on every agentStandard dotnet restore

Quick Start: Kofax OmniPage to IronOCR Migration

Step 1: Replace the SDK with a NuGet Package

OmniPage has no NuGet package to remove. Remove the manual DLL references from the .csproj file and uninstall the SDK from development machines when the migration is complete. Then install IronOCR:

dotnet add package IronOcr

The IronOCR NuGet package bundles the OCR engine, preprocessing filters, and runtime components. No separate installer, no native DLL management, no component registration.

Step 2: Update Namespaces

// Before (Kofax OmniPage)
using Kofax.OmniPage.CSDK;
using Kofax.OmniPageCSDK;
using CSDK;

// After (IronOCR)
using IronOcr;
C#

Step 3: Initialize License

Add one line at application startup. This replaces the .lic file path, the license server configuration, and the engine.Initialize() call:

IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

Store the key in an environment variable (IRONOCR_LICENSE_KEY) or appsettings.json rather than source code. The key is read offline - no network call occurs at runtime.

Code Migration Examples

Engine Initialization Error Path Replacement

The most dangerous aspect of OmniPage's lifecycle model is not the happy path - it is the error path. Any exception thrown between engine.Initialize() and engine.Shutdown() can leave a floating license seat locked if Shutdown() is not reached. Production code requires try/finally blocks around every document processing call:

Kofax OmniPage Approach:

// OmniPage: try/finally required everywhere to protect license seat release
public string ProcessInvoice(string imagePath)
{
    var engine = new OmniPageEngine();
    engine.SetLicenseFile(@"C:\Program Files\OmniPage\license.lic");

    try
    {
        engine.Initialize(); // Contacts license server — failure here locks nothing
        var document = engine.CreateDocument();

        try
        {
            document.AddPage(imagePath);
            document.Recognize(new RecognitionSettings { Language = "English" });
            return document.GetText();
        }
        catch (RecognitionException ex)
        {
            // Log, rethrow — but Shutdown must still be called
            throw new OcrProcessingException("Recognition failed", ex);
        }
        finally
        {
            document.Dispose(); // Inner finally: release document
        }
    }
    catch (LicenseValidationException ex)
    {
        throw new OcrProcessingException("License validation failed", ex);
    }
    finally
    {
        engine.Shutdown(); // Outer finally: release license seat — MUST execute
    }
}
C#

IronOCR Approach:

// IronOCR: No license seat to release, no engine to shut down
public string ProcessInvoice(string imagePath)
{
    using var input = new OcrInput();
    input.LoadImage(imagePath);

    var ocr = new IronTesseract();
    var result = ocr.Read(input);
    return result.Text;
    // OcrInput disposal is automatic — no license implications on any code path
}
C#

The using block on OcrInput handles memory cleanup for the loaded image data. No try/finally exists to protect a license seat. An exception anywhere in this method has no side effects outside the method's own scope. See the IronTesseract setup guide for configuration options including thread-local instances.

Zone-Based Recognition Migration

OmniPage's primary structured extraction mechanism is zone definition: document regions are declared with coordinate boundaries and recognition type per zone (OCR, ICR, OMR, barcode). Developers define FormZone objects per document template and pass them to the recognition engine. IronOCR uses CropRectangle to achieve the same targeted extraction without template management or zone type declarations:

Kofax OmniPage Approach:

// OmniPage: Zone-based form extraction with template management
public Dictionary<string, string> ExtractInvoiceFields(string invoicePath)
{
    using var engine = new OmniPageEngine();
    engine.SetLicenseFile(licensePath);
    engine.Initialize();

    // Define zones per document template
    var zones = new List<FormZone>
    {
        new FormZone { Name = "InvoiceNumber", Type = "OCR",
            X = 520, Y = 80, Width = 200, Height = 30 },
        new FormZone { Name = "InvoiceDate",   Type = "OCR",
            X = 520, Y = 120, Width = 200, Height = 30 },
        new FormZone { Name = "TotalAmount",   Type = "OCR",
            X = 520, Y = 580, Width = 200, Height = 30 },
        new FormZone { Name = "VendorName",    Type = "OCR",
            X = 50,  Y = 80,  Width = 300, Height = 40 }
    };

    var template = new FormTemplate { Name = "StandardInvoice", Zones = zones };
    var settings = new RecognitionSettings { Language = "English" };

    var document = engine.CreateDocument();
    document.AddPage(invoicePath);
    document.ApplyTemplate(template);
    document.Recognize(settings);

    var fields = new Dictionary<string, string>();
    foreach (var zone in zones)
        fields[zone.Name] = document.GetZoneText(zone.Name);

    document.Dispose();
    engine.Shutdown();
    return fields;
}
C#

IronOCR Approach:

// IronOCR: CropRectangle targets specific regions — no template management
public Dictionary<string, string> ExtractInvoiceFields(string invoicePath)
{
    var fields = new Dictionary<string, string>();
    var ocr = new IronTesseract();

    // Extract each field by reading only the target region
    var fieldRegions = new Dictionary<string, CropRectangle>
    {
        ["InvoiceNumber"] = new CropRectangle(520, 80,  200, 30),
        ["InvoiceDate"]   = new CropRectangle(520, 120, 200, 30),
        ["TotalAmount"]   = new CropRectangle(520, 580, 200, 30),
        ["VendorName"]    = new CropRectangle(50,  80,  300, 40)
    };

    foreach (var (fieldName, region) in fieldRegions)
    {
        using var input = new OcrInput();
        input.LoadImage(invoicePath, region);
        fields[fieldName] = ocr.Read(input).Text.Trim();
    }

    return fields;
}
C#

Each CropRectangle specifies (x, y, width, height) in pixels. The OCR engine processes only the nominated region, not the full page - the same efficiency benefit that zone-based processing provides in OmniPage. The region-based OCR guide covers coordinate selection patterns, including how to extract multiple regions from a single image load using OcrInput's multi-region API.

Structured Data Output Migration

OmniPage exposes document structure through a proprietary export pipeline: format settings are applied to a recognized document, and output is written to a file in a specified format (RTF, XML, CSV, searchable PDF). Accessing word-level coordinates requires iterating a result iterator with explicit position queries. IronOCR exposes the same structured data directly on the result object without a secondary export step:

Kofax OmniPage Approach:

// OmniPage: Structured output requires format configuration and file export
public void ExtractStructuredContent(string imagePath, string outputDir)
{
    using var engine = new OmniPageEngine();
    engine.SetLicenseFile(licensePath);
    engine.Initialize();

    var settings = new RecognitionSettings { Language = "English" };
    var document = engine.CreateDocument();
    document.AddPage(imagePath);
    document.Recognize(settings);

    // Word-level coordinates through result iterator
    var iterator = document.GetResultIterator(ResultIteratorLevel.Word);
    while (iterator.MoveNext())
    {
        string word = iterator.GetText();
        var bounds = iterator.GetBoundingBox();
        double confidence = iterator.GetConfidence();
        Console.WriteLine($"Word: {word} at ({bounds.X},{bounds.Y}) conf:{confidence:F1}%");
    }

    // Structured export requires separate output format configuration
    var outputSettings = new OutputSettings
    {
        Format = OutputFormat.XML,
        IncludeCoordinates = true,
        IncludeConfidence = true
    };
    document.SaveAs(Path.Combine(outputDir, "output.xml"), outputSettings);

    document.Dispose();
    engine.Shutdown();
}
C#

IronOCR Approach:

// IronOCR: Structured data directly on OcrResult — no export step
public void ExtractStructuredContent(string imagePath)
{
    var result = new IronTesseract().Read(imagePath);

    Console.WriteLine($"Confidence: {result.Confidence:F1}%");
    Console.WriteLine($"Pages: {result.Pages.Length}");

    foreach (var page in result.Pages)
    {
        foreach (var paragraph in page.Paragraphs)
        {
            Console.WriteLine($"[Paragraph at ({paragraph.X},{paragraph.Y})]");
            Console.WriteLine(paragraph.Text);

            foreach (var word in paragraph.Words)
            {
                // Per-word confidence and coordinates — no iterator needed
                Console.WriteLine(
                    $"  Word: '{word.Text}' " +
                    $"at ({word.X},{word.Y}) " +
                    $"conf: {word.Confidence:F1}%");
            }
        }
    }
}
C#

The OcrResult object's hierarchy - Pages, Paragraphs, Lines, Words, Characters - provides the same positional data OmniPage's result iterator exposes, but as a navigable object graph rather than a sequential cursor. Confidence scores are available at the result, page, paragraph, and word level without additional configuration. The read results guide covers all structured data properties, and the confidence scores guide covers per-word validation patterns.

Multi-Page TIFF Processing Migration

OmniPage's multi-page TIFF workflow requires page-by-page extraction from the TIFF container, with a separate recognition call and document disposal per page. This creates both boilerplate and a resource management surface area proportional to the page count. IronOCR loads multi-frame TIFF files in a single call:

Kofax OmniPage Approach:

// OmniPage: Page-by-page TIFF extraction with per-page lifecycle
public List<string> ExtractFromMultiPageTiff(string tiffPath)
{
    var pageTexts = new List<string>();

    using var engine = new OmniPageEngine();
    engine.SetLicenseFile(licensePath);
    engine.Initialize();

    // Open TIFF and iterate frames
    var tiffContainer = engine.OpenTiff(tiffPath);
    int pageCount = tiffContainer.GetPageCount();

    var settings = new RecognitionSettings { Language = "English" };

    for (int i = 0; i < pageCount; i++)
    {
        var page = tiffContainer.GetPage(i); // Extract frame
        var document = engine.CreateDocument();

        try
        {
            document.AddPage(page);
            document.Recognize(settings);
            pageTexts.Add(document.GetText());
        }
        finally
        {
            document.Dispose(); // Dispose per page to manage memory
        }
    }

    tiffContainer.Dispose();
    engine.Shutdown();
    return pageTexts;
}
C#

IronOCR Approach:

// IronOCR: Multi-frame TIFF loaded in one call — all pages in one result
public List<string> ExtractFromMultiPageTiff(string tiffPath)
{
    using var input = new OcrInput();
    input.LoadImageFrames(tiffPath); // All frames loaded automatically

    var result = new IronTesseract().Read(input);

    // Each TIFF frame becomes a page in the result
    return result.Pages.Select(page => page.Text).ToList();
}
C#

LoadImageFrames reads every frame from the TIFF container in a single call. The result exposes one OcrResult.Page per frame, preserving the page-by-page structure without requiring a manual iteration loop or per-page cleanup. For production TIFF batch workflows, see the TIFF and GIF input guide.

Thread-Safe Parallel Processing Migration

OmniPage's engine is a shared, stateful resource. Sharing one OmniPageEngine instance across threads requires external synchronization because multiple threads calling CreateDocument() concurrently can produce interleaved state. The safe pattern - one engine instance per thread - conflicts with the engine's heavyweight initialization cost. IronOCR instances carry no shared state: create one IronTesseract per thread with zero coordination overhead:

Kofax OmniPage Approach:

// OmniPage: Shared engine with locking to serialize document operations
public ConcurrentDictionary<string, string> ProcessBatchWithEngine(
    string[] imagePaths, string licensePath)
{
    var results = new ConcurrentDictionary<string, string>();
    var engineLock = new object();

    // One engine — document operations must be serialized
    using var engine = new OmniPageEngine();
    engine.SetLicenseFile(licensePath);
    engine.Initialize();

    var settings = new RecognitionSettings { Language = "English" };

    Parallel.ForEach(imagePaths, imagePath =>
    {
        lock (engineLock) // Serialize: one recognition at a time
        {
            var document = engine.CreateDocument();
            try
            {
                document.AddPage(imagePath);
                document.Recognize(settings);
                results[imagePath] = document.GetText();
            }
            finally
            {
                document.Dispose();
            }
        }
    });

    engine.Shutdown();
    return results;
}
C#

IronOCR Approach:

// IronOCR: One IronTesseract per thread — no locking, genuine parallelism
public ConcurrentDictionary<string, string> ProcessBatchInParallel(string[] imagePaths)
{
    var results = new ConcurrentDictionary<string, string>();

    Parallel.ForEach(imagePaths, imagePath =>
    {
        // Each thread creates its own instance — no shared state, no locks
        var ocr = new IronTesseract();
        using var input = new OcrInput();
        input.LoadImage(imagePath);

        var result = ocr.Read(input);
        results[imagePath] = result.Text;
    });

    return results;
}
C#

The OmniPage version serializes all recognition through a lock, negating the parallelism. The IronOCR version processes documents concurrently with no coordination. For high-throughput batch workloads, see the multithreading example and the speed optimization guide.

Searchable PDF Generation from Scanned Archive

OmniPage's searchable PDF output requires assembling a recognition pipeline with explicit OutputSettings and OutputFormat configuration before saving. IronOCR produces searchable PDFs from a single method call on the result object:

Kofax OmniPage Approach:

// OmniPage: Searchable PDF requires OutputSettings configuration before save
public void ConvertArchiveToSearchable(string[] scannedPdfPaths, string outputDirectory)
{
    using var engine = new OmniPageEngine();
    engine.SetLicenseFile(licensePath);
    engine.Initialize();

    var recognitionSettings = new RecognitionSettings
    {
        Language = "English",
        AccuracyMode = "Maximum",
        PreserveLayout = true
    };

    var outputSettings = new OutputSettings
    {
        Format = OutputFormat.SearchablePDF,
        Compression = PDFCompression.Standard,
        ImageQuality = 85,
        EmbedFonts = true
    };

    foreach (var pdfPath in scannedPdfPaths)
    {
        var document = engine.OpenPDF(pdfPath);
        document.RecognizeAll(recognitionSettings);

        string outputPath = Path.Combine(
            outputDirectory,
            Path.GetFileNameWithoutExtension(pdfPath) + "_searchable.pdf");

        document.SaveAs(outputPath, outputSettings);
        document.Dispose();
    }

    engine.Shutdown();
}
C#

IronOCR Approach:

// IronOCR: Searchable PDF output is one method call on the result
public void ConvertArchiveToSearchable(string[] scannedPdfPaths, string outputDirectory)
{
    var ocr = new IronTesseract();

    foreach (var pdfPath in scannedPdfPaths)
    {
        using var input = new OcrInput();
        input.LoadPdf(pdfPath); // All pages loaded automatically

        var result = ocr.Read(input);

        string outputPath = Path.Combine(
            outputDirectory,
            Path.GetFileNameWithoutExtension(pdfPath) + "_searchable.pdf");

        result.SaveAsSearchablePdf(outputPath);
        Console.WriteLine($"Processed: {Path.GetFileName(pdfPath)} ({result.Pages.Length} pages)");
    }
}
C#

SaveAsSearchablePdf embeds a text layer into the PDF, making it indexable in document management systems without altering the visual appearance of the original scan. The searchable PDF guide covers text layer options and the PDF OCR example demonstrates end-to-end scanned PDF processing.

Kofax OmniPage API to IronOCR Mapping Reference

Kofax OmniPageIronOCR Equivalent
using Kofax.OmniPage.CSDK;using IronOcr;
using Kofax.OmniPageCSDK;using IronOcr;
using CSDK;using IronOcr;
new OmniPageEngine()Not required - no engine object
engine.SetLicenseFile(path)IronOcr.License.LicenseKey = "key";
engine.Initialize()Not required
engine.Shutdown()Not required
engine.CreateDocument()new OcrInput()
document.AddPage(imagePath)input.LoadImage(imagePath)
engine.OpenPDF(pdfPath)input.LoadPdf(pdfPath)
engine.OpenTiff(tiffPath)input.LoadImageFrames(tiffPath)
document.Recognize(settings)new IronTesseract().Read(input)
document.RecognizeAll(settings)new IronTesseract().Read(input) (all pages at once)
document.GetText()result.Text
document.GetZoneText(zoneName)input.LoadImage(path, cropRectangle) + result.Text
document.Dispose()using var input = new OcrInput() (automatic)
iterator.GetText()result.Pages[n].Words[m].Text
iterator.GetBoundingBox()result.Pages[n].Words[m].X / Y / Width / Height
iterator.GetConfidence()result.Pages[n].Words[m].Confidence
engine.LoadLanguageDictionary("German")dotnet add package IronOcr.Languages.German
settings.PrimaryLanguage = "English"ocr.Language = OcrLanguage.English;
settings.SecondaryLanguages = new[] {"German"}ocr.Language = OcrLanguage.English + OcrLanguage.German;
settings.DeskewImage = trueinput.Deskew();
settings.DespeckleLevel = 2input.DeNoise();
settings.ContrastEnhancement = trueinput.Contrast();
settings.AutoRotate = trueinput.Deskew(); (includes rotation correction)
document.SaveAs(path, outputSettings)result.SaveAsSearchablePdf(path)
OutputFormat.SearchablePDFresult.SaveAsSearchablePdf(path)
OutputFormat.XML (with coordinates)result.Pages / .Paragraphs / .Words object graph
FormZone with coordinate boundsnew CropRectangle(x, y, width, height)
Per-page license countingNot applicable
.lic file deploymentNot applicable
License server configurationNot applicable

Common Migration Issues and Solutions

Issue 1: License File Not Found Exceptions in Production

Kofax OmniPage: Every deployment requires the .lic file to exist at a specific path accessible to the application process. A deployment pipeline that does not explicitly copy the license file to the target server causes FileNotFoundException or LicenseException at engine initialization. Security teams often flag embedding .lic files in container images or committing them to source control.

Solution: IronOCR reads its license from a string. Store the key as an environment variable and read it at startup - no file to deploy, no path to configure:

// At application startup — reads IRONOCR_LICENSE_KEY from environment
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE_KEY")
    ?? throw new InvalidOperationException("IronOCR license key not configured.");
C#

In Docker, pass --env IRONOCR_LICENSE_KEY=YOUR-KEY. In Azure App Service, set it as an Application Setting. In Kubernetes, inject it via a Secret. No file mounts, no path configuration, no security review for embedded license files.

Issue 2: Floating License Seats Locked After Process Crash

Kofax OmniPage: When an application process crashes, is killed by a watchdog, or exits via Environment.FailFast, engine.Shutdown() does not execute. Floating license seats remain checked out until the license server's timeout expires - typically 30-60 minutes. In a containerized environment where pods restart frequently, this behavior depletes the license pool.

Solution: IronOCR has no concept of a checked-out license seat. A process crash releases no resources and locks no external system. The next process starts immediately with no waiting for seat availability:

// IronOCR: Process crash has no license implications whatsoever
// Start processing immediately after any failure
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var result = new IronTesseract().Read("document.jpg"); // No seat to check out
C#

For resilient ASP.NET Core services, see the async OCR guide for patterns that integrate cleanly with hosted services and graceful shutdown.

Issue 3: Docker Image Build Fails - Installer Cannot Run Non-Interactively

Kofax OmniPage: The OmniPage SDK installer is a GUI or semi-interactive installer that does not run cleanly in a docker build context. Teams attempting to bake the SDK into a container image encounter failures in the installer's license agreement or component selection steps. Workarounds (silent install switches, pre-extracted DLL copies) are undocumented and version-specific.

Solution: IronOCR's Dockerfile is three lines:

FROM mcr.microsoft.com/dotnet/aspnet:8.0
RUN apt-get update && apt-get install -y libgdiplus  # Single Linux dependency
COPY --from=build /app/publish /app
WORKDIR /app
ENTRYPOINT ["dotnet", "YourApp.dll"]
Text

libgdiplus is the only system dependency. The IronOCR NuGet package is restored by dotnet restore inside the build stage like any other package reference. The Docker deployment guide covers both Debian and Alpine base images, and the Linux deployment guide covers distribution-specific package names.

Issue 4: Reactivation Required After VM Migration or Cloud Autoscaling

Kofax OmniPage: OmniPage activation is tied to hardware identity. Cloud environments that migrate VMs between physical hosts, autoscale to new instances, or replace containers with fresh images trigger hardware identity changes that require reactivation. Contacting Tungsten support for reactivation mid-incident adds operational risk.

Solution: IronOCR's license key is hardware-independent. The same key works on any machine, any container, any cloud region, any number of autoscaled instances within the licensed tier. No reactivation, no support contact, no downtime:

// Identical startup code on any hardware topology
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
bool valid = IronOcr.License.IsLicensed; // Verify without a network call
C#

Issue 5: RecognitionSettings Object Has No IronOCR Equivalent

Kofax OmniPage: OmniPage uses a RecognitionSettings object (or PreprocessingSettings depending on SDK version) to configure engine behavior per document. Teams migrating expect a parallel configuration object in IronOCR.

Solution: IronOCR splits configuration across two surfaces: preprocessing operations on OcrInput and engine settings on IronTesseract. There is no settings object to instantiate:

// OmniPage settings object → IronOCR method calls on OcrInput
var ocr = new IronTesseract();
ocr.Language = OcrLanguage.English;              // RecognitionSettings.Language
// ocr.Configuration.TesseractVersion = ...     // Engine version already optimized

using var input = new OcrInput();
input.LoadImage(imagePath);
input.Deskew();                                  // settings.DeskewImage = true
input.DeNoise();                                 // settings.DespeckleLevel = 2
input.Contrast();                                // settings.ContrastEnhancement = true

var result = ocr.Read(input);
C#

The image quality correction guide lists all available preprocessing methods with guidance on which filters apply to which document quality profiles.

Issue 6: Zone Template Files Cannot Be Ported Directly

Kofax OmniPage: OmniPage form templates store zone definitions in proprietary .fdt or .fpf template files that define field positions, recognition types, and validation rules per document class. These files are not importable by IronOCR.

Solution: Extract the coordinate data from the template files (they are XML-based) and convert each zone to a CropRectangle. Field names become dictionary keys; zone coordinates map directly to (x, y, width, height) parameters:

// Convert OmniPage zone definition to IronOCR CropRectangle
// OmniPage zone: Name="TotalDue" X="490" Y="612" Width="180" Height="28"
// IronOCR equivalent:
var totalDueRegion = new CropRectangle(490, 612, 180, 28);

using var input = new OcrInput();
input.LoadImage(invoicePath, totalDueRegion);
string totalDue = new IronTesseract().Read(input).Text.Trim();
C#

For documents where zones vary per page, load the same image with different CropRectangle values per region rather than reloading the file. The region crop example demonstrates multiple region reads from a single image source.

Kofax OmniPage Migration Checklist

Pre-Migration

Identify all OmniPage integration points in the codebase:

# Find all OmniPage namespace references
grep -r "Kofax\|OmniPage\|CSDK" --include="*.cs" --include="*.csproj" .

# Find engine lifecycle calls
grep -r "Initialize\|Shutdown\|SetLicenseFile" --include="*.cs" .

# Find document and zone creation patterns
grep -r "CreateDocument\|AddPage\|FormZone\|RecognitionSettings\|PreprocessingSettings" --include="*.cs" .

# Find output format configuration
grep -r "OutputSettings\|OutputFormat\|SaveAs\|GetText" --include="*.cs" .

# Find license file path references
grep -r "\.lic\|license\.lic\|licensePath" --include="*.cs" --include="*.config" --include="*.json" .
SHELL

Inventory before starting:

  • Count files with OmniPage namespace imports
  • List all FormTemplate and FormZone definitions and extract their coordinate data
  • Identify which language dictionaries are loaded and map to IronOcr.Languages.* NuGet packages
  • Note which output formats are used (searchable PDF, plain text, XML) and their IronOCR equivalents
  • Locate all .lic file references in deployment scripts and configuration

Code Migration

  1. Remove OmniPage DLL references from all .csproj files
  2. Run dotnet add package IronOcr in each project that performs OCR
  3. Add language packs for each language in use: dotnet add package IronOcr.Languages.[Language]
  4. Add IronOcr.License.LicenseKey = ...; at each application entry point (Program.cs, Startup.cs, or service host)
  5. Replace all using Kofax.OmniPage.CSDK;, using CSDK;, and related namespace imports with using IronOcr;
  6. Remove all OmniPageEngine construction, SetLicenseFile, and Initialize calls
  7. Remove all engine.Shutdown() calls and the IDisposable implementations that exist solely to ensure shutdown
  8. Replace engine.CreateDocument() + document.AddPage() with new OcrInput() + input.LoadImage()
  9. Replace engine.OpenPDF() + per-page iteration with input.LoadPdf() (all pages in one call)
  10. Replace engine.OpenTiff() + per-frame loops with input.LoadImageFrames()
  11. Replace document.Recognize(settings) with new IronTesseract().Read(input)
  12. Convert FormZone coordinate data to CropRectangle(x, y, width, height) instances
  13. Replace document.GetZoneText() with per-region input.LoadImage(path, cropRectangle) + result.Text
  14. Replace document.SaveAs(path, outputSettings) for searchable PDF with result.SaveAsSearchablePdf(path)
  15. Replace result iterator patterns with result.Pages / .Paragraphs / .Words property traversal
  16. Remove PreprocessingSettings objects and replace boolean flags with explicit input.Deskew(), input.DeNoise(), input.Contrast() method calls
  17. Remove license file paths from deployment scripts, configuration files, and infrastructure-as-code templates

Post-Migration

  • Verify OCR accuracy on a representative sample of 100+ documents from the live corpus - compare against OmniPage output line-by-line for invoices, contracts, and forms
  • Confirm that CropRectangle-based zone extraction returns text matching the OmniPage GetZoneText() output for each mapped field
  • Test multi-page PDF processing: verify page count, page order, and text continuity
  • Test multi-frame TIFF processing: confirm all frames are processed and frame sequence is preserved
  • Verify searchable PDF output is indexable in the document management system used (SharePoint, OpenText, etc.)
  • Run parallel processing test with 50+ concurrent documents and confirm no thread safety issues
  • Test language pack coverage: load each previously used language dictionary via IronOcr.Languages.* and verify recognition quality
  • Confirm that process crashes and container restarts do not require any license recovery action
  • Run Docker build on CI agent - verify dotnet restore resolves IronOCR with no installer steps
  • Validate confidence scores are available per word and match the data quality expectations of any downstream validation workflow
  • Check that the application starts cleanly without the .lic file present in any path

Key Benefits of Migrating to IronOCR

Deployment complexity drops from weeks to minutes. A project that previously required SDK installer access, .lic file deployment, firewall configuration for the license server, and infrastructure team coordination now deploys via dotnet restore. A new developer clones the repository and runs the project. A new production server is provisioned by the CI/CD pipeline. Container images build without installer steps.

License risk disappears entirely. There are no floating seats to exhaust, no checkout timeouts to wait for, no hardware fingerprints to reactivate, and no .lic files to protect in deployment pipelines. An application crash at 3 AM releases nothing and locks nothing. The on-call engineer restarts the process; OCR resumes immediately. The IronOCR product page covers all licensing tiers.

Cross-platform deployment becomes a standard NuGet target. macOS development machines work without a platform exception. Linux production servers do not require a January 2026 SDK version. Docker containers build from a standard mcr.microsoft.com/dotnet/aspnet base image with one system dependency. The same IronOcr package reference in .csproj produces a working build on Windows, Linux, and macOS. See the Azure deployment guide and AWS deployment guide for cloud-specific configuration.

Parallel throughput scales with hardware. OmniPage's shared engine architecture requires locking that serializes concurrent recognition. IronOCR's stateless IronTesseract instances scale linearly with available CPU cores. Doubling the core count of a batch processing server doubles throughput without configuration changes or additional licensing.

Structured data access is immediate. OcrResult.Pages, Paragraphs, Lines, Words, and Characters expose the complete document structure as a navigable .NET object graph. Per-word confidence and coordinates are properties on each word object. There is no secondary export pipeline, no format configuration, and no file output required to access positional data.

Cost is fixed and predictable. OmniPage's combination of SDK license, annual maintenance, and per-page runtime fees creates a cost that scales with usage and recurs annually. IronOCR at $999-$2,399 perpetual is a one-time purchase. A 500,000-page-per-year workflow that was generating per-page charges recoups the IronOCR license cost within weeks. The IronOCR documentation hub and tutorials are available without a support contract.

Please note: Kofax OmniPage, OpenPDF, and Tesseract are registered trademarks of their respective owners. This site is not affiliated with, endorsed by, or sponsored by Google, Kofax, or LibrePDF. All product names, logos, and brands are property of their respective owners. Comparisons are for informational purposes only and reflect publicly available information at the time of writing.

Related Articles

Key in blue circle

Get your free 30-day Trial Key instantly.

Your trial license will be sent to your email address

No limitations. 100% unlocked. No credit card.

bullet_checkedNo credit card or account creation requiredNo limitations. 100% unlocked. No credit card.
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
Get Your No-Obligation Consult
Complete the form below or email sales@ironsoftware.com
Your details will always be kept confidential.
Trusted by Millions of Engineers Worldwide
Iron Software's customer logos
Get your free 30-day Trial Key instantly.
No credit card or account creation required