2GBを超える大きなTIFFファイルがロードされない

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

IronOCRは画像入力を内部のAnyBitmap型を介して1つのインメモリバッファにロードします。 そのバッファは32ビット整数でインデックスされているため、システムメモリの量に関わらず約2GBで制限されます。 2GB超のTIFFはこの制限を超えてロードに失敗します。

Loaded pages: 0

AnyBitmapを構築し、1つのバッファにイメージを全体としてマテリアライズします。 そのバッファはintでインデックスされているため、実質的に約2GBに制限されており、多少制限を超えたTIFFは保持できず、ロードが失敗します。 これは実行時の制約であり、OSに特有のものではなく、すべて for .NETプラットフォームに影響を与えます。

警告LoadImage(filePath) は現在、読み込まれたページが0のまま返され、明確な例外が発生しません。 この静かな失敗は既知の問題です; より明確な例外が計画されています。 単一バファーデザインは設計上の制限であり、ネイティブのページごとのTIFFストリーミングはまだ利用できません。

解決策

解決策は、TIFFを2GB未満のチャンクに分割し、ファイルパスではなくバイト配列として各チャンクをIronOCRに渡すことです。

1. Magick.NETを追加

TIFFをIronOCRに渡す前に分割するためにMagick.NETを使用します。 プロジェクトに合ったバリアント(Q8/Q16, AnyCPU/x64)を選択してください。

dotnet add package Magick.NET-Q16-AnyCPU
dotnet add package Magick.NET-Q16-AnyCPU
SHELL

2. TIFFを分割し、各チャンクを読み込む

TIFFを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)を通過し、すべてのバッファーを2GBの上限内に保ちます。 SetCompression(CompressionMethod.LZW)はバイト配列に変換される前に各チャンクを縮小します。

3. チャンクサイズを調整する

データに合わせてpagesPerChunkを調整します。 チャンクが2GBに近づいたりメモリが不足している場合は下げます; 小さいページの場合はオーバーヘッドを減らすために上げます。

4. デプロイ時のMagick.NETを考慮する

Magick.NETはImageMagickネイティブバイナリを提供します。 デプロイ時に追加のパッケージサイズとネイティブ依存のフットプリントを考慮してください。

Curtis Chau
テクニカルライター

Curtis Chauは、カールトン大学でコンピュータサイエンスの学士号を取得し、Node.js、TypeScript、JavaScript、およびReactに精通したフロントエンド開発を専門としています。直感的で美しいユーザーインターフェースを作成することに情熱を持ち、Curtisは現代のフレームワークを用いた開発や、構造の良い視覚的に魅力的なマニュアルの作成を楽しんでいます。

開発以外にも、CurtisはIoT(Internet of Things)への強い関心を持ち、ハードウェアとソフトウェアの統合方法を模索しています。余暇には、ゲームをしたりDiscordボットを作成したりして、技術に対する愛情と創造性を組み合わせています。

準備はできましたか?
Nuget ダウンロード 6,136,090 | バージョン: 2026.7 リリースされたばかり
Still Scrolling Icon

まだスクロールしていますか?

すぐに証拠が欲しいですか? PM > Install-Package IronOcr
サンプルを実行 あなたの画像が検索可能なテキストになるのをご覧ください。