Große TIFF-Dateien über 2 GB schlagen fehl beim Laden
IronOCR lädt Bilddaten in einen einzigen Speicherpuffer durch seinen internen AnyBitmap-Typ. Dieser Puffer wird durch einen 32-Bit-Integer indiziert, sodass er unabhängig davon, wie viel Systemspeicher Sie haben, auf etwa 2 GB beschränkt ist. Ein TIFF, das größer als 2 GB ist, überschreitet dieses Limit und schlägt beim Laden fehl.
Loaded pages: 0
OcrInput.LoadImage(filePath) erstellt intern einen AnyBitmap und materialisiert das gesamte Bild in einem Puffer. Da dieser Puffer durch int indexiert wird, ist er effektiv auf etwa 2 GB begrenzt, unabhängig davon, wie viel Speicher frei ist. Daher kann ein TIFF, das leicht über dem Limit liegt, nicht gehalten werden und der Ladevorgang schlägt fehl. Dies ist eine Laufzeitbeschränkung, nicht betriebssystemspezifisch, sodass es jede .NET-Plattform gleichermaßen betrifft.
LoadImage(filePath) gibt derzeit null geladene Seiten zurück, anstatt eine klare Ausnahme zu werfen. Dieser stillstehende Fehler ist ein bekanntes Problem; eine klarere Exception ist geplant. Das Single-Buffer-Design ist ein architektonisches Limit und natives per-page TIFF-Streaming ist derzeit nicht verfügbar.Lösung
Die Lösung besteht darin, das TIFF in unter-2-GB-Stücke aufzuteilen und jedes Stück als Byte-Array an IronOCR weiterzugeben, anstatt einen Dateipfad.
1. Fügen Sie Magick.NET hinzu
Verwenden Sie Magick.NET, um das TIFF zu teilen, bevor Sie es an IronOCR weiterleiten. Wählen Sie die Variante, die zu Ihrem Projekt passt (Q8/Q16, AnyCPU/x64).
dotnet add package Magick.NET-Q16-AnyCPU
dotnet add package Magick.NET-Q16-AnyCPU
2. Teilen Sie das TIFF und laden Sie jeden Abschnitt
Öffnen Sie das TIFF als MagickImageCollection, unterteilen Sie es in Seitenzählungsstücke, die jeweils unter 2 GB bleiben, konvertieren Sie jedes Stück in ein Byte-Array und laden Sie es mit OcrInput.LoadImage(byte[]).
var inputPath = "input.tiff";
var pagesPerChunk = 100;
using var allPages = new MagickImageCollection(inputPath);
int chunkNumber = 1;
for (int i = 0; i < allPages.Count; i += pagesPerChunk)
{
using var chunk = new MagickImageCollection();
for (int j = i; j < Math.Min(i + pagesPerChunk, allPages.Count); j++)
{
chunk.Add(allPages[j].Clone());
}
foreach (var image in chunk)
{
image.SetCompression(CompressionMethod.LZW);
}
var chunkBytes = chunk.ToByteArray();
using (var ocrInput = new OcrInput())
{
ocrInput.LoadImage(chunkBytes);
var pages = ocrInput.GetPages().ToList();
Console.WriteLine($"Loaded pages: {pages.Count}");
var result = new IronTesseract().Read(ocrInput);
Console.WriteLine("OCR Text Length: " + (result.Text?.Length ?? 0));
}
Console.WriteLine($"Chunk {chunkNumber} processed");
chunkNumber++;
}
var inputPath = "input.tiff";
var pagesPerChunk = 100;
using var allPages = new MagickImageCollection(inputPath);
int chunkNumber = 1;
for (int i = 0; i < allPages.Count; i += pagesPerChunk)
{
using var chunk = new MagickImageCollection();
for (int j = i; j < Math.Min(i + pagesPerChunk, allPages.Count); j++)
{
chunk.Add(allPages[j].Clone());
}
foreach (var image in chunk)
{
image.SetCompression(CompressionMethod.LZW);
}
var chunkBytes = chunk.ToByteArray();
using (var ocrInput = new OcrInput())
{
ocrInput.LoadImage(chunkBytes);
var pages = ocrInput.GetPages().ToList();
Console.WriteLine($"Loaded pages: {pages.Count}");
var result = new IronTesseract().Read(ocrInput);
Console.WriteLine("OCR Text Length: " + (result.Text?.Length ?? 0));
}
Console.WriteLine($"Chunk {chunkNumber} processed");
chunkNumber++;
}
Imports System
Imports System.Linq
Imports ImageMagick
Dim inputPath As String = "input.tiff"
Dim pagesPerChunk As Integer = 100
Using allPages As New MagickImageCollection(inputPath)
Dim chunkNumber As Integer = 1
For i As Integer = 0 To allPages.Count - 1 Step pagesPerChunk
Using chunk As New MagickImageCollection()
For j As Integer = i To Math.Min(i + pagesPerChunk, allPages.Count) - 1
chunk.Add(allPages(j).Clone())
Next
For Each image In chunk
image.SetCompression(CompressionMethod.LZW)
Next
Dim chunkBytes = chunk.ToByteArray()
Using ocrInput As New OcrInput()
ocrInput.LoadImage(chunkBytes)
Dim pages = ocrInput.GetPages().ToList()
Console.WriteLine($"Loaded pages: {pages.Count}")
Dim result = New IronTesseract().Read(ocrInput)
Console.WriteLine("OCR Text Length: " & If(result.Text?.Length, 0))
End Using
End Using
Console.WriteLine($"Chunk {chunkNumber} processed")
chunkNumber += 1
Next
End Using
Jedes Stück geht als rohe Bytes durch LoadImage(chunkBytes), wobei jeder Puffer unter dem 2 GB-Limit bleibt. SetCompression(CompressionMethod.LZW) verkleinert jedes Stück, bevor es in ein Byte-Array umgewandelt wird.
3. Abstimmen der Abschnittsgröße
Passen Sie pagesPerChunk an Ihre Daten an. Senken Sie es, wenn ein Abschnitt nahe an 2 GB herankommt oder wenn der Speicher knapp ist; erhöhen Sie es für kleinere Seiten, um den Overhead zu reduzieren.
4. Berücksichtigen Sie Magick.NET bei der Bereitstellung
Magick.NET liefert native ImageMagick-Binärdateien. Berücksichtigen Sie die hinzugefügte Paketgröße und den nativen Abhängigkeitsfußabdruck bei der Bereitstellung.

