超过 2 GB 的大 TIFF 文件无法加载
IronOCR 将图像输入加载到单个内存缓冲区中,通过其内部 AnyBitmap 类型。 该缓冲区由 32 位整数索引,因此无论系统内存有多少,它都限制在大约 2 GB。 大于 2 GB 的 TIFF 超出了此限制,无法加载。
Loaded pages: 0
OcrInput.LoadImage(filePath) 在内部创建一个 AnyBitmap 并将整个图像实体化为一个缓冲区。 由于该缓冲区由 int 索引,无论有多少可用内存,它实际上都限制为大约 2 GB,因此略高于此限制的 TIFF 无法加载且加载失败。 这是一个运行时约束,与操作系统无关,因此影响所有 .NET 平台。
LoadImage(filePath) 目前返回零加载页面,而不是抛出明确的异常。 这一无声失败是一个已知问题; 计划推出更清晰的异常。 单缓冲设计是一个架构限制,目前还没有本地逐页 TIFF 流式传输选项。解决方案
解决方法是将 TIFF 拆分为小于 2 GB 的数据块,并将每个块作为字节数组传递给 IronOCR,而不是文件路径。
1. 添加 Magick.NET
using Magick.NET 拆分 TIFF 之后再交给 IronOCR。 选择与您的项目相匹配的变体(Q8/Q16, AnyCPU/x64)。
dotnet add package Magick.NET-Q16-AnyCPU
dotnet add package Magick.NET-Q16-AnyCPU
2. 拆分 TIFF 并加载每个块
将 TIFF 作为 MagickImageCollection 打开,将其分解为每个保持在 2 GB 以下的页面数块,转换每个块为字节数组,并通过 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
每个块以原始字节通过 LoadImage(chunkBytes),保持每个缓冲区在 2 GB 上限以下。 SetCompression(CompressionMethod.LZW) 在将每个块转换为字节数组之前将其缩小。
3. 调整块大小
根据您的数据调整 pagesPerChunk。 如果块接近 2 GB 或内存紧张,请降低大小; 对于较小的页面,增加大小以减少开销。
4. 在部署中考虑 Magick.NET
Magick.NET 装载 ImageMagick 本地二进制文件。 在部署时考虑增加的包大小和本地依赖占位。

