Zum Fußzeileninhalt springen
VIDEOS

Umstellung von Asprise OCR auf IronOCR

Dieser Leitfaden führt .NET -Entwickler Schritt für Schritt durch den Austausch von Asprise OCRdurch IronOCR . Es behandelt den mechanischen Pakettausch, Namensraumänderungen und die vier Code-Migrationsmuster, die den Großteil der Asprise-Nutzung in produktiven .NET Anwendungen ausmachen. Die Zielgruppe sind Entwickler, die sich bereits für eine Migration entschieden haben und einen konkreten Aktionsplan benötigen.

Warum von Asprise OCRmigrieren?

Asprise OCR wurde ursprünglich als Java-Produkt konzipiert. Die .NET Oberfläche ist ein Wrapper um eine native Java-Engine, und diese Herkunft prägt jeden Aspekt des Verhaltens der Bibliothek in .NET – von der Bereitstellung über das API-Design bis hin zu Lizenzbeschränkungen.

JRE und native Binärabhängigkeit. Asprise OCRfor .NET erfordert plattformspezifische native Binärdateien (aocr.dll, aocr_x64.dll, libaocr.so, libaocr.dylib), die auf jedem Rechner vorhanden sein müssen, auf dem die Anwendung ausgeführt wird. Jede Binärdatei muss exakt mit der Zielplattform und der Prozessarchitektur übereinstimmen. Ein 64-Bit-Docker-Container, der mit der 32-Bit-DLL erstellt wurde, löst zur Laufzeit BadImageFormatException aus. Eine Linux-Bereitstellung, der libaocr.so von LD_LIBRARY_PATH fehlt, löst DllNotFoundException aus. Keiner der Fehler tritt während des Build-Prozesses auf. Jedes neue Bereitstellungsziel – ein neuer Server, ein neues Container-Image, ein CI-Agent – ​​erfordert ein manuelles Einlesen der Binärdateien.

String-Konstanten-API aus dem Java-Erbe. Asprise stellt ganzzahlige Konstanten für Erkennungstyp und Ausgabeformat bereit: Ocr.RECOGNIZE_TYPE_TEXT, Ocr.OUTPUT_FORMAT_PLAINTEXT, Ocr.OUTPUT_FORMAT_XML. Diese Konstanten sind direkt der ganzzahlbasierten API des Java SDK zugeordnet. .NET Entwickler erhalten keine IntelliSense-Hilfe zu gültigen Konstantenwerten, keine Kompilierzeitsicherheit bei Argumentkombinationen und keine stark typisierten Ergebnisobjekte. Um strukturierte Ausgaben zu extrahieren, müssen XML-Zeichenketten manuell analysiert werden.

Keine Unterstützung für asynchrone Synchronisierung ohne Workarounds. Asprise bietet keine native asynchrone API. Das Umhüllen synchroner Asprise-Aufrufe in Task.Run, um ASP.NET-Threads nicht zu blockieren, erzeugt Druck auf den Threadpool und löst nicht die Lizenzbeschränkung, die gleichzeitig Ausführung auf LITE und STANDARD Stufen verbietet. Asynchrone Muster in modernen .NET Anwendungen – Hintergrunddienste, minimale API-Endpunkte, Azure Functions – haben kein sauberes Asprise-Äquivalent.

Die Verarbeitung von TIFF-Dateien mit mehreren Einzelbildern erfordert eine manuelle Aufteilung. Asprise arbeitet mit einzelnen Bilddateien. Die Verarbeitung einer mehrseitigen TIFF-Datei erfordert externen Code, der die Einzelbilder in einzelne Dateien aufteilt und diese anschließend in einer Schleife verarbeitet. Metadaten der Einzelbilder und Seitennummern werden nicht in die Ausgabedatei übernommen.

Thread-Beschränkung verhindert Produktionsbereitstellung. Lite Lizenzen (~299 $) und STANDARD-Lizenzen (~699 $) beschränken die Ausführung vertraglich auf einen einzelnen Thread und einen einzelnen Prozess. ASP.NET Core verarbeitet alle HTTP-Anfragen in einem Threadpool. Jeder Web-API-Endpunkt, der Asprise in diesen Tarifen aufruft, stellt ab der ersten gleichzeitigen Anfrage einen Lizenzverstoß dar. Ein Upgrade auf Enterprise hebt diese Einschränkung auf, erfordert jedoch die Kontaktaufnahme mit dem Vertrieb. Der Preis hierfür ist nicht öffentlich bekannt – Schätzungen liegen je nach Implementierungsumfang zwischen 2.000 und über 5.000 US-Dollar.

Handling des Ausgabeformats erfordert String-Parsing. Wenn OUTPUT_FORMAT_XML angegeben ist, gibt Asprise einen rohen XML-String zurück. Die Anwendung ist dafür verantwortlich, diese Zeichenkette zu deserialisieren, ihre Struktur zu validieren und Wörter sowie deren Koordinaten zu extrahieren. Die Konfidenzwerte pro Wort sind in XML-Attributen eingebettet. Es gibt kein Objektmodell – nur Stringmanipulation.

Das grundsätzliche Problem

Asprise benötigt eine JRE-nahe native Binärkonfiguration, bevor der erste OCR-Aufruf ausgeführt werden kann.IronOCR benötigt außer einem NuGet Paket nichts weiter:

// Asprise: native binary must exist in PATH or application directory
// aocr_x64.dll missing → DllNotFoundException at runtime, not at build
Ocr.SetUp();                              // Static init — touches native binary
Ocr ocr = new Ocr();
ocr.StartEngine("eng", Ocr.SPEED_FAST);  // Allocates native engine memory
string text = ocr.Recognize(imagePath, Ocr.RECOGNIZE_TYPE_TEXT, Ocr.OUTPUT_FORMAT_PLAINTEXT);
ocr.StopEngine();                         // Must call or native memory leaks
// Asprise: native binary must exist in PATH or application directory
// aocr_x64.dll missing → DllNotFoundException at runtime, not at build
Ocr.SetUp();                              // Static init — touches native binary
Ocr ocr = new Ocr();
ocr.StartEngine("eng", Ocr.SPEED_FAST);  // Allocates native engine memory
string text = ocr.Recognize(imagePath, Ocr.RECOGNIZE_TYPE_TEXT, Ocr.OUTPUT_FORMAT_PLAINTEXT);
ocr.StopEngine();                         // Must call or native memory leaks
' Asprise: native binary must exist in PATH or application directory
' aocr_x64.dll missing → DllNotFoundException at runtime, not at build
Ocr.SetUp()                              ' Static init — touches native binary
Dim ocr As New Ocr()
ocr.StartEngine("eng", Ocr.SPEED_FAST)   ' Allocates native engine memory
Dim text As String = ocr.Recognize(imagePath, Ocr.RECOGNIZE_TYPE_TEXT, Ocr.OUTPUT_FORMAT_PLAINTEXT)
ocr.StopEngine()                         ' Must call or native memory leaks
$vbLabelText   $csharpLabel
// IronOCR: dotnet add package IronOcr — no binary sourcing, no lifecycle calls
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
string text = new IronTesseract().Read(imagePath).Text;
// IronOCR: dotnet add package IronOcr — no binary sourcing, no lifecycle calls
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
string text = new IronTesseract().Read(imagePath).Text;
' IronOCR: dotnet add package IronOcr — no binary sourcing, no lifecycle calls
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim text As String = New IronTesseract().Read(imagePath).Text
$vbLabelText   $csharpLabel

IronOCR vs. Asprise OCR: Funktionsvergleich

Die folgende Tabelle beschreibt die Funktionen, die für Entwickler bei der Bewertung dieser Migration am relevantesten sind.

Feature Asprise OCR IronOCR
Primäre Plattform Java (Legacy) .NET Native
NuGet -Installation Wrapper + plattformnative DLLs Einzelpaket (IronOcr)
Native Binärdatei zur Laufzeit erforderlich Ja (plattformspezifische DLL) Nein
.NET API-Stil Ganzzahlkonstanten, Zeichenkettenrückgaben Stark typisierte Klassen und Aufzählungen
IDisposable / using Muster Nicht implementiert Ja (OcrInput)
Asynchrone OCR Keine native Unterstützung Ja (ReadAsync)
Multithreading — Lite/STANDARD Stufe Durch die Lizenz untersagt Zulässig
Multithreading – alle Ebenen Enterprise only Alle Stufen
ASP.NET Core Web-API-Unterstützung Enterprise erforderlich Jede Stufe
Azure Functions / AWS Lambda Enterprise erforderlich Jede Stufe
Native PDF-Eingabe Nein Ja
Mehrbild-TIFF-Eingabe Nein (manuelle Rahmenteilung) Ja (LoadImageFrames)
Byte-Array- und Stream-Eingabe Beschränkt Ja
Integrierte Bildvorverarbeitung Nein Ja (9+ Filter)
Durchsuchbare PDF-Ausgabe Nein Ja (SaveAsSearchablePdf)
Strukturiertes Ergebnisobjektmodell Nein (nur XML-Zeichenfolge) Ja (Seiten, Absätze, Wörter, Zeichen)
Vertrauenswerte pro Wort Nein (XML-Attributanalyse) Ja (result.Confidence)
Wortpixelkoordinaten XML-Attributanalyse Stark typisierte Eigenschaften
Wortanzahl 20+ 125+
Auswahl stark typisierter Sprachen Keine (String-Codes) Ja (OcrLanguage Aufzählung)
Barcode-Lesung Ja (separater Erkennungstyp) Ja (Konfigurationsflag)
hOCR-Export Nein Ja
Plattformübergreifende Bereitstellung Manuelle Binärdatei pro Plattform NuGet unterstützt alle Plattformen.
Docker / Linux / macOS Manuelle LD_LIBRARY_PATH Konfiguration Funktioniert out of the box
.NET -Kompatibilität Eingeschränkt (Java-Brücke) .NET Framework 4.6.2+, .NET 5-9
Eintrittspreis für die Servernutzung Enterprise (ca. 2000 $ +) $999 (Lite, alle Funktionen)
Lizenztyp Für jedes Tarifpaket wenden Sie sich bitte an den Vertrieb für Enterprise. Dauerlizenz (einmaliger Kauf)

Schnellstart: Migration von Asprise OCRzu IronOCR

Schritt 1: Ersetzen des NuGet-Pakets

Asprise OCR entfernen:

dotnet remove package asprise-ocr-api
dotnet remove package asprise-ocr-api
SHELL

Installieren Sie IronOCR von der NuGet Paketseite :

dotnet add package IronOcr

Schritt 2: Namespaces aktualisieren

Ersetzen Sie die Asprise Namespaces durch den IronOCR-Namespace:

// Before (Asprise)
using asprise.ocr;

// After (IronOCR)
using IronOcr;
// Before (Asprise)
using asprise.ocr;

// After (IronOCR)
using IronOcr;
Imports IronOcr
$vbLabelText   $csharpLabel

Schritt 3: Lizenz initialisieren

Fügen Sie die Lizenzschlüsselzuordnung beim Anwendungsstart hinzu - in Program.cs vor jedem OCR-Aufruf, in Startup.Configure oder in einem statischen Konstruktor:

IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
$vbLabelText   $csharpLabel

Auf der IronOCR -Lizenzseite ist ein kostenloser Testschlüssel erhältlich. Während der Entwicklungs- und Evaluierungsphase läuft IronOCR ohne Schlüssel und versieht die Ausgabe mit einem Testwasserzeichen.

Beispiele für die Code-Migration

Entfernung der JRE-Pfadkonfiguration und der Engine-Initialisierung

Asprise-Anwendungen, die unter Linux oder macOS laufen, enthalten typischerweise Startcode, der den JRE-Pfad festlegt oder das Vorhandensein nativer Binärdateien überprüft, bevor die OCR-Arbeit beginnt. Diese Infrastruktur hat in IronOCR kein Äquivalent.

Asprise OCR-Ansatz:

// AppStartup.cs — native binary validation before accepting any requests
public static void InitializeOcr()
{
    // Validate native library is reachable before first use
    string nativePath = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
        ? Path.Combine(AppContext.BaseDirectory, "aocr_x64.dll")
        : RuntimeInformation.IsOSPlatform(OSPlatform.Linux)
            ? "/usr/lib/libaocr.so"
            : "/usr/local/lib/libaocr.dylib";

    if (!File.Exists(nativePath))
        throw new FileNotFoundException(
            $"Asprise native binary not found: {nativePath}. " +
            "Deploy the correct platform binary before starting.");

    // Static global init — must run before any Ocr instance is created
    Ocr.SetUp();
}
// AppStartup.cs — native binary validation before accepting any requests
public static void InitializeOcr()
{
    // Validate native library is reachable before first use
    string nativePath = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
        ? Path.Combine(AppContext.BaseDirectory, "aocr_x64.dll")
        : RuntimeInformation.IsOSPlatform(OSPlatform.Linux)
            ? "/usr/lib/libaocr.so"
            : "/usr/local/lib/libaocr.dylib";

    if (!File.Exists(nativePath))
        throw new FileNotFoundException(
            $"Asprise native binary not found: {nativePath}. " +
            "Deploy the correct platform binary before starting.");

    // Static global init — must run before any Ocr instance is created
    Ocr.SetUp();
}
Imports System
Imports System.IO
Imports System.Runtime.InteropServices

' AppStartup.vb — native binary validation before accepting any requests
Public Module AppStartup
    Public Sub InitializeOcr()
        ' Validate native library is reachable before first use
        Dim nativePath As String = If(RuntimeInformation.IsOSPlatform(OSPlatform.Windows),
                                      Path.Combine(AppContext.BaseDirectory, "aocr_x64.dll"),
                                      If(RuntimeInformation.IsOSPlatform(OSPlatform.Linux),
                                         "/usr/lib/libaocr.so",
                                         "/usr/local/lib/libaocr.dylib"))

        If Not File.Exists(nativePath) Then
            Throw New FileNotFoundException($"Asprise native binary not found: {nativePath}. " &
                                            "Deploy the correct platform binary before starting.")
        End If

        ' Static global init — must run before any Ocr instance is created
        Ocr.SetUp()
    End Sub
End Module
$vbLabelText   $csharpLabel

IronOCR Ansatz:

// Program.cs — license key assignment is the entire initialization
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

// That is it.Neinbinary validation, no path configuration, no SetUp() call.
// NuGet resolved the correct native runtime during package restore.
// Program.cs — license key assignment is the entire initialization
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

// That is it.Neinbinary validation, no path configuration, no SetUp() call.
// NuGet resolved the correct native runtime during package restore.
' Program.vb — license key assignment is the entire initialization
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"

' That is it. No binary validation, no path configuration, no SetUp() call.
' NuGet resolved the correct native runtime during package restore.
$vbLabelText   $csharpLabel

Das Asprise-Muster umfasst typischerweise 15-30 Zeilen über mehrere Dateien hinweg - einen Startvalidierer, einen Plattformwechsel, eine Ausnahme mit einer Bereitstellungsnachricht und den SetUp() Aufruf.IronOCR ersetzt das alles durch eine einzige Aufgabe. Der IronTesseract-Einrichtungsleitfaden beschreibt die Bereitstellungskonfigurationsoptionen für Umgebungen, die benutzerdefinierte Tessdata-Pfade oder einen Offline-Betrieb erfordern.

Ersetzung des XML-Ausgabeformats durch strukturierte Ergebnisobjekte

Asprise erzeugt strukturierten Output als rohen XML-String, wenn OUTPUT_FORMAT_XML angegeben ist. Um aus dieser Zeichenkette Worttext, Koordinaten und Konfidenzwerte zu extrahieren, ist XML-Parsing-Code erforderlich.IronOCR gibt einen typisierten Objektgraphen zurück.

Asprise OCR-Ansatz:

// Asprise: structured output is an XML string — must parse manually
Ocr.SetUp();
Ocr ocr = new Ocr();
try
{
    ocr.StartEngine("eng", Ocr.SPEED_FAST);
    string xmlOutput = ocr.Recognize(
        imagePath,
        Ocr.RECOGNIZE_TYPE_TEXT,
        Ocr.OUTPUT_FORMAT_XML);   // Returns raw XML, not an object

    // Parse the XML manually to extract words and coordinates
    var doc = System.Xml.Linq.XDocument.Parse(xmlOutput);
    var words = doc.Descendants("word")
        .Select(w => new
        {
            Text       = (string)w.Attribute("text"),
            Confidence = (float)w.Attribute("confidence"),
            X          = (int)w.Attribute("x"),
            Y          = (int)w.Attribute("y"),
        })
        .ToList();

    foreach (var word in words)
        Console.WriteLine($"{word.Text} @ ({word.X},{word.Y}) conf={word.Confidence}");
}
finally
{
    ocr.StopEngine();
}
// Asprise: structured output is an XML string — must parse manually
Ocr.SetUp();
Ocr ocr = new Ocr();
try
{
    ocr.StartEngine("eng", Ocr.SPEED_FAST);
    string xmlOutput = ocr.Recognize(
        imagePath,
        Ocr.RECOGNIZE_TYPE_TEXT,
        Ocr.OUTPUT_FORMAT_XML);   // Returns raw XML, not an object

    // Parse the XML manually to extract words and coordinates
    var doc = System.Xml.Linq.XDocument.Parse(xmlOutput);
    var words = doc.Descendants("word")
        .Select(w => new
        {
            Text       = (string)w.Attribute("text"),
            Confidence = (float)w.Attribute("confidence"),
            X          = (int)w.Attribute("x"),
            Y          = (int)w.Attribute("y"),
        })
        .ToList();

    foreach (var word in words)
        Console.WriteLine($"{word.Text} @ ({word.X},{word.Y}) conf={word.Confidence}");
}
finally
{
    ocr.StopEngine();
}
Imports System.Xml.Linq

' Asprise: structured output is an XML string — must parse manually
Ocr.SetUp()
Dim ocr As New Ocr()
Try
    ocr.StartEngine("eng", Ocr.SPEED_FAST)
    Dim xmlOutput As String = ocr.Recognize(imagePath, Ocr.RECOGNIZE_TYPE_TEXT, Ocr.OUTPUT_FORMAT_XML) ' Returns raw XML, not an object

    ' Parse the XML manually to extract words and coordinates
    Dim doc As XDocument = XDocument.Parse(xmlOutput)
    Dim words = doc.Descendants("word") _
        .Select(Function(w) New With {
            .Text = CStr(w.Attribute("text")),
            .Confidence = CSng(w.Attribute("confidence")),
            .X = CInt(w.Attribute("x")),
            .Y = CInt(w.Attribute("y"))
        }) _
        .ToList()

    For Each word In words
        Console.WriteLine($"{word.Text} @ ({word.X},{word.Y}) conf={word.Confidence}")
Next
Finally
    ocr.StopEngine()
End Try
$vbLabelText   $csharpLabel

IronOCR Ansatz:

// IronOCR: structured result is a typed object — no XML parsing
var result = new IronTesseract().Read(imagePath);

foreach (var page in result.Pages)
{
    foreach (var paragraph in page.Paragraphs)
    {
        foreach (var word in paragraph.Words)
        {
            Console.WriteLine(
                $"{word.Text} @ ({word.X},{word.Y}) conf={word.Confidence:F1}%");
        }
    }
}
// IronOCR: structured result is a typed object — no XML parsing
var result = new IronTesseract().Read(imagePath);

foreach (var page in result.Pages)
{
    foreach (var paragraph in page.Paragraphs)
    {
        foreach (var word in paragraph.Words)
        {
            Console.WriteLine(
                $"{word.Text} @ ({word.X},{word.Y}) conf={word.Confidence:F1}%");
        }
    }
}
Imports IronOcr

' IronOCR: structured result is a typed object — no XML parsing
Dim result = New IronTesseract().Read(imagePath)

For Each page In result.Pages
    For Each paragraph In page.Paragraphs
        For Each word In paragraph.Words
            Console.WriteLine($"{word.Text} @ ({word.X},{word.Y}) conf={word.Confidence:F1}%")
        Next
    Next
Next
$vbLabelText   $csharpLabel

Keine XML-Deserialisierung, keine Attributumwandlung, keine Schemaannahmen. Das OcrResult Objektmodell stellt Seiten, Absätze, Zeilen, Wörter und Zeichen mit typisierten Eigenschaften bereit. Der Leitfaden zu den Leseergebnissen beschreibt die gesamte Hierarchie und das Koordinatensystem und erklärt unter anderem, wie man für automatisierte Arbeitsabläufe nach Konfidenzschwellenwerten filtert.

Mehrbild-TIFF-Verarbeitung

Asprise akzeptiert einzelne Bilddateien. Eine TIFF-Datei mit mehreren Einzelbildern – üblich bei Dokumentenscanning-Workflows – muss in einzelne Einzelbilddateien aufgeteilt werden, bevor Asprise sie verarbeiten kann.IronOCR akzeptiert mehrseitige TIFFs direkt über LoadImageFrames.

Asprise OCR-Ansatz:

// Asprise: no multi-frame TIFF support — split frames externally first
// Using an external imaging library (e.g., System.Drawing or Magick.NET)
var frameFiles = new List<string>();
using (var tiff = System.Drawing.Image.FromFile("scanned-batch.tiff"))
{
    int frameCount = tiff.GetFrameCount(System.Drawing.Imaging.FrameDimension.Page);
    for (int i = 0; i < frameCount; i++)
    {
        tiff.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, i);
        string framePath = $"frame_{i}.png";
        tiff.Save(framePath);
        frameFiles.Add(framePath);
    }
}

// Now process each frame individually — sequential on LITE/STANDARD
var allText = new System.Text.StringBuilder();
Ocr.SetUp();
Ocr ocr = new Ocr();
try
{
    ocr.StartEngine("eng", Ocr.SPEED_FAST);
    foreach (var framePath in frameFiles)
    {
        string pageText = ocr.Recognize(
            framePath,
            Ocr.RECOGNIZE_TYPE_TEXT,
            Ocr.OUTPUT_FORMAT_PLAINTEXT);
        allText.AppendLine(pageText);
    }
}
finally
{
    ocr.StopEngine();
    // Clean up temporary frame files
    foreach (var f in frameFiles)
        File.Delete(f);
}
Console.WriteLine(allText.ToString());
// Asprise: no multi-frame TIFF support — split frames externally first
// Using an external imaging library (e.g., System.Drawing or Magick.NET)
var frameFiles = new List<string>();
using (var tiff = System.Drawing.Image.FromFile("scanned-batch.tiff"))
{
    int frameCount = tiff.GetFrameCount(System.Drawing.Imaging.FrameDimension.Page);
    for (int i = 0; i < frameCount; i++)
    {
        tiff.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, i);
        string framePath = $"frame_{i}.png";
        tiff.Save(framePath);
        frameFiles.Add(framePath);
    }
}

// Now process each frame individually — sequential on LITE/STANDARD
var allText = new System.Text.StringBuilder();
Ocr.SetUp();
Ocr ocr = new Ocr();
try
{
    ocr.StartEngine("eng", Ocr.SPEED_FAST);
    foreach (var framePath in frameFiles)
    {
        string pageText = ocr.Recognize(
            framePath,
            Ocr.RECOGNIZE_TYPE_TEXT,
            Ocr.OUTPUT_FORMAT_PLAINTEXT);
        allText.AppendLine(pageText);
    }
}
finally
{
    ocr.StopEngine();
    // Clean up temporary frame files
    foreach (var f in frameFiles)
        File.Delete(f);
}
Console.WriteLine(allText.ToString());
Imports System.Drawing
Imports System.Text
Imports System.IO

' Asprise: no multi-frame TIFF support — split frames externally first
' Using an external imaging library (e.g., System.Drawing or Magick.NET)
Dim frameFiles As New List(Of String)()
Using tiff As Image = Image.FromFile("scanned-batch.tiff")
    Dim frameCount As Integer = tiff.GetFrameCount(Imaging.FrameDimension.Page)
    For i As Integer = 0 To frameCount - 1
        tiff.SelectActiveFrame(Imaging.FrameDimension.Page, i)
        Dim framePath As String = $"frame_{i}.png"
        tiff.Save(framePath)
        frameFiles.Add(framePath)
    Next
End Using

' Now process each frame individually — sequential on LITE/STANDARD
Dim allText As New StringBuilder()
Ocr.SetUp()
Dim ocr As New Ocr()
Try
    ocr.StartEngine("eng", Ocr.SPEED_FAST)
    For Each framePath As String In frameFiles
        Dim pageText As String = ocr.Recognize(framePath, Ocr.RECOGNIZE_TYPE_TEXT, Ocr.OUTPUT_FORMAT_PLAINTEXT)
        allText.AppendLine(pageText)
    Next
Finally
    ocr.StopEngine()
    ' Clean up temporary frame files
    For Each f As String In frameFiles
        File.Delete(f)
    Next
End Try
Console.WriteLine(allText.ToString())
$vbLabelText   $csharpLabel

IronOCR Ansatz:

// IronOCR: multi-frame TIFF loads directly — no frame splitting, no temp files
using var input = new OcrInput();
input.LoadImageFrames("scanned-batch.tiff");  // All frames, one call

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

// Access each page independently with its page number
foreach (var page in result.Pages)
    Console.WriteLine($"Page {page.PageNumber}: {page.Text}");
// IronOCR: multi-frame TIFF loads directly — no frame splitting, no temp files
using var input = new OcrInput();
input.LoadImageFrames("scanned-batch.tiff");  // All frames, one call

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

// Access each page independently with its page number
foreach (var page in result.Pages)
    Console.WriteLine($"Page {page.PageNumber}: {page.Text}");
Imports IronOcr

' IronOCR: multi-frame TIFF loads directly — no frame splitting, no temp files
Using input As New OcrInput()
    input.LoadImageFrames("scanned-batch.tiff") ' All frames, one call

    Dim result = New IronTesseract().Read(input)

    ' Access each page independently with its page number
    For Each page In result.Pages
        Console.WriteLine($"Page {page.PageNumber}: {page.Text}")
    Next
End Using
$vbLabelText   $csharpLabel

Der Asprise-Ansatz erfordert eine externe Bildverarbeitungsabhängigkeit, temporäre Dateiverwaltung, manuelle Bereinigung und sequentielle Verarbeitung jedes einzelnen Frames.IronOCR verarbeitet alle Frames in einem einzigen Durchgang. Der Leitfaden zur Eingabe von TIFF- und GIF-Dateien behandelt die Auswahl des Framebereichs für große TIFF-Dateien, bei denen nur bestimmte Seiten benötigt werden.

durchsuchbare PDF-Generierung

Asprise bietet in keiner Lizenzstufe die Möglichkeit, durchsuchbare PDFs auszugeben. Das Erstellen einer PDF-Datei mit eingebettetem OCR-Text aus einem gescannten Dokument erfordert eine externe PDF-Bibliothek, einen separaten OCR-Durchlauf zur Ermittlung der Textpositionen und die manuelle Erstellung der Überlagerung.IronOCR erzeugt direkt aus dem Erkennungsergebnis durchsuchbare PDFs.

Asprise OCR-Ansatz:

// Asprise: no searchable PDF output — external PDF library required
// Step 1: OCR the document to get text
Ocr.SetUp();
Ocr ocr = new Ocr();
string recognizedText;
try
{
    ocr.StartEngine("eng", Ocr.SPEED_FAST);
    recognizedText = ocr.Recognize(
        "scanned-contract.jpg",
        Ocr.RECOGNIZE_TYPE_TEXT,
        Ocr.OUTPUT_FORMAT_PLAINTEXT);   // Only plain text — no position data
}
finally
{
    ocr.StopEngine();
}

// Step 2: Use an external PDF library to embed text over the image
// (iTextSharp, PdfSharp, or similar — adds another dependency and license)
// Text positioning requires coordinate data Asprise cannot provide in plain text mode
// ... 40-80 lines of PDF construction code
Console.WriteLine("Searchable PDF: not achievable with Asprise alone");
// Asprise: no searchable PDF output — external PDF library required
// Step 1: OCR the document to get text
Ocr.SetUp();
Ocr ocr = new Ocr();
string recognizedText;
try
{
    ocr.StartEngine("eng", Ocr.SPEED_FAST);
    recognizedText = ocr.Recognize(
        "scanned-contract.jpg",
        Ocr.RECOGNIZE_TYPE_TEXT,
        Ocr.OUTPUT_FORMAT_PLAINTEXT);   // Only plain text — no position data
}
finally
{
    ocr.StopEngine();
}

// Step 2: Use an external PDF library to embed text over the image
// (iTextSharp, PdfSharp, or similar — adds another dependency and license)
// Text positioning requires coordinate data Asprise cannot provide in plain text mode
// ... 40-80 lines of PDF construction code
Console.WriteLine("Searchable PDF: not achievable with Asprise alone");
' Asprise: no searchable PDF output — external PDF library required
' Step 1: OCR the document to get text
Ocr.SetUp()
Dim ocr As New Ocr()
Dim recognizedText As String
Try
    ocr.StartEngine("eng", Ocr.SPEED_FAST)
    recognizedText = ocr.Recognize( _
        "scanned-contract.jpg", _
        Ocr.RECOGNIZE_TYPE_TEXT, _
        Ocr.OUTPUT_FORMAT_PLAINTEXT)   ' Only plain text — no position data
Finally
    ocr.StopEngine()
End Try

' Step 2: Use an external PDF library to embed text over the image
' (iTextSharp, PdfSharp, or similar — adds another dependency and license)
' Text positioning requires coordinate data Asprise cannot provide in plain text mode
' ... 40-80 lines of PDF construction code
Console.WriteLine("Searchable PDF: not achievable with Asprise alone")
$vbLabelText   $csharpLabel

IronOCR Ansatz:

// IronOCR: searchable PDF in two lines — no external PDF library
var result = new IronTesseract().Read("scanned-contract.jpg");
result.SaveAsSearchablePdf("searchable-contract.pdf");

// Batch: convert a folder of scanned images to searchable PDFs
foreach (var imagePath in Directory.GetFiles("scans", "*.jpg"))
{
    var batchResult = new IronTesseract().Read(imagePath);
    string outputPath = Path.ChangeExtension(imagePath, ".searchable.pdf");
    batchResult.SaveAsSearchablePdf(outputPath);
    Console.WriteLine($"Converted: {outputPath}");
}
// IronOCR: searchable PDF in two lines — no external PDF library
var result = new IronTesseract().Read("scanned-contract.jpg");
result.SaveAsSearchablePdf("searchable-contract.pdf");

// Batch: convert a folder of scanned images to searchable PDFs
foreach (var imagePath in Directory.GetFiles("scans", "*.jpg"))
{
    var batchResult = new IronTesseract().Read(imagePath);
    string outputPath = Path.ChangeExtension(imagePath, ".searchable.pdf");
    batchResult.SaveAsSearchablePdf(outputPath);
    Console.WriteLine($"Converted: {outputPath}");
}
Imports System.IO
Imports IronOcr

' IronOCR: searchable PDF in two lines — no external PDF library
Dim result = New IronTesseract().Read("scanned-contract.jpg")
result.SaveAsSearchablePdf("searchable-contract.pdf")

' Batch: convert a folder of scanned images to searchable PDFs
For Each imagePath In Directory.GetFiles("scans", "*.jpg")
    Dim batchResult = New IronTesseract().Read(imagePath)
    Dim outputPath As String = Path.ChangeExtension(imagePath, ".searchable.pdf")
    batchResult.SaveAsSearchablePdf(outputPath)
    Console.WriteLine($"Converted: {outputPath}")
Next
$vbLabelText   $csharpLabel

Das durchsuchbare PDF enthält das Originalbild als visuelle Ebene mit unsichtbarem OCR-Text, der an den richtigen Koordinaten darübergelegt ist – das Standardformat für Archivierungs- und Compliance-Workflows. Eine Anleitung im durchsuchbaren PDF-Format sowie ein Beispiel im durchsuchbaren PDF-Format zeigen Ihnen die verschiedenen Optionen, darunter die PDF/A-Ausgabe für die Langzeitarchivierung.

Asynchrone OCR in Webanwendungen

Asprise verfügt über keine asynchrone API. Entwickler integrieren es in asynchrone .NET-Anwendungen, indem sie synchrone Aufrufe in Task.Run verpacken, was Threadpool-Threads verbraucht und das Blockieren nicht eliminiert.IronOCR bietet einen nativen asynchronen Pfad.

Asprise OCR-Ansatz:

// Asprise: no async API — must offload to Task.Run
// This blocks a thread pool thread during the entire OCR operation
// On LITE/STANDARD, concurrent Task.Run calls = license violation
public async Task<string> ProcessUploadAsync(Stream fileStream, string fileName)
{
    string tempPath = Path.GetTempFileName();
    await using (var fs = new FileStream(tempPath, FileMode.Create))
        await fileStream.CopyToAsync(fs);

    // Task.Run wraps synchronous Asprise — occupies a thread pool thread
    // Two concurrent requests still violate LITE/STANDARD license
    return await Task.Run(() =>
    {
        Ocr ocr = new Ocr();
        try
        {
            ocr.StartEngine("eng", Ocr.SPEED_FAST);
            return ocr.Recognize(
                tempPath,
                Ocr.RECOGNIZE_TYPE_TEXT,
                Ocr.OUTPUT_FORMAT_PLAINTEXT);
        }
        finally
        {
            ocr.StopEngine();
            File.Delete(tempPath);
        }
    });
}
// Asprise: no async API — must offload to Task.Run
// This blocks a thread pool thread during the entire OCR operation
// On LITE/STANDARD, concurrent Task.Run calls = license violation
public async Task<string> ProcessUploadAsync(Stream fileStream, string fileName)
{
    string tempPath = Path.GetTempFileName();
    await using (var fs = new FileStream(tempPath, FileMode.Create))
        await fileStream.CopyToAsync(fs);

    // Task.Run wraps synchronous Asprise — occupies a thread pool thread
    // Two concurrent requests still violate LITE/STANDARD license
    return await Task.Run(() =>
    {
        Ocr ocr = new Ocr();
        try
        {
            ocr.StartEngine("eng", Ocr.SPEED_FAST);
            return ocr.Recognize(
                tempPath,
                Ocr.RECOGNIZE_TYPE_TEXT,
                Ocr.OUTPUT_FORMAT_PLAINTEXT);
        }
        finally
        {
            ocr.StopEngine();
            File.Delete(tempPath);
        }
    });
}
Imports System.IO
Imports System.Threading.Tasks

' Asprise: no async API — must offload to Task.Run
' This blocks a thread pool thread during the entire OCR operation
' On LITE/STANDARD, concurrent Task.Run calls = license violation
Public Async Function ProcessUploadAsync(fileStream As Stream, fileName As String) As Task(Of String)
    Dim tempPath As String = Path.GetTempFileName()
    Await Using fs As New FileStream(tempPath, FileMode.Create)
        Await fileStream.CopyToAsync(fs)
    End Using

    ' Task.Run wraps synchronous Asprise — occupies a thread pool thread
    ' Two concurrent requests still violate LITE/STANDARD license
    Return Await Task.Run(Function()
                              Dim ocr As New Ocr()
                              Try
                                  ocr.StartEngine("eng", Ocr.SPEED_FAST)
                                  Return ocr.Recognize(tempPath, Ocr.RECOGNIZE_TYPE_TEXT, Ocr.OUTPUT_FORMAT_PLAINTEXT)
                              Finally
                                  ocr.StopEngine()
                                  File.Delete(tempPath)
                              End Try
                          End Function)
End Function
$vbLabelText   $csharpLabel

IronOCR Ansatz:

// IronOCR: native async, concurrent requests permitted on all tiers
public async Task<string> ProcessUploadAsync(Stream fileStream, string fileName)
{
    using var input = new OcrInput();
    input.LoadImage(fileStream);       // Stream input directly — no temp file

    var ocr = new IronTesseract();
    var result = await ocr.ReadAsync(input);
    return result.Text;
}
// IronOCR: native async, concurrent requests permitted on all tiers
public async Task<string> ProcessUploadAsync(Stream fileStream, string fileName)
{
    using var input = new OcrInput();
    input.LoadImage(fileStream);       // Stream input directly — no temp file

    var ocr = new IronTesseract();
    var result = await ocr.ReadAsync(input);
    return result.Text;
}
Imports System.IO
Imports System.Threading.Tasks

' IronOCR: native async, concurrent requests permitted on all tiers
Public Async Function ProcessUploadAsync(fileStream As Stream, fileName As String) As Task(Of String)
    Using input As New OcrInput()
        input.LoadImage(fileStream) ' Stream input directly — no temp file

        Dim ocr As New IronTesseract()
        Dim result = Await ocr.ReadAsync(input)
        Return result.Text
    End Using
End Function
$vbLabelText   $csharpLabel

Die IronOCR-Version eliminiert das Schreiben einer temporären Datei, den Task.Run Wrapper und das Thread-Blockierungsverhalten. Mehrere gleichzeitige Anfragen erzeugen jeweils ihre eigene IronTesseract Instanz - die Klasse ist zustandslos und jede Instanz ist unabhängig. Der asynchrone OCR-Leitfaden behandelt ReadAsync Muster und Unterstützung für Abbruchtoken für langwierige Batch-Operationen in gehosteten Diensten.

Asprise OCRAPI zu IronOCR Mapping-Referenz

Asprise OCR IronOCR-Äquivalent
asprise.ocr Namespace IronOcr Namespace
Ocr.SetUp() Nicht erforderlich
new Ocr() new IronTesseract()
ocr.StartEngine("eng", Ocr.SPEED_FAST) Nicht erforderlich
ocr.StartEngine("eng+fra", speed) ocr.Language = OcrLanguage.English + OcrLanguage.French
ocr.Recognize(path, type, format) ocr.Read(path) oder ocr.Read(input)
Ocr.RECOGNIZE_TYPE_TEXT Standardverhalten
Ocr.RECOGNIZE_TYPE_BARCODE ocr.Configuration.ReadBarCodes = true
Ocr.RECOGNIZE_TYPE_ALL ocr.Configuration.ReadBarCodes = true
Ocr.OUTPUT_FORMAT_PLAINTEXT result.Text
Ocr.OUTPUT_FORMAT_XML result.Pages / result.Pages[n].Words
Ocr.OUTPUT_FORMAT_PDF result.SaveAsSearchablePdf(path)
Ocr.SPEED_FASTEST ocr.Configuration.TesseractEngineMode Abstimmung
Ocr.SPEED_FAST Standardkonfiguration
Ocr.SPEED_SLOW Konfigurationseinstellungen mit höherer Genauigkeit
ocr.StopEngine() Nicht erforderlich — OcrInput ist IDisposable
result.StartsWith("ERROR:") Überprüfung Standard .NET Ausnahmebehandlung (try/catch)
Plattformnative DLL (aocr_x64.dll) NuGet -Laufzeitpaket (automatisch)
Manuelle temporäre Datei für Stream-Eingabe input.LoadImage(stream) direkt
Externe Bibliothek für Mehrbild-TIFF input.LoadImageFrames(path)
Externe Bibliothek für durchsuchbare PDFs result.SaveAsSearchablePdf(path)

Gängige Migrationsprobleme und Lösungen

Problem 1: DllNotFoundException nach dem Entfernen nativer Binärdateien

Asprise OCR: Das Entfernen des Asprise NuGet Pakets, aber das Belassen von Verweisen auf native Binärdateien (in Projektdateikopierregeln, Docker COPY-Anweisungen oder Bereitstellungsskripten), kann DllNotFoundException verursachen, die von einer alten Konfiguration ausgehen, die auf eine nicht vorhandene Binärdatei verweist.

Lösung: Durchsuchen Sie Bereitstellungsartefakte nach Verweisen auf aocr, libaocr oder LD_LIBRARY_PATH Einstellungen und entfernen Sie sie.IronOCR hat keine entsprechenden Konfigurationsanforderungen. In der Dockerfile:

# Remove: COPY aocr_x64.dll /app/
# Remove: ENV LD_LIBRARY_PATH=/app
# IronOCR: nothing to add — NuGet handles native runtime packaging
RUN dotnet restore
RUN dotnet publish -c Release -o /app/publish

Für die plattformübergreifende Bereitstellung beschreibt der Docker-Bereitstellungsleitfaden die Basis-Image-Anforderungen für IronOCR auf Linux-Containern.

Problem 2: Fehlende Ocr.SetUp() Entfernung bricht den Startvorgang ab

Asprise OCR: Ocr.SetUp() führt eine globale native Initialisierung durch. Einige Codebasen rufen dies in einem statischen Konstruktor oder Startup.Configure auf. Nach der Migration entfernt das Entfernen des Asprise-Namespace den Kompilierungsfehler, aber wenn SetUp() in einem try/catch eingewickelt ist, das die Ausnahme unterdrückt, kann der Code stillschweigend kompilieren und ausgeführt werden, ohne etwas zu initialisieren.

Lösung: Suchen Sie nach allen SetUp() Aufrufen und entfernen Sie den gesamten Initialisierungsblock. Ersetzen Sie den entsprechenden Start-Hook durch die IronOCR Lizenzschlüsselzuweisung:

grep -rn "Ocr.SetUp\|StartEngine\|StopEngine" --include="*.cs" .
grep -rn "Ocr.SetUp\|StartEngine\|StopEngine" --include="*.cs" .
SHELL
// Remove all occurrences of the engine lifecycle pattern:
// Ocr.SetUp();
// ocr.StartEngine(...);
// ocr.StopEngine();

// Replace application startup initialization with:
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
// Remove all occurrences of the engine lifecycle pattern:
// Ocr.SetUp();
// ocr.StartEngine(...);
// ocr.StopEngine();

// Replace application startup initialization with:
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
$vbLabelText   $csharpLabel

Problem 3: Es gibt keinen direkten Ersatz für den XML-Ausgabe-Parsing-Code.

Asprise OCR: Code, der OUTPUT_FORMAT_XML Strings mit XDocument, XmlReader oder Regex-Mustern parst, hat keine entsprechende XML-Struktur in IronOCR. Das von Asprise erzeugte XML-Schema lässt sich nicht direkt auf das Objektmodell von IronOCR abbilden.

Lösung: Ersetzen Sie den XML-Parsing-Code durch direkten Zugriff auf Eigenschaft von OcrResult. Die Zuordnung ist wie folgt:

// Asprise XML parsing (remove)
var words = XDocument.Parse(xmlOutput)
    .Descendants("word")
    .Select(w => new { Text = (string)w.Attribute("text"), X = (int)w.Attribute("x") });

//IronOCR object model (replace with)
var result = new IronTesseract().Read(imagePath);
var words = result.Pages
    .SelectMany(p => p.Paragraphs)
    .SelectMany(para => para.Words)
    .Select(w => new { w.Text, w.X });
// Asprise XML parsing (remove)
var words = XDocument.Parse(xmlOutput)
    .Descendants("word")
    .Select(w => new { Text = (string)w.Attribute("text"), X = (int)w.Attribute("x") });

//IronOCR object model (replace with)
var result = new IronTesseract().Read(imagePath);
var words = result.Pages
    .SelectMany(p => p.Paragraphs)
    .SelectMany(para => para.Words)
    .Select(w => new { w.Text, w.X });
Imports System.Xml.Linq
Imports IronOcr

' Asprise XML parsing (remove)
Dim words = XDocument.Parse(xmlOutput) _
    .Descendants("word") _
    .Select(Function(w) New With {Key .Text = CType(w.Attribute("text"), String), Key .X = CType(w.Attribute("x"), Integer)})

' IronOCR object model (replace with)
Dim result = New IronTesseract().Read(imagePath)
Dim words = result.Pages _
    .SelectMany(Function(p) p.Paragraphs) _
    .SelectMany(Function(para) para.Words) _
    .Select(Function(w) New With {w.Text, w.X})
$vbLabelText   $csharpLabel

Der Leitfaden zu den Leseergebnissen umfasst die gesamte Objekthierarchie einschließlich der Daten auf Zeichenebene mit Begrenzungsrahmen.

Problem 4: Task.Run-Wrapper verursachen Thread-Pool-Erschöpfung

Asprise OCR: Webanwendungen mit hoher Parallelität, die Asprise in Task.Run einwickeln, können den Threadpool erschöpfen, wenn das OCR-Aufkommen ansteigt. Jeder eingereihte Task.Run hält einen Threadpool-Thread für die gesamte Dauer der OCR-Operation.

Lösung: Ersetzen Sie Task.Run(() =&gt; { asprise... }) Muster mit nativen IronOCR asynchronen Aufrufen. Jede IronTesseract Instanz ist unabhängig — erstellen Sie eine pro Anfrage:

// Remove: await Task.Run(() => { ocr.Recognize(...) });

// Replace with:
using var input = new OcrInput();
input.LoadImage(stream);
var result = await new IronTesseract().ReadAsync(input);
return result.Text;
// Remove: await Task.Run(() => { ocr.Recognize(...) });

// Replace with:
using var input = new OcrInput();
input.LoadImage(stream);
var result = await new IronTesseract().ReadAsync(input);
return result.Text;
Imports IronTesseract

Using input As New OcrInput()
    input.LoadImage(stream)
    Dim result = Await (New IronTesseract()).ReadAsync(input)
    Return result.Text
End Using
$vbLabelText   $csharpLabel

Ausgabe 5: Validierung von Zeichenketten-basierten Sprachcodes

Asprise OCR: Sprachcodes werden als Strings ("eng", "fra", "eng+fra") übergeben. Anwendungen, die diese Strings zur Laufzeit validieren - durch Überprüfung gegen eine fest codierte Liste, Lesen aus der Konfiguration - müssen aktualisiert werden, wenn sich das String-Format zu OcrLanguage Aufzählung ändert.

Lösung: Ersetzen Sie String-Sprachparameter durch OcrLanguage Aufzählungswerte. Konfigurationsgesteuerte Sprachauswahl ordnet sich sauber zu Enum.Parse:

// Asprise string-based (remove)
string language = config["OcrLanguage"];  // e.g. "eng+fra"
ocr.StartEngine(language, Ocr.SPEED_FAST);

//IronOCR enum-based (replace with)
// For single language from config:
var ocr = new IronTesseract();
ocr.Language = Enum.Parse<OcrLanguage>(config["OcrLanguage"]);  // e.g. "English"
var result = ocr.Read(input);
// Asprise string-based (remove)
string language = config["OcrLanguage"];  // e.g. "eng+fra"
ocr.StartEngine(language, Ocr.SPEED_FAST);

//IronOCR enum-based (replace with)
// For single language from config:
var ocr = new IronTesseract();
ocr.Language = Enum.Parse<OcrLanguage>(config["OcrLanguage"]);  // e.g. "English"
var result = ocr.Read(input);
Imports System
Imports IronOcr

' Asprise string-based (remove)
Dim language As String = config("OcrLanguage")  ' e.g. "eng+fra"
ocr.StartEngine(language, Ocr.SPEED_FAST)

' IronOCR enum-based (replace with)
' For single language from config:
Dim ocr As New IronTesseract()
ocr.Language = [Enum].Parse(Of OcrLanguage)(config("OcrLanguage"))  ' e.g. "English"
Dim result = ocr.Read(input)
$vbLabelText   $csharpLabel

Der Leitfaden für mehrere Sprachen listet alle gültigen OcrLanguage Aufzählungswerte und ihre entsprechenden NuGet Sprachpaketpakete auf.

Problem 6: Logik zur Lizenzstufenprüfung nicht mehr erforderlich

Asprise OCR: Einige Produktionscodebasen enthalten Laufzeitprüfungen, die die Asprise-Lizenzstufe erkennen und die OCR-Verarbeitung serialisieren, wenn die Lizenzstufe unterhalb von Enterprise liegt. Diese Schutzmaßnahmen verhindern Lizenzverstöße, erhöhen jedoch die Komplexität und reduzieren den Durchsatz.

Lösung: Entfernen Sie alle Tier-Erkennungs- und Serialisierungsschutzmechanismen.IronOCR unterliegt in keiner Stufe einer Threading-Beschränkung. Die ConcurrentQueue, SemaphoreSlim oder Einzellenker-Muster, die verwendet werden, um Asprise-Aufrufe zu serialisieren, sind nach der Migration nicht mehr erforderlich:

// Remove: SemaphoreSlim _ocrLock = new SemaphoreSlim(1, 1);
// Remove: await _ocrLock.WaitAsync(); ... _ocrLock.Release();

// IronOCR: direct concurrent access, no guards needed
Parallel.ForEach(documentPaths, path =>
{
    var text = new IronTesseract().Read(path).Text;
    results[path] = text;
});
// Remove: SemaphoreSlim _ocrLock = new SemaphoreSlim(1, 1);
// Remove: await _ocrLock.WaitAsync(); ... _ocrLock.Release();

// IronOCR: direct concurrent access, no guards needed
Parallel.ForEach(documentPaths, path =>
{
    var text = new IronTesseract().Read(path).Text;
    results[path] = text;
});
Imports System.Threading.Tasks

' IronOCR: direct concurrent access, no guards needed
Parallel.ForEach(documentPaths, Sub(path)
    Dim text = (New IronTesseract()).Read(path).Text
    results(path) = text
End Sub)
$vbLabelText   $csharpLabel

Asprise OCR-Migrationscheckliste

Vor der Migration

Prüfen Sie den Quellcode auf alle Asprise-Verwendungen, bevor Sie Ersatzcode schreiben:

# Find all files importing asprise namespace
grep -rn "using asprise" --include="*.cs" .

# Find all engine lifecycle calls
grep -rn "SetUp\|StartEngine\|StopEngine" --include="*.cs" .

# Find all integer constant references
grep -rn "RECOGNIZE_TYPE\|OUTPUT_FORMAT\|SPEED_FAST\|SPEED_SLOW" --include="*.cs" .

# Find native binary references in project files and deployment scripts
grep -rn "aocr\|libaocr" --include="*.csproj" --include="Dockerfile" --include="*.yml" .

# Find XML output parsing code
grep -rn "OUTPUT_FORMAT_XML\|XDocument.Parse\|Descendants.*word" --include="*.cs" .

# Find Task.Run wrappers around OCR calls
grep -rn "Task.Run.*ocr\|Task.Run.*Recognize" --include="*.cs" .
# Find all files importing asprise namespace
grep -rn "using asprise" --include="*.cs" .

# Find all engine lifecycle calls
grep -rn "SetUp\|StartEngine\|StopEngine" --include="*.cs" .

# Find all integer constant references
grep -rn "RECOGNIZE_TYPE\|OUTPUT_FORMAT\|SPEED_FAST\|SPEED_SLOW" --include="*.cs" .

# Find native binary references in project files and deployment scripts
grep -rn "aocr\|libaocr" --include="*.csproj" --include="Dockerfile" --include="*.yml" .

# Find XML output parsing code
grep -rn "OUTPUT_FORMAT_XML\|XDocument.Parse\|Descendants.*word" --include="*.cs" .

# Find Task.Run wrappers around OCR calls
grep -rn "Task.Run.*ocr\|Task.Run.*Recognize" --include="*.cs" .
SHELL

Die Ergebnisse inventarisieren:

  • Dateien zählen, die asprise.ocr importieren — all diese benötigen Namespace-Updates
  • Listen Sie jede StartEngine Aufrufstelle auf — jede wird zu einem Read Aufruf
  • XML-Ausgabe-Parsing-Code identifizieren – jeder Block muss durch ein Objektmodell ersetzt werden. Beachten Sie etwaige Lizenzschutzmechanismen oder Serialisierungshüllen – diese können entfernt werden.
  • Auffinden nativer Binärbereitstellungsskripte und Containerkonfiguration

Code-Migration

  1. Entfernen Sie das asprise-ocr-api NuGet-Paket aus allen Projekten
  2. Installieren Sie das IronOcr NuGet-Paket in jedem Projekt, das OCR ausführt
  3. Ersetzen Sie using asprise.ocr durch using IronOcr in allen Dateien
  4. Fügen Sie IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY" beim Anwendungsstart hinzu
  5. Entfernen Sie Ocr.SetUp() Aufrufe aus allen Start- und Initialisierungscode
  6. Ersetzen Sie jeden Ocr.StartEngine / Recognize / StopEngine Block mit new IronTesseract().Read(path).Text
  7. Ersetzen Sie OUTPUT_FORMAT_XML Parsing-Blöcke durch result.Pages Objekt-Durchlauf
  8. Ersetzen Sie OUTPUT_FORMAT_PDF Workarounds durch result.SaveAsSearchablePdf(path)
  9. Ersetzen Sie den Mehrrahmen-TIFF-Aufspaltungscode durch input.LoadImageFrames(tiffPath)
  10. Ersetzen Sie streambasierte Task.Run Wrapper mit await ocr.ReadAsync(input)
  11. Entfernen Sie SemaphoreSlim oder Serialisierungsabsicherungen, die Asprise vor gleichzeitiger Nutzung schützen
  12. Entfernen Sie native Binärkopieranweisungen aus .csproj Dateien und Dockerfiles
  13. Entfernen Sie LD_LIBRARY_PATH Einstellungen aus der Umgebungskonfiguration und CI-Skripten
  14. Ersetzen Sie String-Sprachcodes ("eng", "eng+fra") durch OcrLanguage Aufzählungswerte
  15. Ersetzen Sie result.StartsWith("ERROR:") Prüfungen durch try/catch Blöcke

Nach der Migration

  • Überprüfen Sie, ob dotnet build ohne Warnungen über fehlende native Bibliotheken abgeschlossen wird
  • Bestätigen Sie, dass kein DllNotFoundException oder BadImageFormatException beim Start unter allen Zielumgebungen (Windows, Linux, Docker) auftritt
  • Führen Sie eine OCR-Texterkennung an einem repräsentativen Bild durch und bestätigen Sie, dass die Textausgabe der Baseline vor der Migration entspricht.
  • Testen Sie die Verarbeitung von TIFF-Dateien mit mehreren Einzelbildern und überprüfen Sie, ob alle Seiten mit den korrekten Seitenzahlen zurückgegeben werden.
  • Erstellen Sie eine durchsuchbare PDF-Datei und überprüfen Sie, ob der Text in einem PDF-Viewer auswählbar und durchsuchbar ist.
  • Gleichzeitige HTTP-Anfragen an beliebige API-Endpunkte senden, die OCR aufrufen, und bestätigen, dass alle Anfragen fehlerfrei abgeschlossen wurden.
  • Überprüfen, ob asynchrone Endpunkte unter gleichzeitiger Last Ergebnisse ohne Deadlocks zurückgeben.
  • Bestätigen, dass die strukturierte Datenextraktion (Wortkoordinaten und Konfidenz) bei einem bekannten Dokument korrekte Ergebnisse liefert.
  • Überprüfen Sie die Speichernutzung der Anwendung im Laufe der Zeit, um sicherzustellen, dass keine nativen Speicherlecks vorhanden sind (zuvor verursacht durch fehlende StopEngine() Aufrufe)
  • Führen Sie die Anwendung unter Linux oder in einem Docker-Container aus, um zu bestätigen, dass die plattformübergreifende Bereitstellung ohne Binärkonfiguration funktioniert.

Wichtigste Vorteile der Migration zu IronOCR

Die Bereitstellung reduziert sich auf einen einzigen NuGet Verweis. Nach der Migration installiert jedes Bereitstellungsziel – Entwicklungsarbeitsplätze, Staging-Server, Linux-Container, CI-Agenten – dasselbe Paket mit demselben Befehl. Es gibt keine Logik zur Plattformerkennung, keine architekturspezifische Binärquellenbeschaffung und keine Laufzeitpfadkonfiguration. Ein Docker-Image, das zuvor manuelle native Binär-COPY-Anweisungen erforderte, benötigt nun nichts weiter als dotnet restore. Der Linux-Bereitstellungsleitfaden und der Azure-Bereitstellungsleitfaden enthalten gegebenenfalls umgebungsspezifische Hinweise.

Alle Lizenzstufen ermöglichen eine servergerechte Bereitstellung. Die $999 Lite Lizenz unterstützt ASP.NET Core Web-APIs, Windows-Dienste, Azure-Funktionen, AWS Lambda und jede andere mehrsträngige .NET-Arbeitslast. Die Threading-Funktion auf Enterprise-Niveau, für die Asprise 2.000 bis 5.000 US-Dollar und mehr berechnet, ist in jeder IronOCR Stufe enthalten. Teams, die von Asprise Enterprise auf IronOCR Lite umsteigen, reduzieren ihre OCR-Lizenzkosten und erhalten gleichzeitig Funktionen, die Enterprise nicht bot – natives PDF, strukturierte Ausgabe, durchsuchbare PDF-Generierung und 125 Sprachen.

Strukturierte OCR-Ergebnisse ersetzen XML-String-Parsing. Das OcrResult Objektmodell stellt eine vollständige Dokumenthierarchie bereit: Seiten, Absätze, Zeilen, Wörter und Zeichen, jeweils mit pixelgenauen Begrenzungsrahmenkoordinaten und Vertrauensgrad. Code, der zuvor Asprise-XML-Zeichenketten mit XDocument oder regulären Ausdrücken analysiert hat, wird nun durch direkten Eigenschaftszugriff ersetzt. Die Seite mit den OCR-Ergebnissen behandelt Koordinatensysteme und wie man Ergebnisse nach Konfidenzintervall für automatisierte Qualitätskontrollen filtert.

Eingebautes Preprocessing entfernt externe Bildabhängigkeiten. Die Preprocessing-Pipeline, die über OcrInput verfügbar ist — Deskew, DeNoise, Contrast, Binarize, Sharpen, Dilate, Erode, Scale, Invert und DeepCleanBackgroundNoise — eliminiert die externe Bildbibliothek, die Asprise-Integrationen benötigen. Das Entfernen dieser Abhängigkeit beseitigt ein Lizenzproblem, reduziert den Build-Fußabdruck und setzt die Preprocessing-Konfiguration direkt neben die OCR-Konfiguration in derselben Code-Datei. Die Preprocessing-Features-Seite und der Leitfaden zur Bildqualitätskorrektur behandeln, wann jeder Filter angewendet werden soll und die messbaren Zuverlässigkeitsgewinne, die jeder bei minderwertigen Scans liefert.

Natives Async und echte Parallelität verbessern den Durchsatz. ReadAsync integriert sich in das standardmäßige async/await Muster ohne Threadpool-Blockierung. Paralleles Batch-Processing mit Parallel.ForEach oder PLINQ skaliert linear mit den verfügbaren Kernen. Ein Dokumentenstapel, der von Asprise Lite/STANDARD zur sequenziellen Verarbeitung gezwungen wurde – 100 Dokumente à 2 Sekunden benötigen über 3 Minuten – wird auf einem 8-Kern-Rechner mit IronOCR in etwa 25 Sekunden verarbeitet. Das Multithreading-Beispiel zeigt parallele Durchsatzmuster und erklärt, wie ConcurrentBag für threadsichere Ergebnissammlungen genutzt wird.

125+ Sprachen ohne Binärverteilung. Sprachpakete werden als NuGet-Pakete installiert - dotnet add package IronOcr.Languages.Arabic, dotnet add package IronOcr.Languages.Japanese - und werden mit der Anwendung wie jede andere Abhängigkeit bereitgestellt. Es muss kein manueller Tessdata-Ordner angelegt, keine Sprachdatei gesucht und keine Pfadkonfiguration auf dem Zielrechner vorgenommen werden. Der Sprachindex listet alle über 125 verfügbaren Sprachpakete auf.

Hinweis:Asprise OCR, PDFSharp, Tesseract und iText sind eingetragene Marken ihrer jeweiligen Eigentümer. Diese Seite ist nicht verbunden, anerkannt oder gesponsert von Asprise, Google, empira Software GmbH oder iText Group. Alle Produktnamen, Logos und Marken sind Eigentum ihrer jeweiligen Inhaber. Vergleiche dienen nur zu Informationszwecken und spiegeln öffentlich zugängliche Informationen zum Zeitpunkt des Schreibens wider.

Häufig gestellte Fragen

Warum sollte ich von Asprise OCR SDK zu IronOCR migrieren?

Zu den häufigsten Gründen gehören die Beseitigung der Komplexität der COM-Interoperabilität, die Ablösung der dateibasierten Lizenzverwaltung, die Vermeidung der seitenweisen Abrechnung, die Ermöglichung der Docker-/Container-Bereitstellung und die Einführung eines NuGet-nativen Workflows, der sich in die Standard-.NET-Werkzeuge integriert.

Was sind die wichtigsten Code-Änderungen bei der Migration von Asprise OCR SDK zu IronOCR?

Ersetzen Sie die Initialisierungssequenzen von Asprise OCR durch IronTesseract-Instanziierung, entfernen Sie das COM-Lebenszyklusmanagement (explizite Create/Load/Close-Muster) und aktualisieren Sie die Namen der Ergebniseigenschaften. Das Ergebnis sind deutlich weniger Boilerplate-Zeilen.

Wie installiere ich IronOCR, um die Migration zu beginnen?

Führen Sie 'Install-Package IronOcr' in der Paketmanager-Konsole oder 'dotnet add package IronOcr' in der CLI aus. Sprachpakete sind separate Pakete: 'dotnet add package IronOcr.Languages.French' für Französisch, zum Beispiel.

Kann IronOCR die OCR-Genauigkeit von Asprise OCR SDK für Standard-Geschäftsdokumente erreichen?

IronOCR erzielt eine hohe Genauigkeit bei Standardgeschäftsinhalten wie Rechnungen, Verträgen, Quittungen und getippten Formularen. Bildvorverarbeitungsfilter (Schräglagenkorrektur, Rauschunterdrückung, Kontrastverbesserung) verbessern die Erkennungsgenauigkeit bei verschlechterten Eingaben weiter.

Wie geht IronOCR mit den Sprachdaten um, die von Asprise OCR SDK separat installiert werden?

Die Sprachdaten in IronOCR werden als NuGet-Pakete verteilt. mit 'dotnet add package IronOcr.Languages.German' wird die deutsche Unterstützung installiert. Es sind keine manuellen Dateiplatzierungen oder Verzeichnispfade erforderlich.

Erfordert die Migration von Asprise OCR SDK zu IronOCR Änderungen an der Bereitstellungsinfrastruktur?

IronOCR erfordert weniger Änderungen an der Infrastruktur als Asprise OCR SDK. Es gibt keine SDK-Binärpfade, keine Platzierung von Lizenzdateien oder Lizenzserverkonfigurationen. Das NuGet-Paket enthält die komplette OCR-Engine, und der Lizenzschlüssel ist ein String, der im Anwendungscode festgelegt wird.

Wie konfiguriere ich die IronOCR-Lizenzierung nach der Migration?

Weisen Sie IronOcr.License.LicenseKey = "YOUR-KEY" im Startup-Code der Anwendung zu. In Docker oder Kubernetes speichern Sie den Schlüssel als Umgebungsvariable und lesen ihn beim Starten aus. Verwenden Sie License.IsValidLicense zur Validierung, bevor Sie den Datenverkehr akzeptieren.

Kann IronOCR PDFs auf die gleiche Weise verarbeiten wie Asprise OCR?

Ja, IronOCR liest sowohl native als auch gescannte PDFs. Instanziieren Sie IronTesseract, rufen Sie ocr.Read(input) auf, wobei input ein PDF-Pfad oder OcrPdfInput ist, und iterieren Sie die OcrResult-Seiten. Es ist keine separate PDF-Rendering-Pipeline erforderlich.

Wie handhabt IronOCR das Threading bei der Verarbeitung großer Datenmengen?

IronTesseract kann sicher pro Thread instanziiert werden. Sie können eine Instanz pro Thread in einem Parallel.ForEach- oder Task-Pool aufsetzen, OCR gleichzeitig ausführen und jede Instanz nach Abschluss entsorgen. Es ist kein globaler Zustand oder Sperren erforderlich.

Welche Ausgabeformate unterstützt IronOCR nach der Textextraktion?

IronOCR liefert strukturierte Ergebnisse mit Text, Wortkoordinaten, Konfidenzwerten und Seitenstruktur. Zu den Exportoptionen gehören reiner Text, durchsuchbare PDF-Dateien und strukturierte Ergebnisobjekte für die nachgeschaltete Verarbeitung.

Ist die Preisgestaltung von IronOCR berechenbarer als die von Asprise OCR SDK für die Skalierung von Arbeitslasten?

IronOCR verwendet eine pauschale, unbefristete Lizenzierung ohne Seiten- oder Volumengebühren. Egal, ob Sie 10.000 oder 10 Millionen Seiten verarbeiten, die Lizenzkosten bleiben konstant. Optionen für Volumen- und Teamlizenzen finden Sie auf der IronOCR-Preisseite.

Was passiert mit meinen bestehenden Tests, nachdem ich von Asprise OCR SDK zu IronOCR migriert habe?

Tests, die extrahierte Textinhalte überprüfen, sollten auch nach der Migration bestehen. Tests, die API-Aufrufmuster oder den Lebenszyklus von COM-Objekten validieren, müssen aktualisiert werden, um das einfachere Initialisierungs- und Ergebnismodell von IronOCR widerzuspiegeln.

Kannaopat Udonpant
Software Ingenieur
Bevor er Software-Ingenieur wurde, absolvierte Kannapat ein PhD in Umweltressourcen an der Hokkaido University in Japan. Während seines Studiums wurde Kannapat auch Mitglied des Vehicle Robotics Laboratory, das Teil der Fakultät für Bioproduktionstechnik ist. Im Jahr 2022 nutzte er seine C#-Kenntnisse, um dem Engineering-Team von Iron Software ...
Weiterlesen

Iron-Support-Team

Wir sind 24 Stunden am Tag, 5 Tage die Woche online.
Chat
E-Mail
Rufen Sie mich an