Zum Fußzeileninhalt springen
VIDEOS

Wie man arabischen Text aus Bildern mit OCR-Tools extrahiert

Dieser Leitfaden führt .NET -Entwickler durch eine vollständige Migration von GdPicture .NET OCR zu IronOCR . Es behandelt den Pakettausch, Namensraumänderungen und praktische Vorher/Nachher-Codemuster für jeden wichtigen OCR-Workflow, mit besonderem Fokus auf die Eliminierung des ganzzahligen Bild-ID-Lebenszyklus, der das Ressourcenverwaltungsmodell von GdPicture definiert. Das vorherige Lesen des Vergleichsartikels ist nicht erforderlich.

Warum von GdPicture .NET migrieren?

GdPicture .NET ist eine Dokumentenverarbeitungsplattform, die für Teams entwickelt wurde, die Scannerintegration, DICOM-Unterstützung, PDF-Bearbeitung, Annotation und OCR von einem einzigen Anbieter benötigen. Wenn OCR die einzige Anforderung ist, erzeugen die Preisgestaltung und die API-Architektur der Plattform Reibungsverluste, die sich im Laufe der Zeit summieren.

Kosten für ein einfaches OCR-Workflow-Plugin. Um Text aus gescannten PDFs zu extrahieren und durchsuchbare Ergebnisse zu generieren, werden drei separate Lizenzkomponenten benötigt: das Core SDK für ca. 4.000 US-Dollar, das OCR-Plugin für ca. 2.000 US-Dollar und das PDF-Plugin für ca. 2.000 US-Dollar. Die Einstiegskosten belaufen sich somit auf 8.000 US-Dollar Plus 20 % jährlicher Wartungsgebühren. Teams, die lediglich OCR benötigen, tragen die volle Preisstruktur einer Dokumentenverarbeitungsplattform.IronOCR umfasst denselben Workflow – Bild-OCR, PDF-OCR, Vorverarbeitung, durchsuchbare PDF-Ausgabe – aus einem einzigen Paket zu $999 bis $2.999 unbefristet, ohne Entscheidungen zur Lizenzierung einzelner Funktionen. Eine vollständige Aufschlüsselung der Lizenzstufen finden Sie auf der IronOCR -Lizenzseite .

Der Lebenszyklus der Ganzzahl-Bild-ID. Jedes über GdPicture geladene Bild gibt eine int zurück. Sie übergeben diese Ganzzahl an OCR-Operationen und rufen dann ReleaseGdPictureImage auf, wenn Sie fertig sind. Dieses Muster ist älter als IDisposable. Es funktioniert, wenn man es richtig befolgt; Es verursacht Speicherlecks, wenn es nicht erkannt wird. Bei Produktionsdiensten, die täglich Hunderte von Dokumenten verarbeiten, führt ein einziger verpasster Freigabeaufruf in einem Fehlerzweig zu einem Speicheranstieg, der sich nur schwer diagnostizieren lässt. IronOCR's OcrInput implementiert IDisposable — eine using-Anweisung eliminiert die gesamte Reinigungsbelastung.

Versionsspezifisches Namespace. GdPicture bettet die Hauptversionsnummer in sein Namespace ein: using GdPicture14. Ein Upgrade auf die nächste Hauptversion erfordert die Aktualisierung dieser using Direktive in jeder Quelldatei, die auf GdPicture-Klassen verweist. Bei einer großen Anwendung, bei der OCR über Dutzende von Diensten verteilt ist, wird daraus eine mehrstündige Such- und Ersetzungsaufgabe, die keine funktionale Verbesserung bringt. IronOCRs Namespace wurde bei allen Hauptversionen IronOcr.

Anforderung an den externen Ressourcenordner. GdPicture OCR erfordert eine ResourceFolder Eigenschaft, die zur Laufzeit auf ein Verzeichnis von .traineddata Sprachdateien verweist. Dieser Pfad funktioniert auf einer Entwicklungsmaschine, bricht jedoch auf Linux-Servern, Docker-Containern und Azure App Service-Bereitstellungen, wo die Verzeichnisstruktur nicht existiert.IronOCR bündelt den englischen Sprachsupport im NuGet-Paket; Zusätzliche Sprachen werden als NuGet Pakete installiert, die mit dem Build-Output übertragen werden.

Drei-Komponenten-Initialisierung. Ein PDF-OCR-Workflow in GdPicture erfordert die Instanziierung von GdPictureImaging, GdPictureOCR und GdPicturePDF — drei separate Komponenten mit individuellen Entsorgungsanforderungen — sowie die Lizenzmanagerregistrierung und die Zuweisung des Ressourcenordners.IronOCR benötigt beim Start eine Zeile und bei jedem Aufruf eine Klasse.

Keine native Thread-Sicherheit. GdPicture OCR-Instanzen sind nicht threadsicher. Die parallele Dokumentenverarbeitung erfordert ein sorgfältiges Instanzmanagement und eine präzise Synchronisierung, um Datenbeschädigungen zu vermeiden.IronOCR ist für den gleichzeitigen Gebrauch konzipiert: Erstellen Sie einen IronTesseract pro Thread oder teilen Sie eine einzelne Instanz unter Last — beide Muster funktionieren ohne zusätzlichen Synchronisationscode.

Das grundsätzliche Problem

GdPicture reserviert für jedes Bild einen Speicherwert als Laufzeit-verwalteten Integer-Handle. Jeder RenderPageToGdPictureImage-Aufruf in einer TIFF-Verarbeitungsschleife erstellt eine neue Zuweisung, die manuell freigegeben werden muss:

// GdPicture: every frame = new integer ID = manual release required
using var pdf = new GdPicturePDF();
pdf.LoadFromFile("multi-page.tiff", false);

var frameIds = new List<int>();
try
{
    for (int i = 1; i <= pdf.GetPageCount(); i++)
    {
        pdf.SelectPage(i);
        int frameId = pdf.RenderPageToGdPictureImage(200, false); // new allocation
        if (frameId != 0) frameIds.Add(frameId);
        // ... OCR call here ...
    }
}
finally
{
    foreach (var id in frameIds) _imaging.ReleaseGdPictureImage(id); // manual per-frame release
}
// GdPicture: every frame = new integer ID = manual release required
using var pdf = new GdPicturePDF();
pdf.LoadFromFile("multi-page.tiff", false);

var frameIds = new List<int>();
try
{
    for (int i = 1; i <= pdf.GetPageCount(); i++)
    {
        pdf.SelectPage(i);
        int frameId = pdf.RenderPageToGdPictureImage(200, false); // new allocation
        if (frameId != 0) frameIds.Add(frameId);
        // ... OCR call here ...
    }
}
finally
{
    foreach (var id in frameIds) _imaging.ReleaseGdPictureImage(id); // manual per-frame release
}
Imports System.Collections.Generic

' GdPicture: every frame = new integer ID = manual release required
Using pdf As New GdPicturePDF()
    pdf.LoadFromFile("multi-page.tiff", False)

    Dim frameIds As New List(Of Integer)()
    Try
        For i As Integer = 1 To pdf.GetPageCount()
            pdf.SelectPage(i)
            Dim frameId As Integer = pdf.RenderPageToGdPictureImage(200, False) ' new allocation
            If frameId <> 0 Then frameIds.Add(frameId)
            ' ... OCR call here ...
        Next
    Finally
        For Each id In frameIds
            _imaging.ReleaseGdPictureImage(id) ' manual per-frame release
        Next
    End Try
End Using
$vbLabelText   $csharpLabel

IronOCR eliminiert den Lebenszyklus vollständig. OcrInput behandelt die Rahmennummerierung und -bereinigung:

// IronOCR: the using statement handles everything
using var input = new OcrInput();
input.LoadImageFrames("multi-page.tiff");
var result = new IronTesseract().Read(input);
// IronOCR: the using statement handles everything
using var input = new OcrInput();
input.LoadImageFrames("multi-page.tiff");
var result = new IronTesseract().Read(input);
Imports IronOcr

Dim input As New OcrInput()
Using input
    input.LoadImageFrames("multi-page.tiff")
    Dim result = New IronTesseract().Read(input)
End Using
$vbLabelText   $csharpLabel

IronOCR vs. GdPicture .NET: Funktionsvergleich

Die folgende Tabelle vergleicht die Funktionsabdeckung der beiden Bibliotheken für OCR-orientierte Arbeitsabläufe.

Feature GdPicture.NET IronOCR
Installation Mehrere NuGet Pakete dotnet add package IronOcr
Lizenzaktivierung LicenseManager.RegisterKEY() IronOcr.License.LicenseKey = "..."
Namespace bei größerem Upgrade Erfordert Suchen-und-Ersetzen (GdPicture14 → weiter) Unverändert (IronOcr)
Komponenteninitialisierung GdPictureImaging + GdPictureOCR + GdPicturePDF new IronTesseract()
Ressourcenspeichermodell Manuelle Verfolgung und Freigabe von Ganzzahl-IDs IDisposable / using Anweisung
Risiko eines Speicherlecks Hoch (fehlend ReleaseGdPictureImage) Keine (compiler-erzwungen über using)
Externer Ressourcenordner Erforderlich (_ocr.ResourceFolder = path) Nicht erforderlich – im Paket enthalten
Bild-OCR Ja Ja
PDF-OCR Ja (PDF-Plugin erforderlich) Integriert, keine zusätzliche Lizenz erforderlich
Mehrseitiges TIFF Manuelle Frame-Schleife + Bereinigung der Frame-ID input.LoadImageFrames()
Stream-Eingabe Über GdPictureImaging Strom überladen input.LoadImage(stream)
Durchsuchbare PDF-Ausgabe pdf.OcrPage() + pdf.SaveToFile() result.SaveAsSearchablePdf()
Vorverarbeitung des Entzerrens Plugin für Dokumentenverarbeitung erforderlich input.Deskew() — eingebaut
Geräuschentfernung Plugin für Dokumentenverarbeitung erforderlich input.DeNoise() — eingebaut
Sprachen Tesseract-basierte Trainingsdatendateien im Ordner Mehr als 125 über NuGet -Pakete
Mehrsprachige OCR Ja OcrLanguage.French + OcrLanguage.German
Thread-Sicherheit Manuelle Instanzverwaltung Thread-sicher durch Design
Asynchrone OCR Nicht eingebaut ReadAsync()
Barcode-Lesung Separates Barcode-Plugin ocr.Configuration.ReadBarCodes = true
Strukturierte Ausgabe Indexbasierter Block-/Zeilen-/Wortzugriff Typisiert .Pages, .Words, .Characters
Konfidenzbewertung GetOCRResultConfidence(resultId) result.Confidence
Plattformübergreifend Windows, Linux, macOS Windows, Linux, macOS, Docker, AWS, Azure
Eingabekosten (OCR aus PDFs) ~8.000 $ (Kernsoftware + OCR + PDF-Plugins) $999–$2.999
Preismodell Plugin-basierte, unbefristete Lizenz + 20 %/Jahr Wartung Feste, unbefristete Gebühr, optionale jährliche Aktualisierungen
Kommerzielle Unterstützung Ja Ja

Schnellstart: Migration von GdPicture .NET zu IronOCR

Schritt 1: Ersetzen des NuGet-Pakets

Entfernen Sie die GdPicture-Pakete:

dotnet remove package GdPicture.NET
dotnet remove package GdPicture.NET.OCR
dotnet remove package GdPicture.NET.PDF
dotnet remove package GdPicture.NET
dotnet remove package GdPicture.NET.OCR
dotnet remove package GdPicture.NET.PDF
SHELL

Installieren Sie IronOCR von der NuGet Paketseite :

dotnet add package IronOcr

Für weitere Sprachen als Englisch installieren Sie bitte das entsprechende Sprachpaket:

dotnet add package IronOcr.Languages.French, IronOcr.Languages.German

Schritt 2: Namespaces aktualisieren

Ersetzen Sie den GdPicture-Namensraum durch den IronOCR Namensraum:

// Before (GdPicture)
using GdPicture14;

// After (IronOCR)
using IronOcr;
// Before (GdPicture)
using GdPicture14;

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

Schritt 3: Lizenz initialisieren

Platzieren Sie diese Zeile in Program.cs oder Startup.cs, vor allen OCR-Aufrufen:

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

Entfernen Sie die GdPicture-Lizenzregistrierungssperre vollständig:

// Remove this
LicenseManager lm = new LicenseManager();
lm.RegisterKEY("GDPICTURE-LICENSE-KEY");
// Remove this
LicenseManager lm = new LicenseManager();
lm.RegisterKEY("GDPICTURE-LICENSE-KEY");
$vbLabelText   $csharpLabel

Auf der IronOCR -Produktseite ist ein kostenloser Testschlüssel zum Ausprobieren vor dem Kauf erhältlich.

Beispiele für die Code-Migration

Verarbeitung mehrseitiger TIFF-Frames

Die Verarbeitung mehrseitiger TIFF-Dateien in GdPicture erfordert die Auswahl jedes einzelnen Frames über die PDF/imaging-API, das Rendern zu einer neuen Bild-ID, die Durchführung der OCR-Texterkennung und die Freigabe der ID. Ein einzelner Rahmen, der im finally-Block nicht freigegeben wird, leckt 10–50 MB, je nach DPI.

GdPicture .NET -Ansatz:

using GdPicture14;

public class GdPictureTiffProcessor
{
    private readonly GdPictureImaging _imaging;
    private readonly GdPictureOCR _ocr;

    public string ExtractTextFromTiff(string tiffPath)
    {
        var text = new StringBuilder();

        // Load TIFF through the imaging component
        int tiffId = _imaging.CreateGdPictureImageFromFile(tiffPath);

        if (tiffId == 0)
            throw new Exception($"TIFF load failed: {_imaging.GetStat()}");

        // Outer try: release the original TIFF handle
        try
        {
            int frameCount = _imaging.GetPageCount(tiffId);

            for (int i = 1; i <= frameCount; i++)
            {
                // Switch to frame — modifies the existing ID in place
                _imaging.SelectPage(tiffId, i);

                // Clone frame to a new image ID for OCR
                int frameId = _imaging.CloneImage(tiffId);

                if (frameId == 0) continue;

                // Inner try: release each cloned frame ID
                try
                {
                    _ocr.SetImage(frameId);
                    _ocr.Language = "eng";

                    string resultId = _ocr.RunOCR();

                    if (!string.IsNullOrEmpty(resultId))
                    {
                        text.AppendLine($"[Frame {i}] {_ocr.GetOCRResultText(resultId)}");
                    }
                }
                finally
                {
                    // Release cloned frame — critical for each iteration
                    _imaging.ReleaseGdPictureImage(frameId);
                }
            }
        }
        finally
        {
            // Release original TIFF handle
            _imaging.ReleaseGdPictureImage(tiffId);
        }

        return text.ToString();
    }
}
using GdPicture14;

public class GdPictureTiffProcessor
{
    private readonly GdPictureImaging _imaging;
    private readonly GdPictureOCR _ocr;

    public string ExtractTextFromTiff(string tiffPath)
    {
        var text = new StringBuilder();

        // Load TIFF through the imaging component
        int tiffId = _imaging.CreateGdPictureImageFromFile(tiffPath);

        if (tiffId == 0)
            throw new Exception($"TIFF load failed: {_imaging.GetStat()}");

        // Outer try: release the original TIFF handle
        try
        {
            int frameCount = _imaging.GetPageCount(tiffId);

            for (int i = 1; i <= frameCount; i++)
            {
                // Switch to frame — modifies the existing ID in place
                _imaging.SelectPage(tiffId, i);

                // Clone frame to a new image ID for OCR
                int frameId = _imaging.CloneImage(tiffId);

                if (frameId == 0) continue;

                // Inner try: release each cloned frame ID
                try
                {
                    _ocr.SetImage(frameId);
                    _ocr.Language = "eng";

                    string resultId = _ocr.RunOCR();

                    if (!string.IsNullOrEmpty(resultId))
                    {
                        text.AppendLine($"[Frame {i}] {_ocr.GetOCRResultText(resultId)}");
                    }
                }
                finally
                {
                    // Release cloned frame — critical for each iteration
                    _imaging.ReleaseGdPictureImage(frameId);
                }
            }
        }
        finally
        {
            // Release original TIFF handle
            _imaging.ReleaseGdPictureImage(tiffId);
        }

        return text.ToString();
    }
}
Imports GdPicture14
Imports System.Text

Public Class GdPictureTiffProcessor
    Private ReadOnly _imaging As GdPictureImaging
    Private ReadOnly _ocr As GdPictureOCR

    Public Function ExtractTextFromTiff(tiffPath As String) As String
        Dim text As New StringBuilder()

        ' Load TIFF through the imaging component
        Dim tiffId As Integer = _imaging.CreateGdPictureImageFromFile(tiffPath)

        If tiffId = 0 Then
            Throw New Exception($"TIFF load failed: {_imaging.GetStat()}")
        End If

        ' Outer try: release the original TIFF handle
        Try
            Dim frameCount As Integer = _imaging.GetPageCount(tiffId)

            For i As Integer = 1 To frameCount
                ' Switch to frame — modifies the existing ID in place
                _imaging.SelectPage(tiffId, i)

                ' Clone frame to a new image ID for OCR
                Dim frameId As Integer = _imaging.CloneImage(tiffId)

                If frameId = 0 Then Continue For

                ' Inner try: release each cloned frame ID
                Try
                    _ocr.SetImage(frameId)
                    _ocr.Language = "eng"

                    Dim resultId As String = _ocr.RunOCR()

                    If Not String.IsNullOrEmpty(resultId) Then
                        text.AppendLine($"[Frame {i}] {_ocr.GetOCRResultText(resultId)}")
                    End If
                Finally
                    ' Release cloned frame — critical for each iteration
                    _imaging.ReleaseGdPictureImage(frameId)
                End Try
            Next
        Finally
            ' Release original TIFF handle
            _imaging.ReleaseGdPictureImage(tiffId)
        End Try

        Return text.ToString()
    End Function
End Class
$vbLabelText   $csharpLabel

IronOCR Ansatz:

using IronOcr;

public class IronOcrTiffProcessor
{
    public string ExtractTextFromTiff(string tiffPath)
    {
        using var input = new OcrInput();
        input.LoadImageFrames(tiffPath);  // all frames loaded, all cleanup automatic

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

        // Per-frame text is available on result.Pages
        foreach (var page in result.Pages)
            Console.WriteLine($"[Frame {page.PageNumber}] {page.Text}");

        return result.Text;
    }
}
using IronOcr;

public class IronOcrTiffProcessor
{
    public string ExtractTextFromTiff(string tiffPath)
    {
        using var input = new OcrInput();
        input.LoadImageFrames(tiffPath);  // all frames loaded, all cleanup automatic

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

        // Per-frame text is available on result.Pages
        foreach (var page in result.Pages)
            Console.WriteLine($"[Frame {page.PageNumber}] {page.Text}");

        return result.Text;
    }
}
Imports IronOcr

Public Class IronOcrTiffProcessor
    Public Function ExtractTextFromTiff(tiffPath As String) As String
        Using input As New OcrInput()
            input.LoadImageFrames(tiffPath) ' all frames loaded, all cleanup automatic

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

            ' Per-frame text is available on result.Pages
            For Each page In result.Pages
                Console.WriteLine($"[Frame {page.PageNumber}] {page.Text}")
            Next

            Return result.Text
        End Using
    End Function
End Class
$vbLabelText   $csharpLabel

LoadImageFrames lädt alle Rahmen aus einem mehrseitigen TIFF in die OcrInput Pipeline. Der using-Block behandelt den gesamten Speicher, der mit jedem Rahmen am Ende des Bereichs verbunden ist. Kein List<int> zu warten, keine verschachtelten try/finally Blöcke erforderlich. Der Leitfaden zur Eingabe von TIFF- und GIF-Dateien behandelt die Auswahl der Einzelbilder und die Handhabung mehrerer Formate im Detail.

Streambasierte Eingabe ersetzt Plugin-Initialisierung

Serveranwendungen empfangen Dokumente häufig als Datenströme anstatt als Dateipfade – beispielsweise durch HTTP-Uploads, Message Queues oder Datenbank-Blobs. GdPicture erfordert das Laden des Streams über GdPictureImaging, was selbst die Initialisierungssequenz der Komponente und die Ressourcenordnerkonfiguration erfordert, die jeder Operation vorausgeht.

GdPicture .NET -Ansatz:

using GdPicture14;

public class GdPictureStreamOcr : IDisposable
{
    private readonly GdPictureImaging _imaging;
    private readonly GdPictureOCR _ocr;

    public GdPictureStreamOcr()
    {
        // Plugin initialization required before stream loading is possible
        var lm = new LicenseManager();
        lm.RegisterKEY("GDPICTURE-LICENSE-KEY");

        _imaging = new GdPictureImaging();
        _ocr = new GdPictureOCR();
        _ocr.ResourceFolder = @"C:\GdPicture\Resources\OCR"; // path must exist at runtime
    }

    public string ExtractTextFromStream(Stream documentStream)
    {
        // Load stream into imaging component to get an image ID
        int imageId = _imaging.CreateGdPictureImageFromStream(documentStream);

        if (imageId == 0)
            throw new Exception($"Stream load failed: {_imaging.GetStat()}");

        try
        {
            _ocr.SetImage(imageId);
            _ocr.Language = "eng";

            string resultId = _ocr.RunOCR();

            if (string.IsNullOrEmpty(resultId))
                throw new Exception($"OCR failed: {_ocr.GetStat()}");

            return _ocr.GetOCRResultText(resultId);
        }
        finally
        {
            _imaging.ReleaseGdPictureImage(imageId);
        }
    }

    public void Dispose()
    {
        _ocr?.Dispose();
        _imaging?.Dispose();
    }
}
using GdPicture14;

public class GdPictureStreamOcr : IDisposable
{
    private readonly GdPictureImaging _imaging;
    private readonly GdPictureOCR _ocr;

    public GdPictureStreamOcr()
    {
        // Plugin initialization required before stream loading is possible
        var lm = new LicenseManager();
        lm.RegisterKEY("GDPICTURE-LICENSE-KEY");

        _imaging = new GdPictureImaging();
        _ocr = new GdPictureOCR();
        _ocr.ResourceFolder = @"C:\GdPicture\Resources\OCR"; // path must exist at runtime
    }

    public string ExtractTextFromStream(Stream documentStream)
    {
        // Load stream into imaging component to get an image ID
        int imageId = _imaging.CreateGdPictureImageFromStream(documentStream);

        if (imageId == 0)
            throw new Exception($"Stream load failed: {_imaging.GetStat()}");

        try
        {
            _ocr.SetImage(imageId);
            _ocr.Language = "eng";

            string resultId = _ocr.RunOCR();

            if (string.IsNullOrEmpty(resultId))
                throw new Exception($"OCR failed: {_ocr.GetStat()}");

            return _ocr.GetOCRResultText(resultId);
        }
        finally
        {
            _imaging.ReleaseGdPictureImage(imageId);
        }
    }

    public void Dispose()
    {
        _ocr?.Dispose();
        _imaging?.Dispose();
    }
}
IRON VB CONVERTER ERROR developers@ironsoftware.com
$vbLabelText   $csharpLabel

IronOCR Ansatz:

using IronOcr;

public class IronOcrStreamOcr
{
    public string ExtractTextFromStream(Stream documentStream)
    {
        using var input = new OcrInput();
        input.LoadImage(documentStream);  // stream accepted directly — no imaging component

        return new IronTesseract().Read(input).Text;
    }
}
using IronOcr;

public class IronOcrStreamOcr
{
    public string ExtractTextFromStream(Stream documentStream)
    {
        using var input = new OcrInput();
        input.LoadImage(documentStream);  // stream accepted directly — no imaging component

        return new IronTesseract().Read(input).Text;
    }
}
Imports IronOcr

Public Class IronOcrStreamOcr
    Public Function ExtractTextFromStream(documentStream As Stream) As String
        Using input As New OcrInput()
            input.LoadImage(documentStream) ' stream accepted directly — no imaging component

            Return New IronTesseract().Read(input).Text
        End Using
    End Function
End Class
$vbLabelText   $csharpLabel

Der GdPicture-Ansatz erfordert die Erstellung von drei Objekten und die Konfiguration eines Dateisystempfads, bevor der erste Datenstrom verarbeitet werden kann.IronOCR akzeptiert den Stream direkt auf OcrInput ohne vorherige Einrichtung. Der Stream Input Guide deckt Byte-Array, MemoryStream und FileStream-Muster für Pipeline-Architekturen ab, wo temporäre Dateischreibvorgänge unerwünscht sind.

Asynchrone OCR ersetzt Statuscode-Abfrage

GdPicture OCR ist synchron. Anwendungen, die Dokumente in ASP.NET Core-Endpunkten oder Hintergrunddiensten verarbeiten, müssen RunOCR in Task.Run einwickeln, um Anfragethreads nicht zu blockieren – und den Bild-ID-Lebenszyklus über die Thread-Grenze verwalten.IronOCR bietet durch ReadAsync erstklassige asynchrone Unterstützung.

GdPicture .NET -Ansatz:

using GdPicture14;
using System.Threading.Tasks;

public class GdPictureAsyncWrapper
{
    private readonly GdPictureImaging _imaging;
    private readonly GdPictureOCR _ocr;
    private readonly SemaphoreSlim _lock = new SemaphoreSlim(1, 1);

    public async Task<string> ExtractTextAsync(string imagePath)
    {
        // Must acquire lock: GdPictureOCR is not thread-safe
        await _lock.WaitAsync();

        try
        {
            return await Task.Run(() =>
            {
                int imageId = _imaging.CreateGdPictureImageFromFile(imagePath);

                if (imageId == 0)
                    throw new Exception($"Load failed: {_imaging.GetStat()}");

                try
                {
                    _ocr.SetImage(imageId);
                    _ocr.Language = "eng";

                    string resultId = _ocr.RunOCR();

                    if (string.IsNullOrEmpty(resultId))
                        throw new Exception($"OCR failed: {_ocr.GetStat()}");

                    return _ocr.GetOCRResultText(resultId);
                }
                finally
                {
                    _imaging.ReleaseGdPictureImage(imageId);
                }
            });
        }
        finally
        {
            _lock.Release();
        }
    }
}
using GdPicture14;
using System.Threading.Tasks;

public class GdPictureAsyncWrapper
{
    private readonly GdPictureImaging _imaging;
    private readonly GdPictureOCR _ocr;
    private readonly SemaphoreSlim _lock = new SemaphoreSlim(1, 1);

    public async Task<string> ExtractTextAsync(string imagePath)
    {
        // Must acquire lock: GdPictureOCR is not thread-safe
        await _lock.WaitAsync();

        try
        {
            return await Task.Run(() =>
            {
                int imageId = _imaging.CreateGdPictureImageFromFile(imagePath);

                if (imageId == 0)
                    throw new Exception($"Load failed: {_imaging.GetStat()}");

                try
                {
                    _ocr.SetImage(imageId);
                    _ocr.Language = "eng";

                    string resultId = _ocr.RunOCR();

                    if (string.IsNullOrEmpty(resultId))
                        throw new Exception($"OCR failed: {_ocr.GetStat()}");

                    return _ocr.GetOCRResultText(resultId);
                }
                finally
                {
                    _imaging.ReleaseGdPictureImage(imageId);
                }
            });
        }
        finally
        {
            _lock.Release();
        }
    }
}
Imports GdPicture14
Imports System.Threading.Tasks

Public Class GdPictureAsyncWrapper
    Private ReadOnly _imaging As GdPictureImaging
    Private ReadOnly _ocr As GdPictureOCR
    Private ReadOnly _lock As New SemaphoreSlim(1, 1)

    Public Async Function ExtractTextAsync(imagePath As String) As Task(Of String)
        ' Must acquire lock: GdPictureOCR is not thread-safe
        Await _lock.WaitAsync()

        Try
            Return Await Task.Run(Function()
                                      Dim imageId As Integer = _imaging.CreateGdPictureImageFromFile(imagePath)

                                      If imageId = 0 Then
                                          Throw New Exception($"Load failed: {_imaging.GetStat()}")
                                      End If

                                      Try
                                          _ocr.SetImage(imageId)
                                          _ocr.Language = "eng"

                                          Dim resultId As String = _ocr.RunOCR()

                                          If String.IsNullOrEmpty(resultId) Then
                                              Throw New Exception($"OCR failed: {_ocr.GetStat()}")
                                          End If

                                          Return _ocr.GetOCRResultText(resultId)
                                      Finally
                                          _imaging.ReleaseGdPictureImage(imageId)
                                      End Try
                                  End Function)
        Finally
            _lock.Release()
        End Try
    End Function
End Class
$vbLabelText   $csharpLabel

IronOCR Ansatz:

using IronOcr;

public class IronOcrAsyncService
{
    private readonly IronTesseract _ocr = new IronTesseract();

    public async Task<string> ExtractTextAsync(string imagePath)
    {
        // ReadAsync is natively async — no Task.Run wrapper, no lock required
        var result = await _ocr.ReadAsync(imagePath);
        return result.Text;
    }

    public async Task<string> ExtractFromStreamAsync(Stream stream)
    {
        using var input = new OcrInput();
        input.LoadImage(stream);

        var result = await _ocr.ReadAsync(input);
        return result.Text;
    }
}
using IronOcr;

public class IronOcrAsyncService
{
    private readonly IronTesseract _ocr = new IronTesseract();

    public async Task<string> ExtractTextAsync(string imagePath)
    {
        // ReadAsync is natively async — no Task.Run wrapper, no lock required
        var result = await _ocr.ReadAsync(imagePath);
        return result.Text;
    }

    public async Task<string> ExtractFromStreamAsync(Stream stream)
    {
        using var input = new OcrInput();
        input.LoadImage(stream);

        var result = await _ocr.ReadAsync(input);
        return result.Text;
    }
}
Imports IronOcr
Imports System.IO
Imports System.Threading.Tasks

Public Class IronOcrAsyncService
    Private ReadOnly _ocr As New IronTesseract()

    Public Async Function ExtractTextAsync(imagePath As String) As Task(Of String)
        ' ReadAsync is natively async — no Task.Run wrapper, no lock required
        Dim result = Await _ocr.ReadAsync(imagePath)
        Return result.Text
    End Function

    Public Async Function ExtractFromStreamAsync(stream As Stream) As Task(Of String)
        Using input As New OcrInput()
            input.LoadImage(stream)

            Dim result = Await _ocr.ReadAsync(input)
            Return result.Text
        End Using
    End Function
End Class
$vbLabelText   $csharpLabel

Der GdPicture-Ansatz erfordert einen SemaphoreSlim, um den Zugriff auf die gemeinsame GdPictureOCR-Instanz zu serialisieren, plus einen Task.Run, um synchrone blockierende Arbeiten vom aufrufenden Thread abseits zu bewegen, plus den gesamten Bild-ID-Lebenszyklus innerhalb dieses Lambdas. IronOCRs ReadAsync ist wirklich nicht blockierend und threadsicher. Der Leitfaden zur asynchronen OCR behandelt die Integration mit ASP.NET Core Middleware und gehosteten Hintergrunddiensten.

Parallele Stapelverarbeitung mit Thread-Sicherheit

Die schnellstmögliche Verarbeitung eines Ordners mit gescannten Dokumenten erfordert eine parallele Ausführung. GdPicture erfordert eine GdPictureOCR-Instanz pro Thread – das Teilen einer einzigen Instanz verursacht nicht-deterministische Fehler. Jede thread-spezifische Instanz erfordert auch ihre eigene GdPictureImaging-Komponente und Ressourcenkonfiguration, was Thread-Pool-Ansätze ohne ein Fabrikmuster unpraktisch macht.

GdPicture .NET -Ansatz:

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

public class GdPictureParallelBatch
{
    private readonly string _resourceFolder = @"C:\GdPicture\Resources\OCR";

    public ConcurrentDictionary<string, string> ProcessBatch(string[] imagePaths)
    {
        var results = new ConcurrentDictionary<string, string>();

        // Each thread must have its own component instances
        Parallel.ForEach(imagePaths, imagePath =>
        {
            // Create per-thread instances — shared instances cause failures
            using var threadImaging = new GdPictureImaging();
            using var threadOcr = new GdPictureOCR();
            threadOcr.ResourceFolder = _resourceFolder;

            // Re-register license per thread (may be required depending on SDK version)
            var lm = new LicenseManager();
            lm.RegisterKEY("GDPICTURE-LICENSE-KEY");

            int imageId = threadImaging.CreateGdPictureImageFromFile(imagePath);

            if (imageId == 0)
            {
                results[imagePath] = $"ERROR: {threadImaging.GetStat()}";
                return;
            }

            try
            {
                threadOcr.SetImage(imageId);
                threadOcr.Language = "eng";

                string resultId = threadOcr.RunOCR();
                results[imagePath] = string.IsNullOrEmpty(resultId)
                    ? $"ERROR: {threadOcr.GetStat()}"
                    : threadOcr.GetOCRResultText(resultId);
            }
            finally
            {
                threadImaging.ReleaseGdPictureImage(imageId);
            }
        });

        return results;
    }
}
using GdPicture14;
using System.Collections.Concurrent;
using System.Threading.Tasks;

public class GdPictureParallelBatch
{
    private readonly string _resourceFolder = @"C:\GdPicture\Resources\OCR";

    public ConcurrentDictionary<string, string> ProcessBatch(string[] imagePaths)
    {
        var results = new ConcurrentDictionary<string, string>();

        // Each thread must have its own component instances
        Parallel.ForEach(imagePaths, imagePath =>
        {
            // Create per-thread instances — shared instances cause failures
            using var threadImaging = new GdPictureImaging();
            using var threadOcr = new GdPictureOCR();
            threadOcr.ResourceFolder = _resourceFolder;

            // Re-register license per thread (may be required depending on SDK version)
            var lm = new LicenseManager();
            lm.RegisterKEY("GDPICTURE-LICENSE-KEY");

            int imageId = threadImaging.CreateGdPictureImageFromFile(imagePath);

            if (imageId == 0)
            {
                results[imagePath] = $"ERROR: {threadImaging.GetStat()}";
                return;
            }

            try
            {
                threadOcr.SetImage(imageId);
                threadOcr.Language = "eng";

                string resultId = threadOcr.RunOCR();
                results[imagePath] = string.IsNullOrEmpty(resultId)
                    ? $"ERROR: {threadOcr.GetStat()}"
                    : threadOcr.GetOCRResultText(resultId);
            }
            finally
            {
                threadImaging.ReleaseGdPictureImage(imageId);
            }
        });

        return results;
    }
}
Imports GdPicture14
Imports System.Collections.Concurrent
Imports System.Threading.Tasks

Public Class GdPictureParallelBatch
    Private ReadOnly _resourceFolder As String = "C:\GdPicture\Resources\OCR"

    Public Function ProcessBatch(imagePaths As String()) As ConcurrentDictionary(Of String, String)
        Dim results As New ConcurrentDictionary(Of String, String)()

        ' Each thread must have its own component instances
        Parallel.ForEach(imagePaths, Sub(imagePath)
            ' Create per-thread instances — shared instances cause failures
            Using threadImaging As New GdPictureImaging()
                Using threadOcr As New GdPictureOCR()
                    threadOcr.ResourceFolder = _resourceFolder

                    ' Re-register license per thread (may be required depending on SDK version)
                    Dim lm As New LicenseManager()
                    lm.RegisterKEY("GDPICTURE-LICENSE-KEY")

                    Dim imageId As Integer = threadImaging.CreateGdPictureImageFromFile(imagePath)

                    If imageId = 0 Then
                        results(imagePath) = $"ERROR: {threadImaging.GetStat()}"
                        Return
                    End If

                    Try
                        threadOcr.SetImage(imageId)
                        threadOcr.Language = "eng"

                        Dim resultId As String = threadOcr.RunOCR()
                        results(imagePath) = If(String.IsNullOrEmpty(resultId), $"ERROR: {threadOcr.GetStat()}", threadOcr.GetOCRResultText(resultId))
                    Finally
                        threadImaging.ReleaseGdPictureImage(imageId)
                    End Try
                End Using
            End Using
        End Sub)

        Return results
    End Function
End Class
$vbLabelText   $csharpLabel

IronOCR Ansatz:

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

public class IronOcrParallelBatch
{
    public ConcurrentDictionary<string, string> ProcessBatch(string[] imagePaths)
    {
        var results = new ConcurrentDictionary<string, string>();

        // IronTesseract is thread-safe — one instance handles all threads
        var ocr = new IronTesseract();

        Parallel.ForEach(imagePaths, imagePath =>
        {
            try
            {
                results[imagePath] = ocr.Read(imagePath).Text;
            }
            catch (Exception ex)
            {
                results[imagePath] = $"ERROR: {ex.Message}";
            }
        });

        return results;
    }
}
using IronOcr;
using System.Collections.Concurrent;
using System.Threading.Tasks;

public class IronOcrParallelBatch
{
    public ConcurrentDictionary<string, string> ProcessBatch(string[] imagePaths)
    {
        var results = new ConcurrentDictionary<string, string>();

        // IronTesseract is thread-safe — one instance handles all threads
        var ocr = new IronTesseract();

        Parallel.ForEach(imagePaths, imagePath =>
        {
            try
            {
                results[imagePath] = ocr.Read(imagePath).Text;
            }
            catch (Exception ex)
            {
                results[imagePath] = $"ERROR: {ex.Message}";
            }
        });

        return results;
    }
}
Imports IronOcr
Imports System.Collections.Concurrent
Imports System.Threading.Tasks

Public Class IronOcrParallelBatch
    Public Function ProcessBatch(imagePaths As String()) As ConcurrentDictionary(Of String, String)
        Dim results As New ConcurrentDictionary(Of String, String)()

        ' IronTesseract is thread-safe — one instance handles all threads
        Dim ocr As New IronTesseract()

        Parallel.ForEach(imagePaths, Sub(imagePath)
            Try
                results(imagePath) = ocr.Read(imagePath).Text
            Catch ex As Exception
                results(imagePath) = $"ERROR: {ex.Message}"
            End Try
        End Sub)

        Return results
    End Function
End Class
$vbLabelText   $csharpLabel

Die parallele Implementierung von GdPicture erzeugt drei Objekte pro Thread und erfordert eine Lizenzregistrierung pro Thread.IronOCR verarbeitet gleichzeitige Lesezugriffe von einer einzigen IronTesseract Instanz ohne Synchronisationsaufwand. Das Multithreading-Beispiel zeigt Durchsatz-Benchmarks und Parallel.ForEach Muster für Hochvolumen-Dokumentverarbeitungs-Workloads.

Byte-Array-Eingabe und Extraktion strukturierter Absätze

Anwendungen, die Dokumente aus Datenbanken oder Objektspeichern abrufen, arbeiten oft mit Byte-Arrays anstatt mit Dateipfaden. GdPicture erfordert die Umwandlung des Byte-Arrays in einen Stream und das Laden über GdPictureImaging. Um strukturierte Daten auf Absatzebene aus dem Ergebnis zu extrahieren, muss die Block-/Zeilenindexhierarchie durchsucht werden.

GdPicture .NET -Ansatz:

using GdPicture14;

public class GdPictureByteArrayOcr
{
    private readonly GdPictureImaging _imaging;
    private readonly GdPictureOCR _ocr;

    public List<string> ExtractParagraphsFromBytes(byte[] imageBytes)
    {
        var paragraphs = new List<string>();

        // Byte array must go through MemoryStream to reach CreateGdPictureImageFromStream
        using var ms = new MemoryStream(imageBytes);
        int imageId = _imaging.CreateGdPictureImageFromStream(ms);

        if (imageId == 0)
            throw new Exception($"Byte array load failed: {_imaging.GetStat()}");

        try
        {
            _ocr.SetImage(imageId);
            _ocr.Language = "eng";

            string resultId = _ocr.RunOCR();

            if (string.IsNullOrEmpty(resultId))
                throw new Exception($"OCR failed: {_ocr.GetStat()}");

            // Paragraph-level data requires iterating block structure
            int blockCount = _ocr.GetOCRResultBlockCount(resultId);

            for (int b = 0; b < blockCount; b++)
            {
                var blockText = new StringBuilder();
                int lineCount = _ocr.GetOCRResultBlockLineCount(resultId, b);

                for (int l = 0; l < lineCount; l++)
                {
                    int wordCount = _ocr.GetOCRResultBlockLineWordCount(resultId, b, l);

                    for (int w = 0; w < wordCount; w++)
                    {
                        blockText.Append(_ocr.GetOCRResultBlockLineWordText(resultId, b, l, w));
                        blockText.Append(" ");
                    }
                }

                string text = blockText.ToString().Trim();
                if (!string.IsNullOrEmpty(text))
                    paragraphs.Add(text);
            }
        }
        finally
        {
            _imaging.ReleaseGdPictureImage(imageId);
        }

        return paragraphs;
    }
}
using GdPicture14;

public class GdPictureByteArrayOcr
{
    private readonly GdPictureImaging _imaging;
    private readonly GdPictureOCR _ocr;

    public List<string> ExtractParagraphsFromBytes(byte[] imageBytes)
    {
        var paragraphs = new List<string>();

        // Byte array must go through MemoryStream to reach CreateGdPictureImageFromStream
        using var ms = new MemoryStream(imageBytes);
        int imageId = _imaging.CreateGdPictureImageFromStream(ms);

        if (imageId == 0)
            throw new Exception($"Byte array load failed: {_imaging.GetStat()}");

        try
        {
            _ocr.SetImage(imageId);
            _ocr.Language = "eng";

            string resultId = _ocr.RunOCR();

            if (string.IsNullOrEmpty(resultId))
                throw new Exception($"OCR failed: {_ocr.GetStat()}");

            // Paragraph-level data requires iterating block structure
            int blockCount = _ocr.GetOCRResultBlockCount(resultId);

            for (int b = 0; b < blockCount; b++)
            {
                var blockText = new StringBuilder();
                int lineCount = _ocr.GetOCRResultBlockLineCount(resultId, b);

                for (int l = 0; l < lineCount; l++)
                {
                    int wordCount = _ocr.GetOCRResultBlockLineWordCount(resultId, b, l);

                    for (int w = 0; w < wordCount; w++)
                    {
                        blockText.Append(_ocr.GetOCRResultBlockLineWordText(resultId, b, l, w));
                        blockText.Append(" ");
                    }
                }

                string text = blockText.ToString().Trim();
                if (!string.IsNullOrEmpty(text))
                    paragraphs.Add(text);
            }
        }
        finally
        {
            _imaging.ReleaseGdPictureImage(imageId);
        }

        return paragraphs;
    }
}
Imports GdPicture14
Imports System.IO
Imports System.Text

Public Class GdPictureByteArrayOcr
    Private ReadOnly _imaging As GdPictureImaging
    Private ReadOnly _ocr As GdPictureOCR

    Public Function ExtractParagraphsFromBytes(imageBytes As Byte()) As List(Of String)
        Dim paragraphs As New List(Of String)()

        ' Byte array must go through MemoryStream to reach CreateGdPictureImageFromStream
        Using ms As New MemoryStream(imageBytes)
            Dim imageId As Integer = _imaging.CreateGdPictureImageFromStream(ms)

            If imageId = 0 Then
                Throw New Exception($"Byte array load failed: {_imaging.GetStat()}")
            End If

            Try
                _ocr.SetImage(imageId)
                _ocr.Language = "eng"

                Dim resultId As String = _ocr.RunOCR()

                If String.IsNullOrEmpty(resultId) Then
                    Throw New Exception($"OCR failed: {_ocr.GetStat()}")
                End If

                ' Paragraph-level data requires iterating block structure
                Dim blockCount As Integer = _ocr.GetOCRResultBlockCount(resultId)

                For b As Integer = 0 To blockCount - 1
                    Dim blockText As New StringBuilder()
                    Dim lineCount As Integer = _ocr.GetOCRResultBlockLineCount(resultId, b)

                    For l As Integer = 0 To lineCount - 1
                        Dim wordCount As Integer = _ocr.GetOCRResultBlockLineWordCount(resultId, b, l)

                        For w As Integer = 0 To wordCount - 1
                            blockText.Append(_ocr.GetOCRResultBlockLineWordText(resultId, b, l, w))
                            blockText.Append(" "c)
                        Next
                    Next

                    Dim text As String = blockText.ToString().Trim()
                    If Not String.IsNullOrEmpty(text) Then
                        paragraphs.Add(text)
                    End If
                Next
            Finally
                _imaging.ReleaseGdPictureImage(imageId)
            End Try
        End Using

        Return paragraphs
    End Function
End Class
$vbLabelText   $csharpLabel

IronOCR Ansatz:

using IronOcr;

public class IronOcrByteArrayOcr
{
    public List<string> ExtractParagraphsFromBytes(byte[] imageBytes)
    {
        using var input = new OcrInput();
        input.LoadImage(imageBytes);  // byte array accepted directly

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

        // Paragraphs are a first-class typed collection
        return result.Paragraphs
            .Select(p => p.Text)
            .Where(t => !string.IsNullOrWhiteSpace(t))
            .ToList();
    }
}
using IronOcr;

public class IronOcrByteArrayOcr
{
    public List<string> ExtractParagraphsFromBytes(byte[] imageBytes)
    {
        using var input = new OcrInput();
        input.LoadImage(imageBytes);  // byte array accepted directly

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

        // Paragraphs are a first-class typed collection
        return result.Paragraphs
            .Select(p => p.Text)
            .Where(t => !string.IsNullOrWhiteSpace(t))
            .ToList();
    }
}
Imports IronOcr

Public Class IronOcrByteArrayOcr
    Public Function ExtractParagraphsFromBytes(imageBytes As Byte()) As List(Of String)
        Using input As New OcrInput()
            input.LoadImage(imageBytes) ' byte array accepted directly

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

            ' Paragraphs are a first-class typed collection
            Return result.Paragraphs _
                .Select(Function(p) p.Text) _
                .Where(Function(t) Not String.IsNullOrWhiteSpace(t)) _
                .ToList()
        End Using
    End Function
End Class
$vbLabelText   $csharpLabel

IronOCR akzeptiert byte[] direkt auf LoadImage ohne das Zwischen-MemoryStream. Das Ergebnis offenbart .Paragraphs als typisierte LINQ-abfragbare Sammlung – kein Block-/Linien-/Wort-Dreifachverschachtelung erforderlich. Der Leitfaden zu den Leseergebnissen behandelt den Koordinatenzugriff, die Vertrauensfilterung und strukturierte Ausgabemuster für Workflows zur Rechnungs- und Formularverarbeitung. Informationen zum Scannen bestimmter Dokumentbereiche finden Sie unter regionenbasierter OCR .

GdPicture .NET API zu IronOCR Mapping-Referenz

GdPicture.NET IronOCR-Äquivalent
using GdPicture14; using IronOcr;
LicenseManager.RegisterKEY("key") IronOcr.License.LicenseKey = "key"
new GdPictureImaging() Nicht erforderlich – intern zu OcrInput
new GdPictureOCR() new IronTesseract()
new GdPicturePDF() Nicht erforderlich – OcrInput.LoadPdf() behandelt dies
_ocr.ResourceFolder = path Nicht erforderlich – Ressourcen sind in NuGet enthalten.
imaging.CreateGdPictureImageFromFile(path) input.LoadImage(path)
imaging.CreateGdPictureImageFromStream(stream) input.LoadImage(stream)
imaging.CreateGdPictureImageFromBytes(bytes) input.LoadImage(bytes)
imaging.CloneImage(tiffId) pro Rahmen input.LoadImageFrames(tiffPath)
imaging.ReleaseGdPictureImage(imageId) using var input = new OcrInput() — automatisch
ocr.SetImage(imageId) Nicht erforderlich — OcrInput hält das Bild.
ocr.Language = "eng" ocr.Language = OcrLanguage.English
ocr.RunOCR()resultId Zeichenkette ocr.Read(input) → typisiert OcrResult
ocr.GetOCRResultText(resultId) result.Text
ocr.GetOCRResultConfidence(resultId) result.Confidence
ocr.GetOCRResultBlockCount(resultId) result.Pages[i].Paragraphs.Count
ocr.GetOCRResultBlockLineWordText(resultId, b, l, w) result.Words[i].Text
imaging.GetStat() / ocr.GetStat() Standard .NET Ausnahmen
GdPictureStatus.OK-Check nach jedem Anruf Nicht erforderlich – Ausnahmen werden weitergegeben
pdf.OcrPage("eng", resourcePath, "", 200) result.SaveAsSearchablePdf(outputPath)
pdf.RenderPageToGdPictureImage(200, false) Nicht erforderlich –IronOCR rendert intern.
pdf.SelectPage(i) Nicht erforderlich – alle Seiten werden standardmäßig verarbeitet
pdf.GetPageCount() result.Pages.Count
Task.Run(() => ocr.RunOCR()) + SemaphoreSlim await ocr.ReadAsync(input)

Gängige Migrationsprobleme und Lösungen

Problem 1: Bild-ID-Variablen verblieben nach Refactoring im Code.

GdPicture.NET: Bestehender Code erklärt int imageId oben in den Methoden, verfolgt es durch Try/Finally und übergibt es an mehrere GdPicture-Anrufe. Nach dem Ersetzen von GdPicture-Aufrufen werden diese Variablen und ihre ReleaseGdPictureImage-Aufrufe verwaister toter Code.

Lösung: Löschen Sie das gesamte Bild-ID-Muster. Ersetzen Sie die Deklaration, den try, den finally und den Freigabeaufruf durch einen using var input = new OcrInput()-Block. Suchen und Ersetzen für ReleaseGdPictureImage, um jeden Bereinigungsaufruf zu finden, der entfernt werden muss:

grep -rn "ReleaseGdPictureImage\|imageId\|resultId" --include="*.cs" .
grep -rn "ReleaseGdPictureImage\|imageId\|resultId" --include="*.cs" .
SHELL
// Remove all of this
int imageId = _imaging.CreateGdPictureImageFromFile(path);
try
{
    _ocr.SetImage(imageId);
    string resultId = _ocr.RunOCR();
    return _ocr.GetOCRResultText(resultId);
}
finally
{
    _imaging.ReleaseGdPictureImage(imageId);
}

// Replace with
using var input = new OcrInput();
input.LoadImage(path);
return new IronTesseract().Read(input).Text;
// Remove all of this
int imageId = _imaging.CreateGdPictureImageFromFile(path);
try
{
    _ocr.SetImage(imageId);
    string resultId = _ocr.RunOCR();
    return _ocr.GetOCRResultText(resultId);
}
finally
{
    _imaging.ReleaseGdPictureImage(imageId);
}

// Replace with
using var input = new OcrInput();
input.LoadImage(path);
return new IronTesseract().Read(input).Text;
' Remove all of this
Dim imageId As Integer = _imaging.CreateGdPictureImageFromFile(path)
Try
    _ocr.SetImage(imageId)
    Dim resultId As String = _ocr.RunOCR()
    Return _ocr.GetOCRResultText(resultId)
Finally
    _imaging.ReleaseGdPictureImage(imageId)
End Try

' Replace with
Using input As New OcrInput()
    input.LoadImage(path)
    Return New IronTesseract().Read(input).Text
End Using
$vbLabelText   $csharpLabel

Problem 2: Ressourcenordnerpfad in der bereitgestellten Umgebung nicht gefunden

GdPicture.NET: Der im _ocr.ResourceFolder gesetzte Pfad wird auf der Entwicklungsmaschine aufgelöst, schlägt jedoch in der Produktion fehl. Häufige Symptome sind stille OCR-Fehler, die leere Ergebnisse zurückgeben, oder allgemeine GdPictureStatus-Fehler, die die fehlende Datei nicht benennen.

Lösung: Entfernen Sie die ResourceFolder-Zuordnung vollständig. Englische Unterstützung ist im IronOCR NuGet Paket integriert. Zusätzliche Sprachen werden als NuGet -Pakete installiert. Es gibt keinen Dateisystempfad zum Konfigurieren oder Bereitstellen:

# Remove the filesystem folder from deployment artifacts
# Add language NuGet packages to the project instead
:InstallCmd dotnet add package IronOcr.Languages.French, IronOcr.Languages.German
# Remove the filesystem folder from deployment artifacts
# Add language NuGet packages to the project instead
:InstallCmd dotnet add package IronOcr.Languages.French, IronOcr.Languages.German
SHELL

Problem 3: Fehlerbehandlung für GdPictureStatus durch Ausnahmen ersetzt

GdPicture.NET: Jede Operation gibt oder setzt einen GdPictureStatus-Enum-Wert, der sofort überprüft werden muss. Der Code ist dicht mit if (status != GdPictureStatus.OK)-Schutzmaßnahmen. Einige Statuscodes sind generisch (z.B. Error, InvalidParameter) und erfordern es, die Dokumentation zu konsultieren, um die Ursache zu bestimmen.

Lösung:IronOCR löst typisierte .NET -Ausnahmen aus. Ersetzen Sie Statusprüfungen durch try/catch-Blöcke. Standard IOException und FileNotFoundException decken Eingabefehler ab; IronOcr.Exceptions.OcrException deckt OCR-spezifische Fehler ab. Empfohlene Fehlerbehandlungsmuster finden Sie im IronTesseract-Einrichtungsleitfaden :

try
{
    var result = new IronTesseract().Read(imagePath);
    return result.Text;
}
catch (FileNotFoundException ex)
{
    _logger.LogError("Input file missing: {Path}", ex.FileName);
    throw;
}
catch (IronOcr.Exceptions.OcrException ex)
{
    _logger.LogError("OCR processing failed: {Message}", ex.Message);
    throw;
}
try
{
    var result = new IronTesseract().Read(imagePath);
    return result.Text;
}
catch (FileNotFoundException ex)
{
    _logger.LogError("Input file missing: {Path}", ex.FileName);
    throw;
}
catch (IronOcr.Exceptions.OcrException ex)
{
    _logger.LogError("OCR processing failed: {Message}", ex.Message);
    throw;
}
Imports IronOcr
Imports System.IO

Try
    Dim result = New IronTesseract().Read(imagePath)
    Return result.Text
Catch ex As FileNotFoundException
    _logger.LogError("Input file missing: {Path}", ex.FileName)
    Throw
Catch ex As IronOcr.Exceptions.OcrException
    _logger.LogError("OCR processing failed: {Message}", ex.Message)
    Throw
End Try
$vbLabelText   $csharpLabel

Problem 4: GdPicture14 Namespace in mehreren Dateien

GdPicture.NET: Die Versionsnummer im Namespace bedeutet, dass es ein projektweites using GdPicture14;-Anweisung in Dutzenden von Dateien gibt. Nach der Migration müssen alle mit using IronOcr; ersetzt werden.

Lösung: Verwenden Sie ein globales Suchen-und-Ersetzen über alle .cs-Dateien und verifizieren Sie dann, dass keine GdPicture-Referenzen mehr übrig sind:

# Find all files with GdPicture namespace
grep -rln "using GdPicture" --include="*.cs" .

# After replacing, verify nothing remains
grep -rn "GdPicture14\|GdPictureOCR\|GdPictureImaging\|GdPicturePDF" --include="*.cs" .
# Find all files with GdPicture namespace
grep -rln "using GdPicture" --include="*.cs" .

# After replacing, verify nothing remains
grep -rn "GdPicture14\|GdPictureOCR\|GdPictureImaging\|GdPicturePDF" --include="*.cs" .
SHELL

Ausgabe 5: Logik zur TIFF-Framezählung

GdPicture.NET: Code, der TIFF-Rahmen durchläuft, mischt oft Aufrufe über GdPictureImaging.GetPageCount(imageId) und GdPicturePDF.GetPageCount() hinweg, abhängig davon, wie die Datei geladen wurde. Der Frame-Index beginnt bei 1.

Lösung: input.LoadImageFrames(path) behandelt alle Rahmen automatisch. Wenn Ihr vorhandener Code nur spezifische Rahmen verarbeitet, verwenden Sie input.LoadImageFrames(path, frameNumbers) mit einem nullbasierten Index-Array. Zugriff auf pro-Rahmen-Ergebnisse über result.Pages, der auch nullbasiert ist. Das TIFF-Eingabehandbuch dokumentiert das Indexierungsverhalten explizit.

Problem 6: Vorverarbeitung erfordert das Dokumenten-Imaging-Plugin

GdPicture.NET: Deskew- und Despeckle-Operationen gehören zum GdPictureDocumentImaging Plugin, das einen separaten Lizenzerwerb erfordert. Teams, die das Plugin übersprungen haben, haben oft Probleme mit der OCR-Genauigkeit bei gescannten Dokumenten mit schiefen oder verrauschten Seiten.

Lösung: Die IronOCR Vorverarbeitungsmethoden sind Teil des Basispakets. Fügen Sie Deskew() und DeNoise() direkt auf OcrInput hinzu. Der Leitfaden zur Bildqualitätskorrektur deckt alle verfügbaren Filter einschließlich Contrast(), Sharpen(), Binarize() und DeepCleanBackgroundNoise() für stark verschlechterte Scans ab:

using var input = new OcrInput();
input.LoadImage("scanned-document.tiff");
input.Deskew();        // no separate plugin license
input.DeNoise();
input.Contrast();

var result = new IronTesseract().Read(input);
using var input = new OcrInput();
input.LoadImage("scanned-document.tiff");
input.Deskew();        // no separate plugin license
input.DeNoise();
input.Contrast();

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

Using input As New OcrInput()
    input.LoadImage("scanned-document.tiff")
    input.Deskew() ' no separate plugin license
    input.DeNoise()
    input.Contrast()

    Dim result = New IronTesseract().Read(input)
End Using
$vbLabelText   $csharpLabel

GdPicture .NET Migrations-Checkliste

Vor der Migration

Prüfen Sie den Quellcode, um alle GdPicture-Abhängigkeiten zu ermitteln, bevor Sie Änderungen vornehmen:

# Find all GdPicture namespace imports
grep -rn "using GdPicture" --include="*.cs" .

# Find all image ID creation points
grep -rn "CreateGdPictureImageFromFile\|CreateGdPictureImageFromStream\|RenderPageToGdPictureImage\|CloneImage" --include="*.cs" .

# Find all release calls — these map to using block boundaries
grep -rn "ReleaseGdPictureImage" --include="*.cs" .

# Find all resource folder assignments
grep -rn "ResourceFolder" --include="*.cs" .

# Find all OCR result ID accesses
grep -rn "RunOCR\|GetOCRResult\|resultId" --include="*.cs" .

# Find all GdPictureStatus checks
grep -rn "GdPictureStatus\|GetStat()" --include="*.cs" .

# Count GdPicture-dependent files
grep -rln "GdPicture14" --include="*.cs" . | wc -l
# Find all GdPicture namespace imports
grep -rn "using GdPicture" --include="*.cs" .

# Find all image ID creation points
grep -rn "CreateGdPictureImageFromFile\|CreateGdPictureImageFromStream\|RenderPageToGdPictureImage\|CloneImage" --include="*.cs" .

# Find all release calls — these map to using block boundaries
grep -rn "ReleaseGdPictureImage" --include="*.cs" .

# Find all resource folder assignments
grep -rn "ResourceFolder" --include="*.cs" .

# Find all OCR result ID accesses
grep -rn "RunOCR\|GetOCRResult\|resultId" --include="*.cs" .

# Find all GdPictureStatus checks
grep -rn "GdPictureStatus\|GetStat()" --include="*.cs" .

# Count GdPicture-dependent files
grep -rln "GdPicture14" --include="*.cs" . | wc -l
SHELL

Dokumentieren Sie Folgendes, bevor Sie den Code ändern:

  • Welche Dateien enthalten GdPictureImaging, GdPictureOCR und GdPicturePDF-Referenzen
  • Wie viele unterschiedliche Bild-ID-Erstellungs-/Veröffentlichungspaare gibt es?
  • Ob das Document Imaging Plugin (Entzerren, Fleckenentfernen) verwendet wird
  • Welche Sprachtraineddata-Dateien befinden sich im Ressourcenordner
  • Welche Bereitstellungsskripte oder Docker-Dateien verweisen auf den Ressourcenordnerpfad?

Code-Migration

  1. Entfernen Sie alle GdPicture NuGet Pakete aus der Projektdatei.
  2. Installieren Sie IronOcr über NuGet
  3. Installieren Sie IronOcr.Languages.*-Pakete für jede Sprache, die zuvor im Ressourcenordner war
  4. Fügen Sie IronOcr.License.LicenseKey = "..." zu Program.cs oder Startup.cs hinzu
  5. Entfernen Sie den LicenseManager.RegisterKEY()-Aufruf und das Lizenzmanagerobjekt
  6. Entfernen Sie alle GdPictureImaging-Felderklärungen und Konstruktorinitialisierungen
  7. Entfernen Sie alle GdPictureOCR Felderklärungen und die ResourceFolder-Zuweisung
  8. Entfernen Sie alle GdPicturePDF Felderklärungen, die für OCR-Workflows verwendet werden
  9. Ersetzen Sie jeden int imageId = _imaging.CreateGdPictureImage*(...)-Block durch using var input = new OcrInput(); input.Load*(...)
  10. Ersetzen Sie jedes _ocr.SetImage(imageId); _ocr.Language = &quot;...&quot;; string resultId = _ocr.RunOCR(); with var result = new IronTesseract().Read(input);
  11. Ersetzen Sie _ocr.GetOCRResultText(resultId) durch result.Text
  12. Entfernen Sie alle _imaging.ReleaseGdPictureImage(imageId)-Aufrufe
  13. Ersetzen Sie GdPictureStatus-Prüfungen durch try/catch-Blöcke
  14. Ersetzen Sie TIFF-Rahmenschleifen durch input.LoadImageFrames(path)
  15. Ersetzen Sie pdf.OcrPage(...) + pdf.SaveToFile(...) durch result.SaveAsSearchablePdf(outputPath)
  16. Entfernen Sie den Pfad zum Ressourcenordner aus den Bereitstellungsskripten und Docker-Images.
  17. Aktualisieren Sie using GdPicture14; auf using IronOcr; in allen betroffenen Dateien

Nach der Migration

Nachdem alle Codeänderungen abgeschlossen sind, überprüfen Sie bitte Folgendes, bevor Sie die Bereitstellung in der Produktionsumgebung durchführen:

  • Einzelselbstbild-OCR gibt den erwarteten Text ohne NullReferenceException von entfernten Komponenten zurück
  • Mehrseitige TIFF-Verarbeitung umfasst alle Rahmen und produziert pro-Seite-Text durch result.Pages Die PDF-OCR verarbeitet alle Seiten ohne Speicherbedarf bei einem Stapel von über 50 Dokumenten.
  • Stream-Eingabe akzeptiert MemoryStream und FileStream ohne Zwischen-Dateischreibvorgänge
  • Asynchrone OCR integriert sich in ASP.NET Core Anforderungshandler, ohne den Threadpool zu blockieren.
  • Parallele Batch-Verarbeitung mit Parallel.ForEach liefert genaue Ergebnisse über alle Threads hinweg
  • Alle Sprachpakete (Französisch, Deutsch usw.) werden über NuGet Pakete korrekt aktiviert.
  • Vorverarbeitungsfilter (Entzerren, Rauschen) verbessern die Genauigkeit gescannter Dokumente
  • Durchsuchbare PDF-Dateien können von PDF-Readern und Textsuchanwendungen gelesen werden.
  • Keine GdPicture-Namespaces-Verweise verbleiben in einer .cs-Datei nach der Migration
  • Das Speicherprofil zeigt eine stabile Nutzung unter anhaltender Last (keine Speicherlecks bei Image-Zuweisungen).
  • Die Bereitstellung auf Linux- und Docker-Systemen war erfolgreich, ohne dass Dateisystempfadfehler auftraten.

Wichtigste Vorteile der Migration zu IronOCR

Compilerseitig erzwungene Speichersicherheit. Der Image-ID-Lebenszyklus, den Entwickler bei GdPicture manuell verwalten mussten, entfällt vollständig. OcrInput implementiert IDisposable, und using-Blöcke erzwingen die Bereinigung am Ende jedes Bereichs – einschließlich Ausnahmepfade. Kein List<int> zu warten, keine finally-Blöcke zu erinnern, keine Produktivitätsvorfälle durch nicht freigegebene Aufrufe.

Ein einzelnes Paket für jedes OCR-Szenario. Bild-OCR, PDF-OCR, mehrseitige TIFF-Verarbeitung, durchsuchbare PDF-Erstellung, Vorverarbeitungsfilter, Barcode-Lesen und über 125 Sprachpakete sind alle aus dem IronOcr-NuGet-Paket und seinen Sprachbegleitern verfügbar. Es gibt keine Funktionsbarriere, die den Kauf einer zweiten oder dritten Lizenz erfordert, bevor ein gemeinsamer Arbeitsablauf möglich wird. Die vollständige Funktionsübersicht von IronOCR finden Sie hier.

Nativer Async und Thread-Sicherheit. ReadAsync ist eine echte asynchrone Methode, keine Task.Run-Verpackung. IronTesseract ist sicher, um über Threads ohne Synchronisation verwendet zu werden. Dokumentenverarbeitungsdienste, die zuvor eine thread-spezifische Komponenteninitialisierung und Semaphore-Serialisierung erforderten, reduzieren sich auf eine einzige geteilte Instanz mit Parallel.ForEach. Der Leitfaden zur asynchronen OCR behandelt sowohl ASP.NET Core als auch gehostete Dienstmuster.

Keine Konfiguration erforderlich.IronOCR benötigt weder Dateisystempfade noch externe Sprachdateien, native Binärverzeichnisse oder Bereitstellungsskripte. Der NuGet Wiederherstellungsschritt stellt alles bereit, was die Anwendung benötigt. Docker-Images, Azure App Service-Bereitstellungen und Linux-Server funktionieren alle identisch zur Entwicklungsumgebung. Die Docker-Bereitstellungsanleitung und die Azure-Bereitstellungsanleitung zeigen produktionsreife Konfigurationen.

Version-Stable Namespace. using IronOcr hat sich über Hauptversionen hinweg nicht geändert. Die Versionsnummern von NuGet regeln die Versionsverwaltung über das Standard-Paketverwaltungsmodell. Zukünftige größere Aktualisierungen erfordern keine codeweite Suche und Ersetzung des Namespace-Imports.

Vorhersehbare unbefristete Lizenzierung.IronOCR ist zu $999 (Lite), $1.499 (Plus), $2.999 (Professional) und $5.999 (Unlimited) erhältlich — einmalige unbefristete Käufe, die ein Jahr Updates beinhalten, mit optionaler jährlicher Erneuerung. Alle Funktionen sind in jeder Stufe verfügbar. Es gibt keine Plugins pro Funktion, keine Kosten pro Seite und keine Wartungsverpflichtung nach dem ersten Jahr. Teams, die zuvor über 8.000 US-Dollar für GdPicture-Plugin-Lizenzen für einen reinen OCR-Workflow aufgewendet haben, gleichen diese Lücke innerhalb des ersten Lizenzzyklus aus. Die vollständigen Preisinformationen finden Sie auf der IronOCR Lizenzseite .

Hinweis:GdPicture.NET und Tesseract sind eingetragene Marken ihrer jeweiligen Besitzer. Diese Seite ist nicht mit Google, Nutrient oder ORPALIS verbunden, genehmigt oder gesponsert. Alle Produktnamen, Logos und Marken sind Eigentum ihrer jeweiligen Eigentümer. Vergleiche dienen nur zu Informationszwecken und spiegeln öffentlich zugängliche Informationen zum Zeitpunkt des Schreibens wider.

Häufig gestellte Fragen

Warum sollte ich von GdPicture.NET OCR 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 GdPicture.NET OCR zu IronOCR?

Ersetzen Sie die Initialisierungssequenzen von GdPicture.NET durch die Instanziierung von IronTesseract, entfernen Sie das COM-Lebenszyklusmanagement (explizite Create/Load/Close-Muster) und aktualisieren Sie die Namen der Ergebniseigenschaften. Das Ergebnis ist eine deutliche Verringerung der Anzahl von 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 GdPicture.NET OCR für Standardgeschä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 GdPicture.NET OCR 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 GdPicture.NET OCR zu IronOCR Änderungen an der Bereitstellungsinfrastruktur?

IronOCR erfordert weniger Änderungen an der Infrastruktur als GdPicture.NET OCR. 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 eine im Anwendungscode festgelegte Zeichenfolge.

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 GdPicture.NET?

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 bei der Skalierung von Arbeitslasten berechenbarer als die von GdPicture.NET OCR?

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 nach der Migration von GdPicture.NET OCR zu IronOCR?

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