IRONSOFTWAREHOME
MIGRATION GUIDES

Migrating from Dynamsoft OCR to IronOCR

Kannaopat Udonpant
Kannapat Udonpant
Updated: August 1, 2026

This guide provides a complete migration path for .NET developers moving from Dynamsoft Label Recognizer to IronOCR. It covers NuGet package replacement, namespace updates, license initialization, and practical code migration examples for scenarios distinct from general capability comparisons - including template configuration elimination, runtime settings JSON removal, region definition migration, and result parsing simplification.

Why Migrate from Dynamsoft OCR

Dynamsoft Label Recognizer is a purpose-built specialist. That precision works well for narrow deployments but creates friction the moment application scope grows beyond the original MRZ or VIN use case.

Runtime Settings JSON Is a Maintenance Surface. Every Dynamsoft recognition workflow begins with AppendSettingsFromString, loading a JSON document that declares parameter arrays, character models, and region references. Those JSON templates are separate deployment artifacts - not compiled into your binary. They require version control, deployment pipeline management, and manual updates when Dynamsoft changes template schemas across SDK versions. IronOCR requires zero configuration files: instantiate IronTesseract, call .Read(), and the engine selects appropriate settings automatically.

Annual Subscription Pricing Compounds. Dynamsoft Label Recognizer licenses at $599+ per device per year. There is no perpetual option. A five-device processing cluster costs $2,995+ annually - and that budget covers only MRZ and structured label recognition. Add Dynamsoft Barcode Reader for barcodes or Dynamsoft Document Normalizer for edge correction, and the annual bill multiplies by product count. IronOCR's Lite license is $999 one-time and covers general OCR, structured labels, barcodes, native PDF, searchable PDF output, and 125+ languages from a single package.

Region Definition Requires JSON Templates. Defining a recognition region in Dynamsoft means authoring a ReferenceRegionArray JSON block, referencing it in a LabelRecognizerParameterArray, and loading the entire document before any image processing begins. IronOCR uses a single CropRectangle(x, y, width, height) constructor passed directly to OcrInput.LoadImage. Changing a region is one number edit, not a JSON document reparse.

Result Parsing Is Entirely Your Responsibility. RecognizeFile and RecognizeByFile return LineResult arrays containing raw text strings. Every structure you need - field offsets, date conversions, check digit validation, name separator handling - requires custom parsing code on top of that raw output. IronOCR returns an OcrResult with .Pages, .Lines, .Words, and .Characters as typed collections with bounding box coordinates, confidence scores, and font metadata already populated.

No Native PDF Support Creates a Hidden Dependency. Dynamsoft Label Recognizer has no PDF input capability. Any PDF that arrives at your processing pipeline requires an external library to render each page to a bitmap, a page iteration loop, and a result aggregation step before the first Dynamsoft call. IronOCR reads PDFs natively: new IronTesseract().Read("document.pdf") processes every page without a secondary dependency, a rendering loop, or a temporary image folder.

Multi-Product Initialization Blocks Grow With Scope. A Dynamsoft application that handles structured labels, barcodes, and document normalization carries three static InitLicense calls at startup, three disposal chains, and three independent SDK version dependencies. Upgrading the SDK means coordinating across all products. IronOCR has one initialization line and one package version regardless of which capabilities the application uses.

The Fundamental Problem

Dynamsoft requires a JSON configuration file loaded at runtime before recognition can start:

// Dynamsoft: JSON template required before any image processing
LabelRecognizer.InitLicense(licenseKey);
var recognizer = new LabelRecognizer();

string settings = @"{
    ""LabelRecognizerParameterArray"": [{
        ""Name"": ""VIN_Label"",
        ""ReferenceRegionNameArray"": [""VinRegion""],
        ""CharacterModelName"": ""VIN""
    }],
    ""ReferenceRegionArray"": [{
        ""Name"": ""VinRegion"",
        ""Localization"": {
            ""SourceType"": ""LST_MANUAL_SPECIFICATION"",
            ""FirstPoint"":  [5, 40],
            ""SecondPoint"": [95, 40],
            ""ThirdPoint"":  [95, 60],
            ""FourthPoint"": [5, 60]
        }
    }]
}";

recognizer.AppendSettingsFromString(settings);  // fails silently if JSON is malformed
var results = recognizer.RecognizeFile(imagePath);
C#
// IronOCR: no JSON, no template files — region is a constructor argument
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

var region = new CropRectangle(x: 50, y: 400, width: 900, height: 200);
using var input = new OcrInput();
input.LoadImage(imagePath, region);

var result = new IronTesseract().Read(input);
Console.WriteLine(result.Text);
C#

IronOCR vs Dynamsoft OCR: Feature Comparison

The table below covers the full capability gap between the two libraries.

FeatureDynamsoft Label RecognizerIronOCR
General document OCRNot supportedFull support
MRZ recognitionSpecialized (raw text output)Built-in with structured fields
VIN recognitionSpecialized (template required)Standard OCR with region targeting
Industrial label readingSpecialized (template required)Yes, via CropRectangle
Runtime settings configurationRequired (JSON via AppendSettingsFromString)Not required
Template deployment artifactsRequired (JSON files)None
Native PDF inputNot supportedYes
Password-protected PDFNot supportedYes
Multi-page TIFF inputManual page iterationNative (LoadImageFrames)
Searchable PDF outputNot supportedYes (SaveAsSearchablePdf)
Barcode readingSeparate product (Dynamsoft Barcode Reader)Built-in (ReadBarCodes = true)
Automatic preprocessingLimitedYes (Deskew, DeNoise, Contrast, Binarize, Sharpen, Dilate, Erode)
Structured output (Words, Lines, Paragraphs)Raw LineResult text stringsFully typed with coordinates and confidence
Language supportLimited (Latin MRZ)125+ languages, bundled as NuGet packages
Multi-language simultaneousNot supportedYes (OcrLanguage.French + OcrLanguage.German)
Confidence scoresPer-line onlyPer word, line, page
hOCR exportNot supportedYes
Licensing modelAnnual subscription ($599+/device/year)Perpetual ($999 one-time, Lite tier)
Multiple products requiredYes (3+ for full coverage)No (one package)
.NET Framework support.NET Framework 4.x+.NET Framework 4.6.2+, .NET 5/6/7/8/9
Cross-platform deploymentYesYes (Windows, Linux, macOS, Docker, Azure, AWS)
NuGet packageDynamsoft.LabelRecognizerIronOcr

Quick Start: Dynamsoft OCR to IronOCR Migration

Step 1: Replace NuGet Package

Remove the Dynamsoft package:

dotnet remove package Dynamsoft.LabelRecognizer
SHELL

Install IronOCR from the NuGet gallery:

dotnet add package IronOcr

Step 2: Update Namespaces

// Before (Dynamsoft)
using Dynamsoft.LabelRecognizer;
using Dynamsoft.Core;

// After (IronOCR)
using IronOcr;
C#

Step 3: Initialize License

Replace each Dynamsoft static InitLicense call with a single IronOCR license assignment at application startup:

// Before (Dynamsoft — one call per product)
LabelRecognizer.InitLicense("DYNAMSOFT-LICENSE-KEY");

// After (IronOCR — one line, all features)
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
C#

Code Migration Examples

Template-Based Recognition to Zero-Config Engine

Dynamsoft's JSON template system gives the SDK detailed instructions about character models, region specifications, and recognition parameters before any image is processed. For most real-world OCR workloads, that configuration adds setup complexity without recognition benefits, because the underlying Tesseract engine handles layout detection automatically.

Dynamsoft Approach:

using Dynamsoft.LabelRecognizer;
using Dynamsoft.Core;

// JSON template required before recognition
LabelRecognizer.InitLicense(licenseKey);
var recognizer = new LabelRecognizer();

string invoiceTemplate = @"{
    ""LabelRecognizerParameterArray"": [{
        ""Name"": ""Invoice_Header"",
        ""ReferenceRegionNameArray"": [""HeaderRegion""],
        ""CharacterModelName"": ""NumberLetter""
    }],
    ""ReferenceRegionArray"": [{
        ""Name"": ""HeaderRegion"",
        ""Localization"": {
            ""SourceType"": ""LST_MANUAL_SPECIFICATION"",
            ""FirstPoint"":  [0, 0],
            ""SecondPoint"": [100, 0],
            ""ThirdPoint"":  [100, 20],
            ""FourthPoint"": [0, 20]
        }
    }]
}";

recognizer.AppendSettingsFromString(invoiceTemplate);

var results = recognizer.RecognizeFile("invoice.jpg");
var headerText = new StringBuilder();
foreach (var result in results)
    foreach (var line in result.LineResults)
        headerText.AppendLine(line.Text);

Console.WriteLine(headerText.ToString());
recognizer.Dispose();
C#

IronOCR Approach:

using IronOcr;

// No template file — region specified inline, engine auto-configures
var region = new CropRectangle(x: 0, y: 0, width: 1200, height: 200);
using var input = new OcrInput();
input.LoadImage("invoice.jpg", region);
input.Deskew();

var result = new IronTesseract().Read(input);
Console.WriteLine(result.Text);
Console.WriteLine($"Confidence: {result.Confidence}%");
C#

The Dynamsoft approach requires authoring, validating, and deploying a JSON template before any image is processed. A typo in AppendSettingsFromString returns empty results at runtime - there is no compile-time validation. IronOCR's CropRectangle is a plain constructor: compile-time type checking, no external files, no deployment artifact. See the region-based OCR guide for all targeting patterns.

VIN Code Scanning With Region Migration

Vehicle identification number extraction is a Dynamsoft Label Recognizer specialty. Its VIN template model optimizes for the specific 17-character alphanumeric format. Migrating to IronOCR replaces the template model with a preprocessing pipeline and region targeting, which handles the same VIN plate conditions without requiring a character model configuration.

Dynamsoft Approach:

using Dynamsoft.LabelRecognizer;

LabelRecognizer.InitLicense(licenseKey);
var recognizer = new LabelRecognizer();

// VIN requires a specific character model and region configuration
string vinTemplate = @"{
    ""LabelRecognizerParameterArray"": [{
        ""Name"": ""VIN_Scan"",
        ""ReferenceRegionNameArray"": [""VIN_Zone""],
        ""CharacterModelName"": ""VIN""
    }],
    ""ReferenceRegionArray"": [{
        ""Name"": ""VIN_Zone"",
        ""Localization"": {
            ""SourceType"": ""LST_MANUAL_SPECIFICATION"",
            ""FirstPoint"":  [10, 35],
            ""SecondPoint"": [90, 35],
            ""ThirdPoint"":  [90, 65],
            ""FourthPoint"": [10, 65]
        }
    }]
}";
recognizer.AppendSettingsFromString(vinTemplate);

var results = recognizer.RecognizeFile("vehicle-vin.jpg");
string rawVin = results
    .SelectMany(r => r.LineResults)
    .Select(l => l.Text)
    .FirstOrDefault() ?? string.Empty;

Console.WriteLine($"Raw VIN text: {rawVin}");  // still requires validation
recognizer.Dispose();
C#

IronOCR Approach:

using IronOcr;
using System.Text.RegularExpressions;

// Target the VIN plate region directly — no template file
var vinRegion = new CropRectangle(x: 100, y: 350, width: 800, height: 300);

using var input = new OcrInput();
input.LoadImage("vehicle-vin.jpg", vinRegion);
input.Contrast();   // recover faded stamped digits
input.Sharpen();    // clarify character boundaries on embossed plates

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

// VIN: 17 chars, no I/O/Q
var vinMatch = Regex.Match(result.Text, @"\b[A-HJ-NPR-Z0-9]{17}\b");
string vin = vinMatch.Success ? vinMatch.Value : result.Text.Trim();

Console.WriteLine($"VIN: {vin}");
Console.WriteLine($"Confidence: {result.Confidence}%");
C#

CropRectangle coordinates use the same pixel reference frame as Dynamsoft's percentage-based FirstPoint/SecondPoint specification - convert by multiplying Dynamsoft's percentage values by your image dimensions. The preprocessing pipeline (Contrast, Sharpen) replaces the character model optimization Dynamsoft bakes into its VIN template. The image quality correction guide covers filter selection for embossed and low-contrast surfaces.

Multi-Page TIFF Batch Processing

Dynamsoft Label Recognizer processes single images. Multi-page TIFF documents - common in document management systems, medical imaging archives, and fax pipelines - require external iteration: load each frame, pass it through the recognizer individually, and aggregate results. IronOCR handles multi-frame TIFF natively through LoadImageFrames.

Dynamsoft Approach:

using Dynamsoft.LabelRecognizer;
// Requires an external TIFF library to extract frames

LabelRecognizer.InitLicense(licenseKey);
var recognizer = new LabelRecognizer();
recognizer.AppendSettingsFromString(genericTemplate);

// External library needed to iterate TIFF frames
var tiffImage = System.Drawing.Image.FromFile("scanned-batch.tiff");
int frameCount = tiffImage.GetFrameCount(
    System.Drawing.Imaging.FrameDimension.Page);

var allText = new StringBuilder();
for (int i = 0; i < frameCount; i++)
{
    tiffImage.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, i);
    string tempPath = $"frame_{i}.jpg";
    tiffImage.Save(tempPath, System.Drawing.Imaging.ImageFormat.Jpeg);

    var results = recognizer.RecognizeFile(tempPath);
    foreach (var r in results)
        foreach (var line in r.LineResults)
            allText.AppendLine(line.Text);

    System.IO.File.Delete(tempPath);  // clean up temp files
}

Console.WriteLine(allText.ToString());
recognizer.Dispose();
C#

IronOCR Approach:

using IronOcr;

// No frame iteration, no temp files, no external TIFF library
using var input = new OcrInput();
input.LoadImageFrames("scanned-batch.tiff");  // loads all frames natively
input.Deskew();
input.DeNoise();

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

// Results organized per page
foreach (var page in result.Pages)
{
    Console.WriteLine($"Frame {page.PageNumber}: {page.Lines.Count} lines");
    Console.WriteLine(page.Text);
}

// Save entire batch as a single searchable PDF
result.SaveAsSearchablePdf("batch-searchable.pdf");
C#

The Dynamsoft approach requires System.Drawing for frame extraction, a temporary file on disk per frame, and manual cleanup after each pass. IronOCR's LoadImageFrames reads all frames in a single call - no temp files, no frame index tracking. After OCR, SaveAsSearchablePdf archives the entire batch as a searchable document in one method call. The multi-frame TIFF guide and searchable PDF output guide cover both capabilities in detail.

Structured Word-Level Result Parsing

Dynamsoft RecognizeFile returns a DLRResult array. Each DLRResult contains a LineResults collection of DLRLineResult objects with a Text property and a Location property holding the bounding quadrilateral. Extracting word-level positions requires splitting the line text on whitespace and proportionally dividing the line bounding box - an approximation that breaks on proportional fonts. IronOCR surfaces word-level bounding boxes as typed properties on every OcrResult.Word object.

Dynamsoft Approach:

using Dynamsoft.LabelRecognizer;

LabelRecognizer.InitLicense(licenseKey);
var recognizer = new LabelRecognizer();
recognizer.AppendSettingsFromString(settingsJson);

var results = recognizer.RecognizeFile("form-scan.jpg");

foreach (var dlrResult in results)
{
    foreach (var lineResult in dlrResult.LineResults)
    {
        // Line-level data only — word boundaries are not provided
        Console.WriteLine($"Text: {lineResult.Text}");
        Console.WriteLine($"Confidence: {lineResult.Confidence}");

        // Location is a quadrilateral — four corner points
        var loc = lineResult.Location;
        Console.WriteLine($"Top-left: ({loc.Points[0].X}, {loc.Points[0].Y})");

        // To get word positions: split text and divide bounding box manually
        var words = lineResult.Text.Split(' ');
        int approxWidth = (loc.Points[1].X - loc.Points[0].X) / words.Length;
        for (int i = 0; i < words.Length; i++)
        {
            int wordX = loc.Points[0].X + (i * approxWidth);
            Console.WriteLine($"  Word '{words[i]}' approx at x={wordX}");
        }
    }
}
recognizer.Dispose();
C#

IronOCR Approach:

using IronOcr;

var result = new IronTesseract().Read("form-scan.jpg");

// Word-level positions are first-class properties — no manual division
foreach (var page in result.Pages)
{
    foreach (var paragraph in page.Paragraphs)
    {
        Console.WriteLine($"Paragraph at ({paragraph.X}, {paragraph.Y}): {paragraph.Text}");

        foreach (var line in paragraph.Lines)
        {
            foreach (var word in line.Words)
            {
                Console.WriteLine(
                    $"  Word: '{word.Text}' " +
                    $"at ({word.X},{word.Y}) " +
                    $"size {word.Width}x{word.Height} " +
                    $"confidence {word.Confidence}%");
            }
        }
    }
}
C#

IronOCR provides a true hierarchy: pages contain paragraphs, paragraphs contain lines, lines contain words, words contain characters. Every level exposes .X, .Y, .Width, .Height, and .Confidence as typed integer and double properties - no quadrilateral coordinate arithmetic required. The structured results guide documents every accessible property, and the confidence scoring guide explains confidence thresholding for automated document review pipelines.

Async Parallel Processing for High-Volume Label Scanning

Dynamsoft Label Recognizer is thread-safe, but its RecognizeFile call is synchronous. Wrapping it in Task.Run produces parallel processing, but each call shares configuration state through AppendSettingsFromString - loading templates on multiple threads requires careful initialization sequencing. IronOCR's IronTesseract instances are independent: create one per task, call Read, and the thread model is straightforward.

Dynamsoft Approach:

using Dynamsoft.LabelRecognizer;
using System.Threading.Tasks;

// InitLicense must be called once before parallel work begins
LabelRecognizer.InitLicense(licenseKey);

// Each thread needs its own recognizer instance with its own template load
var results = new System.Collections.Concurrent.ConcurrentBag<string>();

await Task.WhenAll(imagePaths.Select(async path =>
{
    // Cannot share recognizer instances safely across tasks
    var recognizer = new LabelRecognizer();
    recognizer.AppendSettingsFromString(templateJson);  // reload JSON per instance

    await Task.Run(() =>
    {
        var dlrResults = recognizer.RecognizeFile(path);
        var text = string.Join("\n",
            dlrResults.SelectMany(r => r.LineResults).Select(l => l.Text));
        results.Add(text);
    });

    recognizer.Dispose();
}));

Console.WriteLine($"Processed {results.Count} images");
C#

IronOCR Approach:

using IronOcr;
using System.Collections.Concurrent;
using System.Threading.Tasks;

var extractedTexts = new ConcurrentDictionary<string, string>();

// Each IronTesseract instance is independent — no shared state
Parallel.ForEach(imagePaths, imagePath =>
{
    var ocr = new IronTesseract();
    var result = ocr.Read(imagePath);
    extractedTexts[imagePath] = result.Text;
});

foreach (var (path, text) in extractedTexts)
    Console.WriteLine($"{System.IO.Path.GetFileName(path)}: {text.Length} characters");
C#

IronOCR requires no initialization sequencing before parallel work begins. One IronOcr.License.LicenseKey assignment at application startup activates all instances. No template reload per thread, no JSON validation per instance. For non-blocking server-side scenarios, the async OCR guide covers await-based patterns for ASP.NET Core and Azure Functions.

Searchable PDF Output From Scanned Label Archives

Dynamsoft has no PDF output capability of any kind. Scanned label archives processed through Dynamsoft remain as image-only files - unsearchable, not indexable by document management systems, and not compliant with PDF/A archival standards. IronOCR adds searchable PDF output as a single method call on the OcrResult object.

Dynamsoft Approach:

using Dynamsoft.LabelRecognizer;

// Process scanned label — extract text into a string
LabelRecognizer.InitLicense(licenseKey);
var recognizer = new LabelRecognizer();
recognizer.AppendSettingsFromString(labelTemplate);

var results = recognizer.RecognizeFile("scanned-labels.jpg");
var extractedText = new StringBuilder();
foreach (var r in results)
    foreach (var line in r.LineResults)
        extractedText.AppendLine(line.Text);

// Cannot create a searchable PDF — save text to a sidecar .txt file instead
System.IO.File.WriteAllText("scanned-labels.txt", extractedText.ToString());

// The original image remains unsearchable
Console.WriteLine("No PDF output available in Dynamsoft Label Recognizer.");
recognizer.Dispose();
C#

IronOCR Approach:

using IronOcr;

// Read, preprocess, and produce a searchable PDF archive in one pipeline
using var input = new OcrInput();
input.LoadImage("scanned-labels.jpg");
input.Deskew();
input.Contrast();

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

// Searchable PDF: original image layer preserved, invisible text layer added
result.SaveAsSearchablePdf("scanned-labels-searchable.pdf");

Console.WriteLine($"Searchable PDF created. Confidence: {result.Confidence}%");
Console.WriteLine($"Extracted text preview: {result.Text.Substring(0, 100)}");
C#

The searchable PDF output preserves the original scanned image at full resolution and adds an invisible OCR text layer on top. Document management systems, search indexes, and PDF viewers can now search the label content. The searchable PDF how-to and the scanned document processing guide cover multi-page archives and batch conversion workflows.

Dynamsoft OCR API to IronOCR Mapping Reference

Dynamsoft Label RecognizerIronOCR Equivalent
LabelRecognizer.InitLicense(key)IronOcr.License.LicenseKey = key
new LabelRecognizer()new IronTesseract()
recognizer.AppendSettingsFromString(json)Not required - auto-configured
recognizer.RecognizeFile(path)ocr.Read(path)
recognizer.RecognizeByFile(path, templateName)ocr.Read(path)
recognizer.RecognizeBuffer(buffer, width, height, ...)input.LoadImage(imageBytes) then ocr.Read(input)
DLRResult[] (array of results)OcrResult (single result object)
DLRResult.LineResultsOcrResult.Lines
DLRLineResult.TextOcrResult.Line.Text
DLRLineResult.ConfidenceOcrResult.Line.Words[i].Confidence
DLRLineResult.Location.Points[i]OcrResult.Line.X, .Y, .Width, .Height
ReferenceRegionArray (JSON)new CropRectangle(x, y, w, h)
LabelRecognizerParameterArray (JSON)Not required
CharacterModelName in templateNot required
recognizer.Dispose()using var ocr = new IronTesseract()
No PDF input supportinput.LoadPdf(path)
No searchable PDF outputresult.SaveAsSearchablePdf(path)
No multi-page TIFF inputinput.LoadImageFrames(path)
Barcode reading (separate product)ocr.Configuration.ReadBarCodes = true
Multiple InitLicense calls (per product)Single IronOcr.License.LicenseKey assignment

Common Migration Issues and Solutions

Issue 1: AppendSettingsFromString Returns Empty Results After Migration

Dynamsoft: Recognition silently returns empty DLRResult arrays when AppendSettingsFromString receives a malformed JSON string. No exception is thrown. Teams migrating from Dynamsoft sometimes add defensive null-checks throughout their result parsing code to guard against this silent failure.

Solution: Remove AppendSettingsFromString entirely. IronOCR requires no template configuration. If specific region targeting is needed, replace the ReferenceRegionArray JSON with a CropRectangle:

// Remove all AppendSettingsFromString calls
// Replace region JSON with a CropRectangle constructor
var region = new CropRectangle(x: 0, y: 400, width: 1200, height: 300);
using var input = new OcrInput();
input.LoadImage(imagePath, region);
var result = new IronTesseract().Read(input);
C#

The IronTesseract setup guide documents all engine configuration options that can be set as properties rather than JSON strings.

Issue 2: Multiple InitLicense Calls at Application Startup

Dynamsoft: An application using Label Recognizer, Barcode Reader, and Document Normalizer calls three separate InitLicense methods at startup, each requiring its own license key. Teams store three environment variables, rotate three keys independently, and debug three separate initialization failures.

Solution: Remove all Dynamsoft InitLicense calls. Replace with one IronOCR line:

// Remove:
// LabelRecognizer.InitLicense(mrzKey);
// BarcodeReader.InitLicense(barcodeKey);
// DocumentNormalizer.InitLicense(docKey);

// Add once, at application startup:
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
C#

One environment variable activates all IronOCR capabilities - OCR, barcodes, PDF processing, and all 125+ languages - with no per-feature initialization required.

Issue 3: LineResult Text Aggregation Produces Garbled Output

Dynamsoft: RecognizeFile returns one DLRResult per detected label region. Applications that concatenate lineResult.Text across all results with \n separators produce output that mixes lines from different label zones on the page - because the order of DLRResult objects is region-detection order, not reading order.

Solution: IronOCR's result hierarchy organizes output in reading order. Use the PagesParagraphsLines structure to access text in natural document order:

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

// Reading-order text — no manual aggregation
Console.WriteLine(result.Text);

// Or access paragraph-level groupings
foreach (var paragraph in result.Pages[0].Paragraphs)
    Console.WriteLine(paragraph.Text);
C#

Issue 4: Template JSON Files Missing on Deployment Server

Dynamsoft: Template JSON files are separate deployment artifacts. When a template file is missing or has an incorrect path on a new server, AppendSettingsFromString fails - sometimes silently, sometimes with a runtime exception - and the deployment breaks recognition without touching application code.

Solution: IronOCR has no template files. After replacing the NuGet package and updating namespaces, the deployment artifact list shrinks to the application binaries and one environment variable. Add a startup validation check if needed:

// Validate license at startup — no template files to check
if (!IronOcr.License.IsValidLicense)
    throw new InvalidOperationException("IronOCR license key is invalid or missing.");

var ocr = new IronTesseract();
// Ready to process — no file dependencies
C#

Issue 5: Disposal Chain Management Across Multiple Products

Dynamsoft: Each Dynamsoft product instance (LabelRecognizer, BarcodeReader, DocumentNormalizer) implements IDisposable. Service classes that aggregate multiple products carry multi-level Dispose implementations, and missing a Dispose call on any product instance causes native resource leaks that manifest as memory growth under load.

Solution: IronOCR's IronTesseract and OcrInput both implement IDisposable, but the disposal model is simpler - one class, one pattern. Register a single IronTesseract instance in the DI container as a singleton, or use using blocks for short-lived instances:

// Short-lived pattern
using var input = new OcrInput();
input.LoadImage(imagePath);
var result = new IronTesseract().Read(input);

// Long-lived singleton (register in Program.cs)
builder.Services.AddSingleton<IronTesseract>();
C#

The progress tracking guide covers lifetime management for long-running batch jobs, and the async OCR guide shows singleton patterns in ASP.NET Core.

Issue 6: Character Model Not Available for Custom Label Format

Dynamsoft: The CharacterModelName field in a template references a model file that must exist in the Dynamsoft SDK installation directory. Custom character models require downloading additional model files from Dynamsoft's portal and placing them in the correct SDK path. A missing model causes recognition to fail with a cryptic runtime error.

Solution: IronOCR does not use character model files. For custom or specialized fonts, use custom language training:

// No character model files needed
// For specialized fonts, use a custom language pack
var ocr = new IronTesseract();
ocr.Language = OcrLanguage.English;  // or load a custom trained pack

using var input = new OcrInput();
input.LoadImage(specializedFontImage);
input.Binarize();  // helps with specialized font clarity

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

The custom font training guide covers training a custom language pack for proprietary label fonts without any file path configuration.

Dynamsoft OCR Migration Checklist

Pre-Migration

Audit the codebase for all Dynamsoft references:

# Find all Dynamsoft using statements
grep -r "using Dynamsoft" --include="*.cs" .

# Find InitLicense calls (one per product)
grep -r "InitLicense" --include="*.cs" .

# Find AppendSettingsFromString calls (template loads)
grep -r "AppendSettingsFromString" --include="*.cs" .

# Find template JSON strings (inline or file references)
grep -r "LabelRecognizerParameterArray\|ReferenceRegionArray\|CharacterModelName" --include="*.cs" .

# Find RecognizeFile and RecognizeByFile calls
grep -r "RecognizeFile\|RecognizeByFile\|RecognizeBuffer" --include="*.cs" .

# Find LineResult result parsing patterns
grep -r "LineResults\|DLRResult\|DLRLineResult" --include="*.cs" .

# Identify any JSON template files in the project
find . -name "*.json" | xargs grep -l "LabelRecognizerParameterArray" 2>/dev/null
SHELL

Inventory findings:

  • Count InitLicense call sites (one per Dynamsoft product in use)
  • Count AppendSettingsFromString call sites (one per recognition template)
  • List all JSON template files that will be deleted after migration
  • Identify any ReferenceRegionArray definitions (convert to CropRectangle)
  • Note which features are covered by separate products (barcodes, document normalization)

Code Migration

  1. Remove Dynamsoft.LabelRecognizer NuGet package (and any other Dynamsoft packages)
  2. Install IronOcr NuGet package (dotnet add package IronOcr)
  3. Replace all using Dynamsoft.LabelRecognizer; and using Dynamsoft.Core; with using IronOcr;
  4. Replace all LabelRecognizer.InitLicense(key) calls with a single IronOcr.License.LicenseKey = key at application startup
  5. Remove all AppendSettingsFromString(json) calls - no equivalent required
  6. Replace ReferenceRegionArray JSON coordinates with new CropRectangle(x, y, width, height) constructors
  7. Replace new LabelRecognizer() instantiation with new IronTesseract()
  8. Replace recognizer.RecognizeFile(path) with ocr.Read(path)
  9. Replace DLRResult/DLRLineResult result iteration with OcrResult.Pages/.Lines/.Words hierarchy
  10. Replace manual lineResult.Text string aggregation with result.Text or structured page enumeration
  11. Replace BarcodeReader.InitLicense + BarcodeReader.DecodeFile with ocr.Configuration.ReadBarCodes = true
  12. Remove multi-product Dispose chains and replace with using var ocr = new IronTesseract()
  13. Delete JSON template files from the project and deployment artifacts
  14. Replace frame iteration loops over TIFF files with input.LoadImageFrames(path)
  15. Add result.SaveAsSearchablePdf(outputPath) wherever scanned outputs need to be archived

Post-Migration

  • Verify IronOcr.License.IsValidLicense returns true at application startup
  • Confirm all recognition results return non-empty result.Text for previously working inputs
  • Check result.Confidence on representative samples - values above 80% indicate good recognition quality
  • Test region-targeting accuracy by comparing CropRectangle outputs against previous Dynamsoft region results
  • Validate barcode reading by running ocr.Configuration.ReadBarCodes = true on inputs that previously required Dynamsoft Barcode Reader
  • Verify multi-page TIFF processing produces one OcrResult.Page per frame
  • Confirm searchable PDF output is text-searchable in a PDF viewer
  • Run parallel processing tests with Parallel.ForEach and verify no thread contention
  • Test all deployment targets (Linux, Docker, Azure) to confirm single-package deployment works without JSON template files
  • Confirm no Dynamsoft license key environment variables remain in deployment configuration

Key Benefits of Migrating to IronOCR

One Package Eliminates the Multi-Product Coordination Tax. Every capability - general OCR, MRZ extraction, barcode reading, native PDF input, searchable PDF output, preprocessing, and 125+ languages - ships as a single IronOcr NuGet package. Version upgrades affect one package entry in one .csproj file. License key rotation is one environment variable. The deployment artifact inventory shrinks to application binaries, no JSON template files, no character model directories.

Zero Configuration File Dependencies. The Dynamsoft template system requires JSON files to be present and correctly pathed at runtime. IronOCR has no runtime file dependencies beyond the NuGet package itself. Docker images become deterministic: what passes CI is exactly what runs in production. The Docker deployment guide shows a complete Dockerfile requiring only one apt-get install line for Linux.

Structured Output Reduces Integration Code. Dynamsoft returns raw LineResult text strings. Structured data extraction - field positions, word boundaries, confidence per token - requires post-processing your code owns and tests. IronOCR's result hierarchy exposes pages, paragraphs, lines, words, and characters as typed collections with coordinates and confidence scores at every level. Teams migrating from Dynamsoft typically remove 30-50% of their result-processing code because IronOCR delivers the structure they were building by hand. The OCR results feature page documents the complete output model.

Perpetual Licensing Removes Annual Budget Uncertainty. Dynamsoft Label Recognizer has no perpetual option. A processing cluster running for five years costs $2,995+ per year for label recognition alone, before adding barcode or document normalization products. IronOCR's $999 Lite license is a one-time purchase that covers all features indefinitely. For government, enterprise, and long-lived production deployments, removing annual renewal dependencies from a core document processing component reduces procurement complexity and eliminates the risk of a mid-project subscription lapse. The IronOCR licensing page lists all tiers and what each covers.

Cross-Platform Without Platform-Specific Configuration. IronOCR resolves the correct runtime binary for Windows x64, Linux x64, macOS x64, and macOS ARM through NuGet's runtime identifier graph. No conditional <PackageReference> blocks, no platform detection code, no native binary path setup. The same using IronOcr; code compiles and runs on Windows, Linux, AWS Lambda, and Azure App Service without modification.

Language Coverage Scales With Application Needs. Dynamsoft Label Recognizer is engineered for Latin-character MRZ formats. Non-Latin scripts - Arabic, Chinese, Japanese, Korean, Hebrew - fall outside its design scope. IronOCR supports 125+ languages installed as individual NuGet packages: dotnet add package IronOcr.Languages.Arabic adds Arabic support with no code change in the recognition pipeline. The languages index lists every available language pack. For applications processing international identity documents, multilingual shipping labels, or cross-border invoices, this breadth means one library covers every document type a growing application encounters.

Please note: Dynamsoft and Tesseract are registered trademarks of their respective owners. This site is not affiliated with, endorsed by, or sponsored by Dynamsoft or Google. 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