OCRツールを使用して画像からアラビア語のテキストを抽出する方法
このガイドでは、 .NET開発者が GdPicture .NET OCR からIronOCRへ完全に移行する方法を説明します。 本書では、主要なOCRワークフローすべてにおけるパッケージの入れ替え、名前空間の変更、および実用的な変更前後のコードパターンについて解説し、特にGdPictureのリソース管理モデルを定義する整数画像IDライフサイクルの排除に重点を置いています。 比較記事を事前に読む必要はありません。
GdPicture .NETから移行する理由
GdPicture .NETは、スキャナーとの統合、DICOMサポート、PDF編集、注釈付け、OCRといった機能を単一ベンダーから必要とするチーム向けに構築されたドキュメントイメージングプラットフォームです。 OCRが唯一の要件である場合、プラットフォームの価格設定とAPIアーキテクチャは、時間の経過とともに蓄積される摩擦を生み出す。
**基本的なOCRワークフローに必要なプラグインの費用。**スキャンしたPDFからテキストを抽出し、検索可能な出力を生成するには、3つのライセンスコンポーネントが必要です。コアSDKが約4,000ドル、OCRプラグインが約2,000ドル、PDFプラグインが約2,000ドルです。つまり、初期費用は8,000ドルで、Plus年間保守費用として20%がかかります。 OCR機能のみを必要とするチームでも、文書画像処理プラットフォームの料金体系全体を負担することになる。 IronOCRは、単一のパッケージでイメージOCR、PDF OCR、前処理、検索可能なPDF出力の同じワークフローを$999から$2,399の永続ライセンスでカバーします。機能ごとのライセンス決定はありません。 ライセンス階層の詳細については、 IronOCRのライセンスページをご覧ください。
整数画像IDのライフサイクル。 GdPictureを通してロードされたすべての画像はintを返します。 その整数をOCR操作に渡し、完了したらそれを使用してReleaseGdPictureImageを呼び出します。 このパターンはIDisposableより前から存在しています。 正しく手順に従えば効果を発揮します。 欠落するとメモリリークが発生します。 毎日数百ものドキュメントを処理する本番環境において、エラー分岐でリリース呼び出しが一度でも漏れると、メモリ使用量が急増し、その原因究明が非常に困難になる。 IronOCRのusingステートメントがすべてのクリーンアップの負担を排除します。
バージョン固有の名前空間。 GdPictureは主バージョン番号をその名前空間に埋め込んでいます: using GdPicture14。 次のメジャーリリースへのアップグレードには、GdPictureクラスを参照しているすべてのソースファイルのusing指令の更新が必要です。 OCRが数十ものサービスにまたがる大規模なアプリケーションでは、検索と置換に何時間もかかる上に、機能的な改善も得られない。 IronOCRの名前空間は、すべてのメジャーバージョンを通じてIronOcrです。
外部リソースフォルダーの要件。 GdPicture OCRは実行時に.traineddata言語ファイルのディレクトリを指します。そのパスは開発マシン上では機能しますが、Linuxサーバー、Dockerコンテナ、およびAzure App Serviceデプロイメントなど、ディレクトリ構造が存在しない場所では機能しません。IronOCRはNuGetパッケージ内に英語の言語サポートをバンドルしています。 追加言語は、ビルド出力に含まれるNuGetパッケージとしてインストールされます。
三コンポーネント初期化。 GdPictureでのPDF OCRワークフローは、GdPicturePDF—個別の破棄要件がある3つの別々のコンポーネント—およびライセンスマネージャーの登録とリソースフォルダーの割り当てを必要とします。 IronOCRは起動時に1行、呼び出し時に1つのクラスを必要とします。
ネイティブなスレッドセーフティはありません。GdPicture OCRインスタンスはスレッドセーフではありません。 並列文書処理では、状態の破損を防ぐために、インスタンスの慎重な管理と同期が必要となる。 IronOCRは同時使用を想定して設計されています: スレッドごとに1つのIronTesseractを作成するか、ロード時に単一のインスタンスを共有する—どちらのパターンも追加の同期コードなしで機能します。
基本的な問題
GdPictureは、各画像に対してランタイム管理の整数ハンドルとしてメモリを割り当てます。 TIFF処理ループでのすべてのRenderPageToGdPictureImage呼び出しは、新しい割り当てを生成し、手動でリリースする必要があります:
// 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
}
IronOCRはライフサイクルを完全に排除します。 OcrInputはフレーム列挙とクリーンアップを処理します:
// IronOCR: the using statement handles everything
using var input = new OcrInput();
input.LoadImageFrames("multi-page.tiff");
var result = new IronTesseract().Read(input);
IronOCRと.NET:機能比較
以下の表は、OCRを中心としたワークフローにおける、2つのライブラリの機能カバレッジを示しています。
| フィーチャー | GdPicture.NET | IronOCR |
|---|---|---|
| インストール。 | 複数のNuGetパッケージ | dotnet add package IronOcr |
| ライセンス認証 | LicenseManager.RegisterKEY() | IronOcr.License.LicenseKey = "..." |
| メジャーアップグレード時の名前空間 | 置換が必要 (GdPicture14 → next) | 変更されていない (IronOcr) |
| コンポーネントの初期化 | GdPictureImaging + GdPictureOCR + GdPicturePDF | new IronTesseract() |
| リソースメモリモデル | 手動整数ID追跡とリリース | IDisposable / using文 |
| メモリリークのリスク | 高い (欠落ReleaseGdPictureImage) | なし (コンパイラーによってusingで強制される) |
| 外部リソースフォルダ | 必須 (_ocr.ResourceFolder = path) | 不要 — パッケージに同梱されています |
| 画像OCR | はい | はい |
| PDF OCR。 | はい(PDFプラグインが必要です) | 組み込み済み、追加ライセンス不要 |
| 複数ページTIFF | 手動フレームループ+フレームごとのIDクリーンアップ | input.LoadImageFrames() |
| ストリーム入力 | GdPictureImaging ストリームオーバーロードを介して | input.LoadImage(stream) |
| 検索可能なPDF出力 | pdf.OcrPage() + pdf.SaveToFile() | result.SaveAsSearchablePdf() |
| デスクウ前処理 | ドキュメントイメージングプラグインが必要です | input.Deskew() — ビルトイン |
| ノイズ除去 | ドキュメントイメージングプラグインが必要です | input.DeNoise() — ビルトイン |
| 言語 | Tesseract ベースの学習済みデータファイルがフォルダー内にあります | NuGetパッケージ経由で125以上 |
| 多言語OCR | はい | OcrLanguage.French + OcrLanguage.German |
| スレッドセーフ。 | 手動インスタンス管理 | スレッドセーフ設計 |
| 非同期OCR | ビルトインではない | ReadAsync() |
| バーコード読み取り | 別売りのバーコードプラグイン | ocr.Configuration.ReadBarCodes = true |
| 構造化された出力 | インデックスベースのブロック/行/単語アクセス | 型付き.Characters |
| 信頼度スコア | GetOCRResultConfidence(resultId) | result.Confidence |
| クロスプラットフォーム | Windows、Linux、macOS | Windows、Linux、macOS、Docker、AWS、Azure |
| 入場料(PDFからのOCR) | 約8,000ドル(コア機能+OCR機能+PDFプラグイン) | $999–$2,399 |
| 価格設定モデル | プラグインベースの永久ライセンス + 年間メンテナンス料20% | 定額永久プラン、年間更新オプションあり |
| 商業サポート | はい | はい |
クイックスタート:GdPicture .NETからIronOCRへの移行
ステップ 1: NuGet パッケージを置き換える
GdPictureパッケージを削除してください。
dotnet remove package GdPicture.NET
dotnet remove package GdPicture.NET.OCR
dotnet remove package GdPicture.NET.PDF
NuGetパッケージページからIronOCRをインストールしてください。
英語以外の言語については、対応する言語パックをインストールしてください。
ステップ 2: 名前空間の更新
GdPicture名前空間をIronOCR名前空間に置き換えてください。
// Before (GdPicture)
using GdPicture14;
// After (IronOCR)
using IronOcr;
ステップ 3: ライセンスの初期化
この行をStartup.csに、OCR呼び出しの前に配置します:
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"GdPictureのライセンス登録ブロックを完全に削除してください。
// Remove this
LicenseManager lm = new LicenseManager();
lm.RegisterKEY("GDPICTURE-LICENSE-KEY");
IronOCRの製品ページから無料トライアルキーを入手して、購入前に評価することができます。
コード移行の例
複数ページTIFFフレーム処理
GdPictureで複数ページのTIFFファイルを処理するには、PDF/イメージングAPIを介して各フレームを選択し、それを新しいイメージIDにレンダリングし、OCRを実行し、IDを解放する必要があります。 finallyブロックでリリースされない単一のフレームは、DPIに応じて10–50 MBのメモリをリークします。
GdPicture .NETアプローチ:
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();
}
}
IronOCRのアプローチ:
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ブロックは、スコープの終わりですべてのフレームに関連するメモリを処理します。 維持する必要のあるtry/finallyブロックも必要ありません。 TIFFおよびGIF入力ガイドでは、フレーム選択とマルチフォーマット処理について詳しく解説しています。
ストリームベース入力置換プラグインの初期化
サーバーアプリケーションは、HTTPアップロード、メッセージキュー、データベースのブロブなどから、ファイルパスではなくストリームとしてドキュメントを受け取ることがよくあります。 GdPictureはストリームをGdPictureImagingを通じてロードする必要があり、それ自体がすべての操作に先立つコンポーネント初期化シーケンスとリソースフォルダー構成を要求します。
GdPicture .NETアプローチ:
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();
}
}
IronOCRのアプローチ:
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;
}
}
GdPicture方式では、最初のストリームを消費する前に、3つのオブジェクトを構築し、ファイルシステムパスを設定する必要があります。 IronOCRは事前設定なしでOcrInputにストリームを直接受け入れます。ストリーム入力ガイド は、テンポラリファイル書き込みが望ましくないパイプラインアーキテクチャのために、バイト配列、FileStreamパターンをカバーしています。
非同期OCRがステータスコードポーリングを置き換える
GdPicture OCRは同期型です。 ASP.NET Coreエンドポイントやバックグラウンドサービスでドキュメントを処理するアプリケーションは、リクエストスレッドをブロックしないようにTask.Runでラップする必要があります。そして、そのスレッド境界を越えた画像IDライフサイクルを管理する必要があります。 IronOCRはReadAsyncを通じて一級の非同期サポートを提供します。
GdPicture .NETアプローチ:
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();
}
}
}
IronOCRのアプローチ:
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;
}
}
GdPictureのアプローチでは、共有Task.Runと、そのラムダ内の完全な画像IDライフサイクルが必要です。 IronOCRのReadAsyncは本当にノンブロッキングでスレッドセーフです。 非同期OCRガイドでは、 ASP.NET Coreミドルウェアおよびホスト型バックグラウンドサービスとの統合について解説しています。
スレッドセーフティを備えた並列バッチ処理
スキャンした文書のフォルダをできるだけ高速に処理するには、並列処理が必要です。 GdPictureはスレッドごとに1つのGdPictureOCRインスタンスを必要とします—単一のインスタンスを共有すると非決定的な障害が発生します。 各スレッドごとのインスタンスには、それ自身のGdPictureImagingコンポーネントとリソースフォルダー構成が必要で、ファクトリーパターンなしではスレッドプールアプローチが非現実的になります。
GdPicture .NETアプローチ:
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;
}
}
IronOCRのアプローチ:
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;
}
}
GdPictureの並列実装では、スレッドごとに3つのオブジェクトが作成され、スレッドごとのライセンス登録が必要です。 IronOCRは、同期のオーバーヘッドなしで単一のIronTesseractインスタンスから同時読み取りを処理します。 マルチスレッディングの例 では、大量のドキュメント処理ワークロードのためのスループットベンチマークとParallel.ForEachパターンを示しています。
バイト配列入力と構造化段落抽出
データベースやオブジェクトストレージからドキュメントを取得するアプリケーションは、ファイルパスではなくバイト配列を扱うことが多い。 GdPictureは、バイト配列をストリームに変換し、それをGdPictureImagingを通じてロードする必要があります。 結果から構造化された段落レベルのデータを抽出するには、ブロック/行インデックスの階層構造をたどる必要があります。
GdPicture .NETアプローチ:
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;
}
}
IronOCRのアプローチ:
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();
}
}
IronOCRは、中間的なbyte[]を直接受け入れます。 結果は、ブロック/行/単語のトリプルループを必要としない、型付けされLINQクエリー可能なコレクションとして.Paragraphsを公開します。 読み取り結果ガイドでは、請求書およびフォーム処理ワークフローにおける座標アクセス、信頼性フィルタリング、および構造化出力パターンについて説明します。 文書の特定領域をスキャンする場合は、領域ベースのOCRを参照してください。
GdPicture .NET API からIronOCRへのマッピング リファレンス
| GdPicture.NET | IronOCR相当値 |
|---|---|
using GdPicture14; | using IronOcr; |
LicenseManager.RegisterKEY("key") | IronOcr.License.LicenseKey = "key" |
new GdPictureImaging() | 不要 — OcrInputに内部 |
new GdPictureOCR() | new IronTesseract() |
new GdPicturePDF() | 不要 — OcrInput.LoadPdf()がこれを処理 |
_ocr.ResourceFolder = path | 必須ではありません — NuGetにバンドルされているリソース |
imaging.CreateGdPictureImageFromFile(path) | input.LoadImage(path) |
imaging.CreateGdPictureImageFromStream(stream) | input.LoadImage(stream) |
imaging.CreateGdPictureImageFromBytes(bytes) | input.LoadImage(bytes) |
フレームごとにimaging.CloneImage(tiffId) | input.LoadImageFrames(tiffPath) |
imaging.ReleaseGdPictureImage(imageId) | using var input = new OcrInput() — 自動 |
ocr.SetImage(imageId) | 不要 — OcrInputが画像を保持 |
ocr.Language = "eng" | ocr.Language = OcrLanguage.English |
ocr.RunOCR() → resultId文字列 | ocr.Read(input) → 型付き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() | .NET Standardの例外 |
各呼び出し後にGdPictureStatus.OKチェック | 必須ではありません — 例外が伝播します |
pdf.OcrPage("eng", resourcePath, "", 200) | result.SaveAsSearchablePdf(outputPath) |
pdf.RenderPageToGdPictureImage(200, false) | 不要 — IronOCRは内部的にレンダリングします |
pdf.SelectPage(i) | 必須ではありません — すべてのページはデフォルトで処理されます |
pdf.GetPageCount() | result.Pages.Count |
Task.Run(() => ocr.RunOCR()) + SemaphoreSlim | await ocr.ReadAsync(input) |
一般的な移行の問題と解決策
問題1:リファクタリング後もコード内に画像ID変数が残っている
GdPicture.NET: 既存のコードはメソッドの先頭でint imageIdを宣言し、try/finallyでそれを追跡し、複数のGdPicture呼び出しに渡します。 GdPicture呼び出しを置き換えた後、これらの変数とそのReleaseGdPictureImage呼び出しは孤立したデッドコードになります。
**解決策:**画像IDパターン全体を削除します。 宣言、using var input = new OcrInput()ブロックで置き換えます。 削除する必要があるすべてのクリーンアップ呼び出しを見つけるためにReleaseGdPictureImageをグレップします:
grep -rn "ReleaseGdPictureImage\|imageId\|resultId" --include="*.cs" .
// 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;
問題2:デプロイされた環境でリソースフォルダパスが見つかりません
GdPicture.NET: _ocr.ResourceFolderで設定されたパスは開発マシンでは解決しますが、本番環境では失敗します。 一般的な症状は、空の結果を返すサイレントOCR障害、または消失したファイルを名前で特定しない一般的なGdPictureStatusエラーです。
解決策: ResourceFolder割り当てを完全に削除します。 IronOCR NuGetパッケージには英語サポートが組み込まれています。 追加言語はNuGetパッケージとしてインストールされます。 設定またはデプロイするためのファイルシステムパスがありません。
問題3:GdPictureStatusのエラー処理が例外処理に置き換えられました
GdPicture.NET: すべての操作はGdPictureStatus列挙値を返すかセットし、直ちにチェックする必要があります。 コードはif (status != GdPictureStatus.OK)ガードで密集しています。 一部のステータスコードは一般的です(例: InvalidParameter)であり、根本的な原因を判断するために文書を参照する必要があります。
解決策: IronOCRは型付き.NET例外をスローします。 ステータスチェックをtry/catchブロックに置き換えてください。 標準のFileNotFoundExceptionは入力不良をカバーします; IronOcr.Exceptions.OcrExceptionはOCR固有のエラーをカバーします。 推奨されるエラー処理パターンについては、 IronTesseractのセットアップガイドを参照してください。
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;
}
問題4: 複数のファイル内のGdPicture14名前空間
GdPicture.NET: 名前空間のバージョン番号は、プロジェクト全体で何十ものファイルにusing GdPicture14;ディレクティブが存在することを意味します。 移行後、これらすべてをusing IronOcr;に置き換える必要があります。
解決策: すべての.csファイルでグローバルな検索と置換を使用し、GdPicture参照が残っていないことを確認します:
# 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" .
第5号:TIFFフレームカウントロジック
GdPicture.NET: TIFFフレームを反復するコードは、ファイルのロード方法によってGdPicturePDF.GetPageCount()の呼び出しを混在させていることがよくあります。 フレームインデックスは1から始まります。
解決策: input.LoadImageFrames(path)はすべてのフレームを自動的に処理します。 既存のコードが特定のフレームのみを処理する場合、0ベースのインデックス配列でinput.LoadImageFrames(path, frameNumbers)を使用します。 フレームごとの結果にはゼロインデックス化されたresult.Pagesを通じてアクセスします。 TIFF入力ガイドには、インデックスの動作が明示的に記載されています。
問題6:前処理には文書イメージングプラグインが必要です
GdPicture.NET: 傾き補正およびゴミ取り操作はGdPictureDocumentImagingプラグインに属し、別途ライセンスの購入が必要です。 プラグインを導入しなかったチームは、傾きやノイズの多いスキャン文書において、OCRの精度に問題が生じることが多い。
解決策: IronOCRの前処理方法は基本パッケージに含まれています。 OcrInputに追加します。 画像品質補正ガイドは、DeepCleanBackgroundNoise()を含む、すべての利用可能なフィルターを扱っています。
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);
GdPicture .NET移行チェックリスト
移行前
変更を加える前に、コードベースを監査して、GdPictureへの依存関係をすべて特定してください。
# 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
コードを修正する前に、以下の事項を文書化してください。
GdPicturePDF参照を含むファイル- 異なるイメージIDの作成/リリースペアはいくつ存在しますか?
- ドキュメントイメージングプラグイン(デスクスキュー、デスペックル)が使用されているかどうか
- リソースフォルダーにある
traineddata言語ファイル - どのデプロイメントスクリプトまたはDockerファイルがリソースフォルダパスを参照しているか
コードの移行
- プロジェクトファイルからすべての GdPicture NuGetパッケージを削除します。
IronOcrをNuGet経由でインストール- リソースフォルダーに以前あった各言語の
IronOcr.Languages.*パッケージをインストール Startup.csに追加LicenseManager.RegisterKEY()呼び出しとライセンスマネージャーオブジェクトを削除GdPictureImagingフィールド宣言とコンストラクタ初期化をすべて削除- @
ResourceFolder割り当てをすべて削除 - OCRワークフローに使用される
GdPicturePDFフィールド宣言をすべて削除 - 各
int imageId = _imaging.CreateGdPictureImage*(...)ブロックをusing var input = new OcrInput();で置き換えます。 input.Load*(...)`. - 各
_ocr.SetImage(imageId); を置き換えます。 _ocr.Language = "..."; string resultId = _ocr.RunOCR();withvar result = new IronTesseract().Read(input); result.Textで置き換え_imaging.ReleaseGdPictureImage(imageId)の呼び出しをすべて削除- @
GdPictureStatusチェックをTRY/CATCHブロックで置き換えます。 - TIFFフレームループを
input.LoadImageFrames(path)で置き換えます。 pdf.OcrPage(...)+result.SaveAsSearchablePdf(outputPath)で置き換えます。- デプロイスクリプトとDockerイメージからリソースフォルダパスを削除します。
- 影響を受けたすべてのファイルで
using IronOcr;に更新
移行後
すべてのコード変更が完了したら、本番環境にデプロイする前に、以下の点を確認してください。
- 単一画像OCRは、削除されたコンポーネントから
NullReferenceExceptionなしで期待されるテキストを返します - マルチページTIFF処理はすべてのフレームをカバーし、
result.Pages経由でページごとのテキストを生成します。 - PDF OCRは、50以上の文書をバッチ処理してもメモリ使用量を増やすことなく、すべてのページを処理します。
- ストリーム入力は中間ファイル書き込みなしで
FileStreamを受け入れます - Async OCR は、スレッド プールをブロックすることなくASP.NET Coreリクエスト ハンドラーと統合されます
- @
Parallel.ForEachを使用した並列バッチ処理は、すべてのスレッドで正確な結果を生成します - すべての言語パック(フランス語、ドイツ語など)は、 NuGetパッケージを通じて正しく有効化されます。
- 前処理フィルター(傾き補正、ノイズ除去)により、スキャンした文書の精度が向上します。 検索可能なPDF出力は、PDFビューアおよびテキスト検索アプリケーションで読み取り可能です。
- マイグレーション後、
.csファイルにGdPictureの名前空間参照は残っていません ・メモリプロファイルは、持続的な負荷下でも安定した使用状況を示しています(イメージのメモリリークは発生していません)。 LinuxおよびDockerターゲットへのデプロイは、ファイルシステムパスエラーなしで成功しました。
IronOCRへの移行の主なメリット
コンパイラによるメモリ安全性の強制。GdPictureで開発者が手動で管理する必要があったイメージIDのライフサイクルは完全に不要になります。 usingブロックが例外パスを含めてすべてのスコープの終了時にクリーンアップを強制します。 維持するfinallyブロックもなく、リリース呼び出しの遺漏による本番メモリインシデントもありません。
すべてのOCRシナリオに対する単一パッケージ。 イメージOCR、PDF OCR、マルチページTIFF処理、検索可能なPDF生成、前処理フィルター、バーコード読み取り、および125以上の言語パックがすべてIronOcr NuGetパッケージとその言語パートナーから利用可能です。 共通のワークフローを実現するために、2つ目または3つ目のライセンスを購入する必要が生じるような機能制限はありません。 機能一覧の詳細は、 IronOCRの機能概要をご覧ください。
ネイティブの非同期とスレッドセーフティ。 Task.Runラッパーではありません。 IronTesseractは同期なしでスレッド間で安全に使用できます。 以前はスレッドごとのコンポーネント初期化とセマフォ直列化を必要としたドキュメント処理サービスは、Parallel.ForEachを使用して単一の共有インスタンスに減少します。 非同期OCRガイドでは、 ASP.NET Coreとホスト型サービスの両方パターンを取り上げています。
デプロイメント構成は不要です。IronOCRは、ファイルシステムパス、外部言語ファイル、ネイティブバイナリの配置、デプロイメントスクリプトを一切必要としません。NuGetの復元手順で、アプリケーションに必要なすべてが提供されます。 Dockerイメージ、Azure App Serviceデプロイメント、Linuxサーバーはすべて、開発環境と全く同じように動作します。DockerデプロイメントガイドとAzureデプロイメントガイドでは、本番環境ですぐに使用できる構成例を示しています。
バージョン安定の名前空間。 using IronOcrはメジャーバージョンのリリースの間で変更されていません。 NuGetのバージョン番号は、標準的なパッケージ管理モデルを通じてバージョン管理を行います。 今後の大規模なアップグレードでは、コードベース全体で名前空間のインポートを検索して置換する必要はありません。
予測可能な永続ライセンス。 IronOCRは$999(ライト)で$1,499(プラス)、$2,399(プロフェッショナル)、$5,999(アンリミテッド)で価格設定されており、1年間のアップデートと年次更新のオプションを含む一回限りの永続購入です。 すべての機能はどのプランでも利用可能です。 機能ごとのプラグイン料金やページごとの費用は一切なく、最初の1年以降はメンテナンス義務もありません。 これまでOCRのみのワークフローのためにGdPictureプラグインのライセンスに8,000ドル以上を費やしてきたチームは、最初のライセンスサイクル内でその費用を回収できる。 価格の詳細については、 IronOCRのライセンスページをご覧ください。
