超过 2 GB 的大 TIFF 文件无法加载

This article was translated from English: Does it need improvement?
Translated
View the article in English

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
SHELL

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
$vbLabelText   $csharpLabel

每个块以原始字节通过 LoadImage(chunkBytes),保持每个缓冲区在 2 GB 上限以下。 SetCompression(CompressionMethod.LZW) 在将每个块转换为字节数组之前将其缩小。

3. 调整块大小

根据您的数据调整 pagesPerChunk。 如果块接近 2 GB 或内存紧张,请降低大小; 对于较小的页面,增加大小以减少开销。

4. 在部署中考虑 Magick.NET

Magick.NET 装载 ImageMagick 本地二进制文件。 在部署时考虑增加的包大小和本地依赖占位。

Curtis Chau
技术作家

Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。

除了开发之外,Curtis 对物联网 (IoT) 有浓厚的兴趣,探索将硬件和软件集成的新方法。在空闲时间,他喜欢玩游戏和构建 Discord 机器人,将他对技术的热爱与创造力相结合。

准备开始了吗?
Nuget 下载 6,136,090 | 版本: 2026.7 刚刚发布
Still Scrolling Icon

还在滚动吗?

想快速获得证据? PM > Install-Package IronOcr
运行示例 观看您的图像变成可搜索文本。