Migrando do Asprise OCR para o IronOCR
Este guia orienta os desenvolvedores .NET em cada etapa da substituição doAsprise OCRpelo IronOCR . Este documento aborda a troca mecânica de pacotes, as alterações de namespace e os quatro padrões de migração de código que representam a maior parte do uso do Asprise em aplicações .NET de produção. O público-alvo são os desenvolvedores que já decidiram migrar e precisam de um plano de ação concreto.
Por que migrar do Asprise OCR?
OAsprise OCRfoi projetado inicialmente como um produto Java. A interface .NET é um wrapper em torno de um mecanismo nativo originado em Java, e essa origem molda todos os aspectos do comportamento da biblioteca no .NET — desde a implantação até o design da API e as restrições de licenciamento.
Dependência de Binário Nativo e JRE.Asprise OCRfor .NET requer binários nativos específicos da plataforma (aocr.dll, aocr_x64.dll, libaocr.so, libaocr.dylib) para estar presente em cada máquina onde o aplicativo é executado. Cada arquivo binário deve corresponder exatamente à plataforma de destino e à arquitetura do processo. Um contêiner Docker de 64 bits construído com o DLL de 32 bits lança BadImageFormatException durante a execução. Uma implantação Linux sem libaocr.so de LD_LIBRARY_PATH lança DllNotFoundException. Nenhum dos erros aparece durante a compilação. Cada novo destino de implantação — um novo servidor, uma nova imagem de contêiner, um agente de CI — torna-se um exercício manual de busca de binários.
API de Constante de String de Herança Java. Asprise expõe constantes inteiras para tipo de reconhecimento e formato de saída: Ocr.RECOGNIZE_TYPE_TEXT, Ocr.OUTPUT_FORMAT_PLAINTEXT, Ocr.OUTPUT_FORMAT_XML. Essas constantes correspondem diretamente à API baseada em números inteiros do SDK Java. Os desenvolvedores .NET não recebem nenhuma orientação do IntelliSense sobre valores constantes válidos, nenhuma segurança em tempo de compilação sobre combinações de argumentos e nenhum objeto de resultado fortemente tipado. A extração de dados estruturados requer a análise manual de strings XML.
Sem suporte assíncrono sem soluções alternativas. A Asprise não fornece uma API assíncrona nativa. Embrulhar chamadas síncronas Asprise em Task.Run para evitar bloquear threads do ASP.NET cria pressão no pool de threads e não resolve a restrição de licença que proíbe a execução simultânea nos níveis LITE e STANDARD. Padrões assíncronos em aplicações .NET modernas — serviços em segundo plano, endpoints de API mínimos, Azure Functions — não têm um equivalente direto no Asprise.
O processamento de TIFF com múltiplos quadros requer divisão manual. O Asprise opera com arquivos de imagem individuais. O processamento de um TIFF com várias páginas requer código externo para dividir os frames em arquivos individuais e, em seguida, processar cada arquivo em um loop. Nenhum metadado de frame ou numeração de página é transferido para o arquivo de saída.
Restrições de threads impedem a implantação em produção. As licenças Lite (aproximadamente US$ 299) e STANDARD (aproximadamente US$ 699) restringem contratualmente a execução a uma única thread e um único processo. O ASP.NET Core processa todas as solicitações HTTP em um pool de threads. Cada endpoint de API web que chama o Asprise nesses planos constitui uma violação de licença desde a primeira requisição simultânea. A atualização para o plano Enterprise remove a restrição, mas exige contato com o departamento de vendas, cujo preço não foi divulgado — as estimativas variam de US$ 2.000 a mais de US$ 5.000, dependendo do escopo da implementação.
O Manuseio do Formato de Saída Requer Análise de String. Quando OUTPUT_FORMAT_XML é especificado, Asprise retorna uma string XML bruta. O aplicativo é responsável por desserializar essa string, validar sua estrutura e extrair palavras e suas coordenadas. Os índices de confiança por palavra estão incorporados em atributos XML. Não existe modelo de objetos — apenas manipulação de strings.
O problema fundamental
O Asprise requer configuração binária nativa adjacente ao JRE antes que a primeira chamada de OCR possa ser executada. O IronOCR não requer nada além de um pacote NuGet :
// Asprise: native binary must exist in PATH or application directory
// aocr_x64.dll missing → DllNotFoundException at runtime, not at build
Ocr.SetUp(); // Static init — touches native binary
Ocr ocr = new Ocr();
ocr.StartEngine("eng", Ocr.SPEED_FAST); // Allocates native engine memory
string text = ocr.Recognize(imagePath, Ocr.RECOGNIZE_TYPE_TEXT, Ocr.OUTPUT_FORMAT_PLAINTEXT);
ocr.StopEngine(); // Must call or native memory leaks
// Asprise: native binary must exist in PATH or application directory
// aocr_x64.dll missing → DllNotFoundException at runtime, not at build
Ocr.SetUp(); // Static init — touches native binary
Ocr ocr = new Ocr();
ocr.StartEngine("eng", Ocr.SPEED_FAST); // Allocates native engine memory
string text = ocr.Recognize(imagePath, Ocr.RECOGNIZE_TYPE_TEXT, Ocr.OUTPUT_FORMAT_PLAINTEXT);
ocr.StopEngine(); // Must call or native memory leaks
' Asprise: native binary must exist in PATH or application directory
' aocr_x64.dll missing → DllNotFoundException at runtime, not at build
Ocr.SetUp() ' Static init — touches native binary
Dim ocr As New Ocr()
ocr.StartEngine("eng", Ocr.SPEED_FAST) ' Allocates native engine memory
Dim text As String = ocr.Recognize(imagePath, Ocr.RECOGNIZE_TYPE_TEXT, Ocr.OUTPUT_FORMAT_PLAINTEXT)
ocr.StopEngine() ' Must call or native memory leaks
// IronOCR: dotnet add package IronOcr — no binary sourcing, no lifecycle calls
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
string text = new IronTesseract().Read(imagePath).Text;
// IronOCR: dotnet add package IronOcr — no binary sourcing, no lifecycle calls
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
string text = new IronTesseract().Read(imagePath).Text;
' IronOCR: dotnet add package IronOcr — no binary sourcing, no lifecycle calls
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
Dim text As String = New IronTesseract().Read(imagePath).Text
IronOCR vs Asprise OCR: Comparação de Recursos
A tabela abaixo abrange as funcionalidades mais relevantes para os desenvolvedores que avaliam essa migração.
| Recurso | Asprise OCR | IronOCR |
|---|---|---|
| Plataforma principal | Java (legado) | .NET nativo |
| Instalação do NuGet | Wrapper + DLLs nativas da plataforma | Pacote único (IronOcr) |
| Binário nativo necessário em tempo de execução. | Sim (DLL por plataforma) | Não |
| Estilo da API .NET | Constantes inteiras, retornos de string | Classes e enumerações fortemente tipadas |
IDisposable / using padrão |
Não implementado | Sim (OcrInput) |
| OCR assíncrono | Sem suporte nativo | Sim (ReadAsync) |
| Multithreading — Nível Lite/STANDARD | Proibido por licença | Permitido |
| Multithreading — todos os níveis | SOMENTE PARA Enterprise | Todos os níveis |
| Suporte à API Web do ASP.NET Core | Enterprise necessária | Qualquer nível |
| Azure Functions / AWS Lambda | Enterprise necessária | Qualquer nível |
| Entrada nativa de PDF | Não | Sim |
| Entrada TIFF multiframe | Não (divisão manual de quadros) | Sim (LoadImageFrames) |
| entrada de matriz de bytes e fluxo | Limitado | Sim |
| Pré-processamento de imagem integrado | Não | Sim (mais de 9 filtros) |
| Saída em PDF pesquisável | Não | Sim (SaveAsSearchablePdf) |
| Modelo de objeto de resultado estruturado | Não (somente string XML) | Sim (páginas, parágrafos, palavras, caracteres) |
| Pontuações de confiança por palavra | Não (análise de atributos XML) | Sim (result.Confidence) |
| Coordenadas de pixel da palavra | análise de atributos XML | Propriedades fortemente tipadas |
| Contagem de idiomas | 20+ | 125+ |
| Seleção de linguagem fortemente tipificada | Não (códigos de string) | Sim (OcrLanguage enum) |
| Leitura de código de barras | Sim (tipo de reconhecimento separado) | Sim (flag de configuração) |
| Exportação hOCR | Não | Sim |
| Implantação multiplataforma | Binário manual por plataforma | O NuGet é compatível com todas as plataformas. |
| Docker / Linux / macOS | Configuração manual LD_LIBRARY_PATH |
Funciona perfeitamente assim que é conectado. |
| Compatibilidade com .NET | Limitado (ponte Java) | .NET Framework 4.6.2+, .NET 5–9 |
| Preço de entrada para uso do servidor | Enterprise (a partir de US$ 2.000) | $999 (Lite, todos os recursos) |
| Tipo de licença | Para obter informações sobre preços por nível, entre em contato com a equipe de vendas para Enterprise. | Perpétuo (compra única) |
Guia rápido: Migração doAsprise OCRpara o IronOCR
Passo 1: Substitua o pacote NuGet
Remover OCR Asprise:
dotnet remove package asprise-ocr-api
dotnet remove package asprise-ocr-api
Instale o IronOCR a partir da página de pacotes NuGet :
dotnet add package IronOcr
Etapa 2: Atualizar Namespaces
Substitua os namespaces Asprise pelo namespace IronOCR:
// Before (Asprise)
using asprise.ocr;
// After (IronOCR)
using IronOcr;
// Before (Asprise)
using asprise.ocr;
// After (IronOCR)
using IronOcr;
Imports IronOcr
Etapa 3: Inicializar a licença
Adicione a atribuição da chave de licença ao iniciar o aplicativo — em Program.cs antes de qualquer chamada OCR, em Startup.Configure, ou em um construtor estático:
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
Uma chave de avaliação gratuita está disponível na página de licenciamento do IronOCR . Durante o desenvolvimento e a avaliação, o IronOCR é executado sem chave e adiciona uma marca d'água de teste à saída.
Exemplos de migração de código
Remoção da configuração do caminho do JRE e da inicialização do mecanismo
Os aplicativos Asprise que são executados em Linux ou macOS normalmente incluem um código de inicialização que define o caminho do JRE ou valida a presença de binários nativos antes que qualquer trabalho de OCR seja iniciado. Essa infraestrutura não tem equivalente no IronOCR.
Abordagem OCR da Asprise:
// AppStartup.cs — native binary validation before accepting any requests
public static void InitializeOcr()
{
// Validate native library is reachable before first use
string nativePath = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
? Path.Combine(AppContext.BaseDirectory, "aocr_x64.dll")
: RuntimeInformation.IsOSPlatform(OSPlatform.Linux)
? "/usr/lib/libaocr.so"
: "/usr/local/lib/libaocr.dylib";
if (!File.Exists(nativePath))
throw new FileNotFoundException(
$"Asprise native binary not found: {nativePath}. " +
"Deploy the correct platform binary before starting.");
// Static global init — must run before any Ocr instance is created
Ocr.SetUp();
}
// AppStartup.cs — native binary validation before accepting any requests
public static void InitializeOcr()
{
// Validate native library is reachable before first use
string nativePath = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
? Path.Combine(AppContext.BaseDirectory, "aocr_x64.dll")
: RuntimeInformation.IsOSPlatform(OSPlatform.Linux)
? "/usr/lib/libaocr.so"
: "/usr/local/lib/libaocr.dylib";
if (!File.Exists(nativePath))
throw new FileNotFoundException(
$"Asprise native binary not found: {nativePath}. " +
"Deploy the correct platform binary before starting.");
// Static global init — must run before any Ocr instance is created
Ocr.SetUp();
}
Imports System
Imports System.IO
Imports System.Runtime.InteropServices
' AppStartup.vb — native binary validation before accepting any requests
Public Module AppStartup
Public Sub InitializeOcr()
' Validate native library is reachable before first use
Dim nativePath As String = If(RuntimeInformation.IsOSPlatform(OSPlatform.Windows),
Path.Combine(AppContext.BaseDirectory, "aocr_x64.dll"),
If(RuntimeInformation.IsOSPlatform(OSPlatform.Linux),
"/usr/lib/libaocr.so",
"/usr/local/lib/libaocr.dylib"))
If Not File.Exists(nativePath) Then
Throw New FileNotFoundException($"Asprise native binary not found: {nativePath}. " &
"Deploy the correct platform binary before starting.")
End If
' Static global init — must run before any Ocr instance is created
Ocr.SetUp()
End Sub
End Module
Abordagem IronOCR:
// Program.cs — license key assignment is the entire initialization
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
// That is it. Não binary validation, no path configuration, no SetUp() call.
// NuGet resolved the correct native runtime during package restore.
// Program.cs — license key assignment is the entire initialization
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
// That is it. Não binary validation, no path configuration, no SetUp() call.
// NuGet resolved the correct native runtime during package restore.
Imports IronOcr
' Program.vb — license key assignment is the entire initialization
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"
' That is it. Não binary validation, no path configuration, no SetUp() call.
' NuGet resolved the correct native runtime during package restore.
O padrão Asprise é tipicamente de 15 a 30 linhas em múltiplos arquivos — um validador de inicialização, um comutador de plataforma, uma exceção com uma mensagem de implantação, e a chamada SetUp(). O IronOCR substitui tudo isso por uma única tarefa. O guia de configuração do IronTesseract aborda opções de configuração de implantação para ambientes que exigem caminhos de tessdata personalizados ou operação offline.
Substituição do formato de saída XML por objetos de resultado estruturados
Asprise produz saída estruturada como uma string XML bruta quando OUTPUT_FORMAT_XML é especificado. Extrair o texto, as coordenadas e o nível de confiança dessa string requer código de análise XML. O IronOCR retorna um grafo de objetos tipados.
Abordagem OCR da Asprise:
// Asprise: structured output is an XML string — must parse manually
Ocr.SetUp();
Ocr ocr = new Ocr();
try
{
ocr.StartEngine("eng", Ocr.SPEED_FAST);
string xmlOutput = ocr.Recognize(
imagePath,
Ocr.RECOGNIZE_TYPE_TEXT,
Ocr.OUTPUT_FORMAT_XML); // Returns raw XML, not an object
// Parse the XML manually to extract words and coordinates
var doc = System.Xml.Linq.XDocument.Parse(xmlOutput);
var words = doc.Descendants("word")
.Select(w => new
{
Text = (string)w.Attribute("text"),
Confidence = (float)w.Attribute("confidence"),
X = (int)w.Attribute("x"),
Y = (int)w.Attribute("y"),
})
.ToList();
foreach (var word in words)
Console.WriteLine($"{word.Text} @ ({word.X},{word.Y}) conf={word.Confidence}");
}
finally
{
ocr.StopEngine();
}
// Asprise: structured output is an XML string — must parse manually
Ocr.SetUp();
Ocr ocr = new Ocr();
try
{
ocr.StartEngine("eng", Ocr.SPEED_FAST);
string xmlOutput = ocr.Recognize(
imagePath,
Ocr.RECOGNIZE_TYPE_TEXT,
Ocr.OUTPUT_FORMAT_XML); // Returns raw XML, not an object
// Parse the XML manually to extract words and coordinates
var doc = System.Xml.Linq.XDocument.Parse(xmlOutput);
var words = doc.Descendants("word")
.Select(w => new
{
Text = (string)w.Attribute("text"),
Confidence = (float)w.Attribute("confidence"),
X = (int)w.Attribute("x"),
Y = (int)w.Attribute("y"),
})
.ToList();
foreach (var word in words)
Console.WriteLine($"{word.Text} @ ({word.X},{word.Y}) conf={word.Confidence}");
}
finally
{
ocr.StopEngine();
}
Imports System.Xml.Linq
' Asprise: structured output is an XML string — must parse manually
Ocr.SetUp()
Dim ocr As New Ocr()
Try
ocr.StartEngine("eng", Ocr.SPEED_FAST)
Dim xmlOutput As String = ocr.Recognize(imagePath, Ocr.RECOGNIZE_TYPE_TEXT, Ocr.OUTPUT_FORMAT_XML) ' Returns raw XML, not an object
' Parse the XML manually to extract words and coordinates
Dim doc As XDocument = XDocument.Parse(xmlOutput)
Dim words = doc.Descendants("word") _
.Select(Function(w) New With {
.Text = CStr(w.Attribute("text")),
.Confidence = CSng(w.Attribute("confidence")),
.X = CInt(w.Attribute("x")),
.Y = CInt(w.Attribute("y"))
}) _
.ToList()
For Each word In words
Console.WriteLine($"{word.Text} @ ({word.X},{word.Y}) conf={word.Confidence}")
Next
Finally
ocr.StopEngine()
End Try
Abordagem IronOCR:
// IronOCR: structured result is a typed object — no XML parsing
var result = new IronTesseract().Read(imagePath);
foreach (var page in result.Pages)
{
foreach (var paragraph in page.Paragraphs)
{
foreach (var word in paragraph.Words)
{
Console.WriteLine(
$"{word.Text} @ ({word.X},{word.Y}) conf={word.Confidence:F1}%");
}
}
}
// IronOCR: structured result is a typed object — no XML parsing
var result = new IronTesseract().Read(imagePath);
foreach (var page in result.Pages)
{
foreach (var paragraph in page.Paragraphs)
{
foreach (var word in paragraph.Words)
{
Console.WriteLine(
$"{word.Text} @ ({word.X},{word.Y}) conf={word.Confidence:F1}%");
}
}
}
Imports IronOcr
' IronOCR: structured result is a typed object — no XML parsing
Dim result = New IronTesseract().Read(imagePath)
For Each page In result.Pages
For Each paragraph In page.Paragraphs
For Each word In paragraph.Words
Console.WriteLine($"{word.Text} @ ({word.X},{word.Y}) conf={word.Confidence:F1}%")
Next
Next
Next
Sem desserialização XML, sem conversão de atributos, sem suposições de esquema. O modelo de objeto OcrResult expõe páginas, parágrafos, linhas, palavras, e caracteres com propriedades tipadas. O guia de resultados de leitura abrange toda a hierarquia e o sistema de coordenadas, incluindo como filtrar por limite de confiança para fluxos de trabalho automatizados.
Processamento TIFF de múltiplos quadros
O Asprise aceita arquivos de imagem individuais. Um arquivo TIFF com vários quadros — comum em fluxos de trabalho de digitalização de documentos — precisa ser dividido em arquivos de quadro individuais antes que o Asprise possa processá-lo.IronOCR aceita TIFFs de múltiplos quadros diretamente através de LoadImageFrames.
Abordagem OCR da Asprise:
// Asprise: no multi-frame TIFF support — split frames externally first
// Using an external imaging library (e.g., System.Drawing or Magick.NET)
var frameFiles = new List<string>();
using (var tiff = System.Drawing.Image.FromFile("scanned-batch.tiff"))
{
int frameCount = tiff.GetFrameCount(System.Drawing.Imaging.FrameDimension.Page);
for (int i = 0; i < frameCount; i++)
{
tiff.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, i);
string framePath = $"frame_{i}.png";
tiff.Save(framePath);
frameFiles.Add(framePath);
}
}
// Now process each frame individually — sequential on LITE/STANDARD
var allText = new System.Text.StringBuilder();
Ocr.SetUp();
Ocr ocr = new Ocr();
try
{
ocr.StartEngine("eng", Ocr.SPEED_FAST);
foreach (var framePath in frameFiles)
{
string pageText = ocr.Recognize(
framePath,
Ocr.RECOGNIZE_TYPE_TEXT,
Ocr.OUTPUT_FORMAT_PLAINTEXT);
allText.AppendLine(pageText);
}
}
finally
{
ocr.StopEngine();
// Clean up temporary frame files
foreach (var f in frameFiles)
File.Delete(f);
}
Console.WriteLine(allText.ToString());
// Asprise: no multi-frame TIFF support — split frames externally first
// Using an external imaging library (e.g., System.Drawing or Magick.NET)
var frameFiles = new List<string>();
using (var tiff = System.Drawing.Image.FromFile("scanned-batch.tiff"))
{
int frameCount = tiff.GetFrameCount(System.Drawing.Imaging.FrameDimension.Page);
for (int i = 0; i < frameCount; i++)
{
tiff.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, i);
string framePath = $"frame_{i}.png";
tiff.Save(framePath);
frameFiles.Add(framePath);
}
}
// Now process each frame individually — sequential on LITE/STANDARD
var allText = new System.Text.StringBuilder();
Ocr.SetUp();
Ocr ocr = new Ocr();
try
{
ocr.StartEngine("eng", Ocr.SPEED_FAST);
foreach (var framePath in frameFiles)
{
string pageText = ocr.Recognize(
framePath,
Ocr.RECOGNIZE_TYPE_TEXT,
Ocr.OUTPUT_FORMAT_PLAINTEXT);
allText.AppendLine(pageText);
}
}
finally
{
ocr.StopEngine();
// Clean up temporary frame files
foreach (var f in frameFiles)
File.Delete(f);
}
Console.WriteLine(allText.ToString());
Imports System.Drawing
Imports System.Text
Imports System.IO
' Asprise: no multi-frame TIFF support — split frames externally first
' Using an external imaging library (e.g., System.Drawing or Magick.NET)
Dim frameFiles As New List(Of String)()
Using tiff As Image = Image.FromFile("scanned-batch.tiff")
Dim frameCount As Integer = tiff.GetFrameCount(Imaging.FrameDimension.Page)
For i As Integer = 0 To frameCount - 1
tiff.SelectActiveFrame(Imaging.FrameDimension.Page, i)
Dim framePath As String = $"frame_{i}.png"
tiff.Save(framePath)
frameFiles.Add(framePath)
Next
End Using
' Now process each frame individually — sequential on LITE/STANDARD
Dim allText As New StringBuilder()
Ocr.SetUp()
Dim ocr As New Ocr()
Try
ocr.StartEngine("eng", Ocr.SPEED_FAST)
For Each framePath As String In frameFiles
Dim pageText As String = ocr.Recognize(framePath, Ocr.RECOGNIZE_TYPE_TEXT, Ocr.OUTPUT_FORMAT_PLAINTEXT)
allText.AppendLine(pageText)
Next
Finally
ocr.StopEngine()
' Clean up temporary frame files
For Each f As String In frameFiles
File.Delete(f)
Next
End Try
Console.WriteLine(allText.ToString())
Abordagem IronOCR:
// IronOCR: multi-frame TIFF loads directly — no frame splitting, no temp files
using var input = new OcrInput();
input.LoadImageFrames("scanned-batch.tiff"); // All frames, one call
var result = new IronTesseract().Read(input);
// Access each page independently with its page number
foreach (var page in result.Pages)
Console.WriteLine($"Page {page.PageNumber}: {page.Text}");
// IronOCR: multi-frame TIFF loads directly — no frame splitting, no temp files
using var input = new OcrInput();
input.LoadImageFrames("scanned-batch.tiff"); // All frames, one call
var result = new IronTesseract().Read(input);
// Access each page independently with its page number
foreach (var page in result.Pages)
Console.WriteLine($"Page {page.PageNumber}: {page.Text}");
Imports IronOcr
' IronOCR: multi-frame TIFF loads directly — no frame splitting, no temp files
Using input As New OcrInput()
input.LoadImageFrames("scanned-batch.tiff") ' All frames, one call
Dim result = New IronTesseract().Read(input)
' Access each page independently with its page number
For Each page In result.Pages
Console.WriteLine($"Page {page.PageNumber}: {page.Text}")
Next
End Using
A abordagem Asprise requer dependência de imagem externa, gerenciamento de arquivos temporários, limpeza manual e processamento sequencial por quadro. O IronOCR processa todos os frames em uma única passagem. O guia de entrada TIFF e GIF aborda a seleção do intervalo de quadros para TIFFs grandes, onde apenas páginas específicas são necessárias.
Geração de PDF pesquisável
O Asprise não oferece a funcionalidade de gerar PDFs pesquisáveis em nenhum nível de licença. Criar um PDF com texto OCR incorporado a partir de um documento digitalizado requer uma biblioteca PDF externa, uma etapa OCR separada para obter as posições do texto e a construção manual da sobreposição. O IronOCR gera PDFs pesquisáveis diretamente a partir do resultado do reconhecimento.
Abordagem OCR da Asprise:
// Asprise: no searchable PDF output — external PDF library required
// Step 1: OCR the document to get text
Ocr.SetUp();
Ocr ocr = new Ocr();
string recognizedText;
try
{
ocr.StartEngine("eng", Ocr.SPEED_FAST);
recognizedText = ocr.Recognize(
"scanned-contract.jpg",
Ocr.RECOGNIZE_TYPE_TEXT,
Ocr.OUTPUT_FORMAT_PLAINTEXT); // Only plain text — no position data
}
finally
{
ocr.StopEngine();
}
// Step 2: Use an external PDF library to embed text over the image
// (iTextSharp, PdfSharp, or similar — adds another dependency and license)
// Text positioning requires coordinate data Asprise cannot provide in plain text mode
// ... 40-80 lines of PDF construction code
Console.WriteLine("Searchable PDF: not achievable with Asprise alone");
// Asprise: no searchable PDF output — external PDF library required
// Step 1: OCR the document to get text
Ocr.SetUp();
Ocr ocr = new Ocr();
string recognizedText;
try
{
ocr.StartEngine("eng", Ocr.SPEED_FAST);
recognizedText = ocr.Recognize(
"scanned-contract.jpg",
Ocr.RECOGNIZE_TYPE_TEXT,
Ocr.OUTPUT_FORMAT_PLAINTEXT); // Only plain text — no position data
}
finally
{
ocr.StopEngine();
}
// Step 2: Use an external PDF library to embed text over the image
// (iTextSharp, PdfSharp, or similar — adds another dependency and license)
// Text positioning requires coordinate data Asprise cannot provide in plain text mode
// ... 40-80 lines of PDF construction code
Console.WriteLine("Searchable PDF: not achievable with Asprise alone");
' Asprise: no searchable PDF output — external PDF library required
' Step 1: OCR the document to get text
Ocr.SetUp()
Dim ocr As New Ocr()
Dim recognizedText As String
Try
ocr.StartEngine("eng", Ocr.SPEED_FAST)
recognizedText = ocr.Recognize( _
"scanned-contract.jpg", _
Ocr.RECOGNIZE_TYPE_TEXT, _
Ocr.OUTPUT_FORMAT_PLAINTEXT) ' Only plain text — no position data
Finally
ocr.StopEngine()
End Try
' Step 2: Use an external PDF library to embed text over the image
' (iTextSharp, PdfSharp, or similar — adds another dependency and license)
' Text positioning requires coordinate data Asprise cannot provide in plain text mode
' ... 40-80 lines of PDF construction code
Console.WriteLine("Searchable PDF: not achievable with Asprise alone")
Abordagem IronOCR:
// IronOCR: searchable PDF in two lines — no external PDF library
var result = new IronTesseract().Read("scanned-contract.jpg");
result.SaveAsSearchablePdf("searchable-contract.pdf");
// Batch: convert a folder of scanned images to searchable PDFs
foreach (var imagePath in Directory.GetFiles("scans", "*.jpg"))
{
var batchResult = new IronTesseract().Read(imagePath);
string outputPath = Path.ChangeExtension(imagePath, ".searchable.pdf");
batchResult.SaveAsSearchablePdf(outputPath);
Console.WriteLine($"Converted: {outputPath}");
}
// IronOCR: searchable PDF in two lines — no external PDF library
var result = new IronTesseract().Read("scanned-contract.jpg");
result.SaveAsSearchablePdf("searchable-contract.pdf");
// Batch: convert a folder of scanned images to searchable PDFs
foreach (var imagePath in Directory.GetFiles("scans", "*.jpg"))
{
var batchResult = new IronTesseract().Read(imagePath);
string outputPath = Path.ChangeExtension(imagePath, ".searchable.pdf");
batchResult.SaveAsSearchablePdf(outputPath);
Console.WriteLine($"Converted: {outputPath}");
}
Imports System.IO
Imports IronOcr
' IronOCR: searchable PDF in two lines — no external PDF library
Dim result = New IronTesseract().Read("scanned-contract.jpg")
result.SaveAsSearchablePdf("searchable-contract.pdf")
' Batch: convert a folder of scanned images to searchable PDFs
For Each imagePath In Directory.GetFiles("scans", "*.jpg")
Dim batchResult = New IronTesseract().Read(imagePath)
Dim outputPath As String = Path.ChangeExtension(imagePath, ".searchable.pdf")
batchResult.SaveAsSearchablePdf(outputPath)
Console.WriteLine($"Converted: {outputPath}")
Next
O PDF pesquisável contém a imagem original como camada visual, com o texto OCR invisível sobreposto nas coordenadas corretas — o formato padrão para fluxos de trabalho de arquivamento e conformidade. Consulte o guia prático de PDF pesquisável e o exemplo de PDF pesquisável para opções que incluem a saída em PDF/A para arquivamento de longo prazo.
OCR assíncrono em aplicações web
A Asprise não possui uma API assíncrona. Os desenvolvedores o integram em aplicativos .NET assíncronos ao embrulhar chamadas síncronas em Task.Run, que consome threads do pool de threads e não elimina o bloqueio. O IronOCR oferece um caminho assíncrono nativo.
Abordagem OCR da Asprise:
// Asprise: no async API — must offload to Task.Run
// This blocks a thread pool thread during the entire OCR operation
// On LITE/STANDARD, concurrent Task.Run calls = license violation
public async Task<string> ProcessUploadAsync(Stream fileStream, string fileName)
{
string tempPath = Path.GetTempFileName();
await using (var fs = new FileStream(tempPath, FileMode.Create))
await fileStream.CopyToAsync(fs);
// Task.Run wraps synchronous Asprise — occupies a thread pool thread
// Two concurrent requests still violate LITE/STANDARD license
return await Task.Run(() =>
{
Ocr ocr = new Ocr();
try
{
ocr.StartEngine("eng", Ocr.SPEED_FAST);
return ocr.Recognize(
tempPath,
Ocr.RECOGNIZE_TYPE_TEXT,
Ocr.OUTPUT_FORMAT_PLAINTEXT);
}
finally
{
ocr.StopEngine();
File.Delete(tempPath);
}
});
}
// Asprise: no async API — must offload to Task.Run
// This blocks a thread pool thread during the entire OCR operation
// On LITE/STANDARD, concurrent Task.Run calls = license violation
public async Task<string> ProcessUploadAsync(Stream fileStream, string fileName)
{
string tempPath = Path.GetTempFileName();
await using (var fs = new FileStream(tempPath, FileMode.Create))
await fileStream.CopyToAsync(fs);
// Task.Run wraps synchronous Asprise — occupies a thread pool thread
// Two concurrent requests still violate LITE/STANDARD license
return await Task.Run(() =>
{
Ocr ocr = new Ocr();
try
{
ocr.StartEngine("eng", Ocr.SPEED_FAST);
return ocr.Recognize(
tempPath,
Ocr.RECOGNIZE_TYPE_TEXT,
Ocr.OUTPUT_FORMAT_PLAINTEXT);
}
finally
{
ocr.StopEngine();
File.Delete(tempPath);
}
});
}
Imports System.IO
Imports System.Threading.Tasks
' Asprise: no async API — must offload to Task.Run
' This blocks a thread pool thread during the entire OCR operation
' On LITE/STANDARD, concurrent Task.Run calls = license violation
Public Async Function ProcessUploadAsync(fileStream As Stream, fileName As String) As Task(Of String)
Dim tempPath As String = Path.GetTempFileName()
Await Using fs As New FileStream(tempPath, FileMode.Create)
Await fileStream.CopyToAsync(fs)
End Using
' Task.Run wraps synchronous Asprise — occupies a thread pool thread
' Two concurrent requests still violate LITE/STANDARD license
Return Await Task.Run(Function()
Dim ocr As New Ocr()
Try
ocr.StartEngine("eng", Ocr.SPEED_FAST)
Return ocr.Recognize(tempPath, Ocr.RECOGNIZE_TYPE_TEXT, Ocr.OUTPUT_FORMAT_PLAINTEXT)
Finally
ocr.StopEngine()
File.Delete(tempPath)
End Try
End Function)
End Function
Abordagem IronOCR:
// IronOCR: native async, concurrent requests permitted on all tiers
public async Task<string> ProcessUploadAsync(Stream fileStream, string fileName)
{
using var input = new OcrInput();
input.LoadImage(fileStream); // Stream input directly — no temp file
var ocr = new IronTesseract();
var result = await ocr.ReadAsync(input);
return result.Text;
}
// IronOCR: native async, concurrent requests permitted on all tiers
public async Task<string> ProcessUploadAsync(Stream fileStream, string fileName)
{
using var input = new OcrInput();
input.LoadImage(fileStream); // Stream input directly — no temp file
var ocr = new IronTesseract();
var result = await ocr.ReadAsync(input);
return result.Text;
}
Imports System.IO
Imports System.Threading.Tasks
' IronOCR: native async, concurrent requests permitted on all tiers
Public Async Function ProcessUploadAsync(fileStream As Stream, fileName As String) As Task(Of String)
Using input As New OcrInput()
input.LoadImage(fileStream) ' Stream input directly — no temp file
Dim ocr As New IronTesseract()
Dim result = Await ocr.ReadAsync(input)
Return result.Text
End Using
End Function
A versão IronOCR elimina a gravação de arquivo temporário, o embrulho Task.Run, e o comportamento de bloqueio de threads. Múltiplas solicitações simultâneas cada uma cria sua própria instância IronTesseract — a classe é sem estado e cada instância é independente. O guia de OCR assíncrono cobre padrões ReadAsync e suporte a token de cancelamento para operações em lote de longa duração em serviços hospedados.
Referência de mapeamento da API OCR da Asprise para o IronOCR
| Asprise OCR | Equivalente de IronOCR |
|---|---|
asprise.ocr namespace |
IronOcr namespace |
Ocr.SetUp() |
Não é necessário |
new Ocr() |
new IronTesseract() |
ocr.StartEngine("eng", Ocr.SPEED_FAST) |
Não é necessário |
ocr.StartEngine("eng+fra", speed) |
ocr.Language = OcrLanguage.English + OcrLanguage.French |
ocr.Recognize(path, type, format) |
ocr.Read(path) ou ocr.Read(input) |
Ocr.RECOGNIZE_TYPE_TEXT |
Comportamento padrão |
Ocr.RECOGNIZE_TYPE_BARCODE |
ocr.Configuration.ReadBarCodes = true |
Ocr.RECOGNIZE_TYPE_ALL |
ocr.Configuration.ReadBarCodes = true |
Ocr.OUTPUT_FORMAT_PLAINTEXT |
result.Text |
Ocr.OUTPUT_FORMAT_XML |
result.Pages / result.Pages[n].Words |
Ocr.OUTPUT_FORMAT_PDF |
result.SaveAsSearchablePdf(path) |
Ocr.SPEED_FASTEST |
ocr.Configuration.TesseractEngineMode ajuste |
Ocr.SPEED_FAST |
Configuração padrão |
Ocr.SPEED_SLOW |
Configurações de maior precisão |
ocr.StopEngine() |
Não é necessário — OcrInput é IDisposable |
result.StartsWith("ERROR:") verificação |
Tratamento de exceções padrão do .NET (try/catch) |
| DLL nativa da plataforma (aocr_x64.dll) | Pacote de tempo de execução NuGet (automático) |
| Arquivo temporário manual para entrada de fluxo | input.LoadImage(stream) diretamente |
| Biblioteca externa para TIFF com múltiplos quadros | input.LoadImageFrames(path) |
| Biblioteca externa para PDFs pesquisáveis | result.SaveAsSearchablePdf(path) |
Problemas e soluções comuns em migrações
Problema 1: DllNotFoundException após a remoção de binários nativos
Asprise OCR: Remover o pacote Asprise NuGet, mas deixar referências binárias nativas (nas regras de cópia de arquivos do projeto, instruções Docker COPY, ou scripts de implantação) pode causar a reemergência de DllNotFoundException de uma configuração obsoleta apontando para um binário inexistente.
Solução: Pesquisar artefatos de implantação por qualquer referência a configurações aocr, libaocr ou LD_LIBRARY_PATH e removê-las. O IronOCR não possui requisitos de configuração correspondentes. Não Dockerfile:
# Remove: COPY aocr_x64.dll /app/
# Remove: ENV LD_LIBRARY_PATH=/app
# IronOCR: nothing to add — NuGet handles native runtime packaging
RUN dotnet restore
RUN dotnet publish -c Release -o /app/publish
Para implantação multiplataforma, o guia de implantação do Docker abrange os requisitos básicos de imagem para o IronOCR em contêineres Linux.
Problema 2: Falha na Remoção de Ocr.SetUp() Prejudica a Inicialização
Asprise OCR: Ocr.SetUp() realiza inicialização global nativa. Algumas bases de código a chamam em um construtor estático ou Startup.Configure. Após a migração, remover o namespace Asprise remove o erro de compilação, mas se SetUp() estiver embrulhado em um try/catch que suprime a exceção, o código pode compilar e executar silenciosamente sem inicializar nada.
Solução: Grep para todas as chamadas SetUp() e remova todo o bloco de inicialização. Substitua o gancho de inicialização equivalente pela atribuição da chave de licença do IronOCR:
grep -rn "Ocr.SetUp\|StartEngine\|StopEngine" --include="*.cs" .
grep -rn "Ocr.SetUp\|StartEngine\|StopEngine" --include="*.cs" .
// Remove all occurrences of the engine lifecycle pattern:
// Ocr.SetUp();
// ocr.StartEngine(...);
// ocr.StopEngine();
// Replace application startup initialization with:
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
// Remove all occurrences of the engine lifecycle pattern:
// Ocr.SetUp();
// ocr.StartEngine(...);
// ocr.StopEngine();
// Replace application startup initialization with:
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
Problema 3: O código de análise de saída XML não possui substituto direto.
Asprise OCR: Código que analisa strings OUTPUT_FORMAT_XML usando XDocument, XmlReader, ou padrões regex não tem estrutura XML equivalente em IronOCR. O esquema XML gerado pelo Asprise não corresponde diretamente ao modelo de objetos do IronOCR.
Solução: Substitua o código de análise XML por acesso direto à propriedade em OcrResult. O mapeamento é:
// Asprise XML parsing (remove)
var words = XDocument.Parse(xmlOutput)
.Descendants("word")
.Select(w => new { Text = (string)w.Attribute("text"), X = (int)w.Attribute("x") });
//IronOCR object model (replace with)
var result = new IronTesseract().Read(imagePath);
var words = result.Pages
.SelectMany(p => p.Paragraphs)
.SelectMany(para => para.Words)
.Select(w => new { w.Text, w.X });
// Asprise XML parsing (remove)
var words = XDocument.Parse(xmlOutput)
.Descendants("word")
.Select(w => new { Text = (string)w.Attribute("text"), X = (int)w.Attribute("x") });
//IronOCR object model (replace with)
var result = new IronTesseract().Read(imagePath);
var words = result.Pages
.SelectMany(p => p.Paragraphs)
.SelectMany(para => para.Words)
.Select(w => new { w.Text, w.X });
Imports System.Xml.Linq
Imports IronOcr
' Asprise XML parsing (remove)
Dim words = XDocument.Parse(xmlOutput) _
.Descendants("word") _
.Select(Function(w) New With {Key .Text = CType(w.Attribute("text"), String), Key .X = CType(w.Attribute("x"), Integer)})
' IronOCR object model (replace with)
Dim result = New IronTesseract().Read(imagePath)
Dim words = result.Pages _
.SelectMany(Function(p) p.Paragraphs) _
.SelectMany(Function(para) para.Words) _
.Select(Function(w) New With {w.Text, w.X})
O guia de resultados de leitura abrange toda a hierarquia de objetos, incluindo dados em nível de caractere com caixas delimitadoras.
Problema 4: Wrappers Task.Run causando esgotamento do pool de threads
Asprise OCR: Aplicações web de alta concorrência que envolvem Asprise em Task.Run podem esgotar o pool de threads quando o volume de OCR aumenta. Cada Task.Run enfileirado retém um thread do pool de threads durante toda a operação OCR.
Solução: Substitua Task.Run(() => { asprise... }) padrões com chamadas assíncronas nativas do IronOCR. Cada instância IronTesseract é independente — crie uma por solicitação:
// Remove: await Task.Run(() => { ocr.Recognize(...) });
// Replace with:
using var input = new OcrInput();
input.LoadImage(stream);
var result = await new IronTesseract().ReadAsync(input);
return result.Text;
// Remove: await Task.Run(() => { ocr.Recognize(...) });
// Replace with:
using var input = new OcrInput();
input.LoadImage(stream);
var result = await new IronTesseract().ReadAsync(input);
return result.Text;
Imports IronTesseract
Using input As New OcrInput()
input.LoadImage(stream)
Dim result = Await (New IronTesseract()).ReadAsync(input)
Return result.Text
End Using
Problema 5: Validação de código de linguagem baseado em strings
Asprise OCR: Códigos de idioma são passados como strings ("eng", "fra", "eng+fra"). Aplicações que validam essas strings em tempo de execução — verificando contra uma lista codificada, lendo da configuração — precisam ser atualizadas quando o formato da string muda para o enum OcrLanguage.
Solução: Substitua parâmetros de linguagem em string por valores enum OcrLanguage. A seleção de idioma orientada por configuração se mapeia perfeitamente para Enum.Parse:
// Asprise string-based (remove)
string language = config["OcrLanguage"]; // e.g. "eng+fra"
ocr.StartEngine(language, Ocr.SPEED_FAST);
//IronOCR enum-based (replace with)
// For single language from config:
var ocr = new IronTesseract();
ocr.Language = Enum.Parse<OcrLanguage>(config["OcrLanguage"]); // e.g. "English"
var result = ocr.Read(input);
// Asprise string-based (remove)
string language = config["OcrLanguage"]; // e.g. "eng+fra"
ocr.StartEngine(language, Ocr.SPEED_FAST);
//IronOCR enum-based (replace with)
// For single language from config:
var ocr = new IronTesseract();
ocr.Language = Enum.Parse<OcrLanguage>(config["OcrLanguage"]); // e.g. "English"
var result = ocr.Read(input);
Imports System
Imports IronOcr
' Asprise string-based (remove)
Dim language As String = config("OcrLanguage") ' e.g. "eng+fra"
ocr.StartEngine(language, Ocr.SPEED_FAST)
' IronOCR enum-based (replace with)
' For single language from config:
Dim ocr As New IronTesseract()
ocr.Language = [Enum].Parse(Of OcrLanguage)(config("OcrLanguage")) ' e.g. "English"
Dim result = ocr.Read(input)
O guia de múltiplos idiomas lista todos os valores enum OcrLanguage válidos e seus pacotes de idiomas NuGet correspondentes.
Edição 6: A lógica de verificação de nível de licença não é mais necessária.
OCR da Asprise: Algumas bases de código de produção incluem verificações em tempo de execução que detectam o nível de licença da Asprise e serializam o trabalho de OCR quando executado em uma versão inferior à Enterprise. Essas proteções evitam violações de licença, mas aumentam a complexidade e reduzem a produtividade.
Solução: Remova todas as proteções de detecção de níveis e serialização. O IronOCR não possui restrições de threading em nenhum nível. Os padrões ConcurrentQueue, SemaphoreSlim, ou despachantes de um único thread usados para serializar chamadas Asprise não servem para nada após a migração:
// Remove: SemaphoreSlim _ocrLock = new SemaphoreSlim(1, 1);
// Remove: await _ocrLock.WaitAsync(); ... _ocrLock.Release();
// IronOCR: direct concurrent access, no guards needed
Parallel.ForEach(documentPaths, path =>
{
var text = new IronTesseract().Read(path).Text;
results[path] = text;
});
// Remove: SemaphoreSlim _ocrLock = new SemaphoreSlim(1, 1);
// Remove: await _ocrLock.WaitAsync(); ... _ocrLock.Release();
// IronOCR: direct concurrent access, no guards needed
Parallel.ForEach(documentPaths, path =>
{
var text = new IronTesseract().Read(path).Text;
results[path] = text;
});
Imports System.Threading.Tasks
' IronOCR: direct concurrent access, no guards needed
Parallel.ForEach(documentPaths, Sub(path)
Dim text = (New IronTesseract()).Read(path).Text
results(path) = text
End Sub)
Lista de verificação para migração do Asprise OCR
Pré-migração
Antes de escrever qualquer código de substituição, faça uma auditoria no código-fonte para verificar se há alguma utilização do Asprise:
# Find all files importing asprise namespace
grep -rn "using asprise" --include="*.cs" .
# Find all engine lifecycle calls
grep -rn "SetUp\|StartEngine\|StopEngine" --include="*.cs" .
# Find all integer constant references
grep -rn "RECOGNIZE_TYPE\|OUTPUT_FORMAT\|SPEED_FAST\|SPEED_SLOW" --include="*.cs" .
# Find native binary references in project files and deployment scripts
grep -rn "aocr\|libaocr" --include="*.csproj" --include="Dockerfile" --include="*.yml" .
# Find XML output parsing code
grep -rn "OUTPUT_FORMAT_XML\|XDocument.Parse\|Descendants.*word" --include="*.cs" .
# Find Task.Run wrappers around OCR calls
grep -rn "Task.Run.*ocr\|Task.Run.*Recognize" --include="*.cs" .
# Find all files importing asprise namespace
grep -rn "using asprise" --include="*.cs" .
# Find all engine lifecycle calls
grep -rn "SetUp\|StartEngine\|StopEngine" --include="*.cs" .
# Find all integer constant references
grep -rn "RECOGNIZE_TYPE\|OUTPUT_FORMAT\|SPEED_FAST\|SPEED_SLOW" --include="*.cs" .
# Find native binary references in project files and deployment scripts
grep -rn "aocr\|libaocr" --include="*.csproj" --include="Dockerfile" --include="*.yml" .
# Find XML output parsing code
grep -rn "OUTPUT_FORMAT_XML\|XDocument.Parse\|Descendants.*word" --include="*.cs" .
# Find Task.Run wrappers around OCR calls
grep -rn "Task.Run.*ocr\|Task.Run.*Recognize" --include="*.cs" .
Faça um levantamento dos resultados:
- Contar arquivos importando
asprise.ocr— todos eles precisam de atualizações de namespace - Listar todos os sites de chamada
StartEngine— cada um se torna uma chamadaRead - Identificar o código de análise sintática da saída XML — cada bloco precisa de substituição do modelo de objeto.
- Observe quaisquer proteções de nível de licença ou encapsulamentos de serialização — estes são removíveis.
- Localize os scripts de implantação de binários nativos e a configuração do contêiner.
Migração de código
- Remova o pacote NuGet
asprise-ocr-apide todos os projetos - Instale o pacote NuGet
IronOcrem cada projeto que execute OCR - Substitua
using asprise.ocrporusing IronOcrem todos os arquivos - Adicione
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"na inicialização do aplicativo. - Remova chamadas
Ocr.SetUp()de todo o código de inicialização e inicialização - Substitua todo bloco
Ocr.StartEngine/Recognize/StopEnginepornew IronTesseract().Read(path).Text - Substitua blocos de análise
OUTPUT_FORMAT_XMLpor tentativa de objetoresult.Pages - Substitua alternativas
OUTPUT_FORMAT_PDFporresult.SaveAsSearchablePdf(path) - Substitua código de divisão de TIFF multi-frame por
input.LoadImageFrames(tiffPath) - Substitua envoltórios baseados em fluxo
Task.Runporawait ocr.ReadAsync(input) - Remova
SemaphoreSlimou proteções de serialização que protegiam Asprise do uso simultâneo - Remova instruções de cópia de binário nativo de arquivos
.csproje Dockerfiles - Remova configurações
LD_LIBRARY_PATHda configuração do ambiente e scripts de CI - Substitua códigos de idioma em string (
"eng","eng+fra") por valores enumOcrLanguage - Substitua verificações
result.StartsWith("ERROR:")por blocostry/catch
Pós-migração
- Verifique se
dotnet buildconclui com zero avisos sobre bibliotecas nativas ausentes - Confirme que nenhuma ocorrência de
DllNotFoundExceptionouBadImageFormatExceptionocorre na inicialização em todos os ambientes alvo (Windows, Linux, Docker) - Execute o OCR em uma imagem representativa e confirme se o texto de saída corresponde à linha de base pré-migração.
- Testar o processamento TIFF de múltiplos quadros e verificar se todas as páginas são retornadas com a numeração correta.
- Gere um PDF pesquisável e verifique se o texto é selecionável e pesquisável em um visualizador de PDF.
- Enviar solicitações HTTP simultâneas para qualquer endpoint da API que invoque o OCR e confirmar se todas as solicitações foram concluídas sem erros.
- Verificar se os endpoints assíncronos retornam resultados sem deadlock sob carga concorrente.
- Confirmar se a extração de dados estruturados (coordenadas de palavras e nível de confiança) produz resultados corretos em um documento conhecido.
- Verifique o uso de memória da aplicação ao longo do tempo para confirmar a ausência de vazamentos de memória nativa (anteriormente causados por chamadas
StopEngine()perdidas) Execute a aplicação no Linux ou em um contêiner Docker para confirmar se a implantação multiplataforma funciona sem configuração binária.
Principais benefícios da migração para o IronOCR
A implantação se resume a uma única referência NuGet . Após a migração, todos os destinos de implantação — estações de trabalho de desenvolvimento, servidores de teste, contêineres Linux, agentes de CI — instalam o mesmo pacote com o mesmo comando. Não existe lógica de detecção de plataforma, nem busca de binários específicos para cada arquitetura, nem configuração de caminho de tempo de execução. Uma imagem Docker que anteriormente exigia instruções de cópia de binários nativos agora não requer nada além de dotnet restore. O guia de implantação do Linux e o guia de implantação do Azure incluem observações específicas do ambiente, quando aplicável.
Todos os Níveis de Licença Desbloqueiam Implantação de Nível de Servidor. A licença Lite $999 suporta APIs Web ASP.NET Core, Serviços Windows, Funções do Azure, AWS Lambda, e qualquer outra carga de trabalho .NET multi-thread. O recurso de threading de nível empresarial, pelo qual a Asprise cobra de US$ 2.000 a mais de US$ 5.000, está incluído em todos os planos do IronOCR. As equipes que migram do Asprise Enterprise para o IronOCR Lite reduzem seus custos de licenciamento de OCR, ao mesmo tempo que ganham recursos que o Enterprise não oferecia — PDF nativo, saída estruturada, geração de PDF pesquisável e 125 idiomas.
Resultados Estruturados de OCR Substituem Análise de String XML. O modelo de objeto OcrResult expõe uma hierarquia completa de documentos: páginas, parágrafos, linhas, palavras, e caracteres, cada um com coordenadas de caixa delimitadora precisas em pixel e escores de confiança. O código que anteriormente analisava strings XML do Asprise com XDocument ou regex passa a ter acesso direto às propriedades. A página de resultados do OCR aborda sistemas de coordenadas e como filtrar os resultados por nível de confiança para verificações de qualidade automatizadas.
Pré-processamento Integrado Remove Dependências de Imagem Externa. O pipeline de pré-processamento disponível através de OcrInput — Deskew, DeNoise, Contrast, Binarize, Sharpen, Dilate, Erode, Scale, Invert, e DeepCleanBackgroundNoise — elimina a biblioteca de imagens externa que as integrações Asprise requerem. Remover essa dependência elimina uma preocupação com a licença, reduz o fator de compilação e coloca a configuração de pré-processamento diretamente ao lado da configuração OCR no mesmo arquivo de código. A página de recursos de pré-processamento e o guia de correção de qualidade de imagem cobrem quando aplicar cada filtro e os ganhos de precisão mensuráveis que cada um proporciona em varreduras de baixa qualidade.
Async Nativo e Verdadeiro Paralelismo Melhoram a Taxa de Processamento. ReadAsync integra-se no padrão async/await sem bloqueio do pool de threads. O processamento em lote paralelo com Parallel.ForEach ou PLINQ escala linearmente com os núcleos disponíveis. Um lote de documentos que o Asprise Lite/STANDARD forçou a executar sequencialmente — 100 documentos a 2 segundos cada leva mais de 3 minutos — é executado em aproximadamente 25 segundos em uma máquina de 8 núcleos com o IronOCR. O exemplo de multithreading demonstra padrões de taxa de processamento paralela e mostra como usar ConcurrentBag para coleção de resultados segura para threads.
125+ Idiomas sem Distribuição Binária. Os pacotes de idiomas são instalados como pacotes NuGet — dotnet add package IronOcr.Languages.Arabic, dotnet add package IronOcr.Languages.Japanese — e implantados com o aplicativo como qualquer outra dependência. Não há pasta tessdata manual para preencher, nenhum binário de idioma para localizar e nenhuma configuração de caminho necessária na máquina de destino. O índice de idiomas lista todos os mais de 125 pacotes de idiomas disponíveis.
Perguntas frequentes
Por que devo migrar do SDK de OCR da Asprise para o IronOCR?
Entre os principais motivos, incluem-se a eliminação da complexidade da interoperabilidade COM, a substituição do gerenciamento de licenças baseado em arquivos, a eliminação da cobrança por página, a viabilização da implantação em Docker/contêineres e a adoção de um fluxo de trabalho nativo do NuGet que se integra às ferramentas padrão do .NET.
Quais são as principais alterações de código ao migrar do SDK de OCR da Asprise para o IronOCR?
Substitua as sequências de inicialização do OCR da Asprise pela instanciação do IronTesseract, remova o gerenciamento do ciclo de vida do COM (padrões explícitos de Criação/Carregamento/Fechamento) e atualize os nomes das propriedades de resultado. O resultado é uma redução significativa no número de linhas de código repetitivo.
Como faço para instalar o IronOCR para iniciar a migração?
Execute 'Install-Package IronOcr' no Console do Gerenciador de Pacotes ou 'dotnet add package IronOcr' na CLI. Os pacotes de idiomas são pacotes separados: 'dotnet add package IronOcr.Languages.French' para francês, por exemplo.
O IronOCR atinge a mesma precisão de OCR que o Asprise OCR SDK para documentos comerciais padrão?
O IronOCR alcança alta precisão para conteúdo comercial padrão, incluindo faturas, contratos, recibos e formulários digitados. Filtros de pré-processamento de imagem (correção de distorção, remoção de ruído, aprimoramento de contraste) melhoram ainda mais o reconhecimento em entradas de baixa qualidade.
Como o IronOCR lida com os dados de idioma que o SDK de OCR da Asprise instala separadamente?
Os dados de idioma no IronOCR são distribuídos como pacotes NuGet. O comando 'dotnet add package IronOcr.Languages.German' instala o suporte ao alemão. Não é necessário inserir arquivos manualmente nem configurar caminhos de diretório.
A migração do SDK de OCR da Asprise para o IronOCR requer alterações na infraestrutura de implantação?
O IronOCR requer menos alterações de infraestrutura do que o SDK de OCR da Asprise. Não há caminhos binários do SDK, necessidade de instalar arquivos de licença ou configurar servidores de licença. O pacote NuGet contém o mecanismo de OCR completo e a chave de licença é uma string definida no código do aplicativo.
Como configuro o licenciamento do IronOCR após a migração?
Atribua `IronOcr.License.LicenseKey = "YOUR-KEY"` no código de inicialização do aplicativo. No Docker ou Kubernetes, armazene a chave como uma variável de ambiente e leia-a na inicialização. Use `License.IsValidLicense` para validar a licença antes de aceitar o tráfego.
O IronOCR consegue processar PDFs da mesma forma que o Asprise OCR?
Sim. O IronOCR lê PDFs nativos e digitalizados. Instancie o IronTesseract, chame ocr.Read(input) onde input é um caminho para um PDF ou OcrPdfInput, e itere pelas páginas do OcrResult. Não é necessário um pipeline de renderização de PDF separado.
Como o IronOCR lida com multithreading em processamento de alto volume?
O IronTesseract pode ser instanciado com segurança por thread. Crie uma instância por thread em um Parallel.ForEach ou pool de Tasks, execute o OCR simultaneamente e descarte cada instância ao terminar. Não é necessário nenhum estado global ou bloqueio.
Quais formatos de saída o IronOCR suporta após a extração de texto?
O IronOCR retorna resultados estruturados, incluindo texto, coordenadas de palavras, níveis de confiança e estrutura da página. As opções de exportação incluem texto simples, PDF pesquisável e objetos de resultados estruturados para processamento posterior.
O preço do IronOCR é mais previsível do que o do SDK OCR da Asprise para dimensionamento de cargas de trabalho?
O IronOCR utiliza licenciamento perpétuo com preço fixo, sem cobranças por página ou volume. Independentemente de você processar 10.000 ou 10 milhões de páginas, o custo da licença permanece constante. As opções de licenciamento por volume e para equipes estão disponíveis na página de preços do IronOCR.
O que acontece com meus testes existentes após a migração do SDK de OCR da Asprise para o IronOCR?
Os testes que verificam o conteúdo de texto extraído devem continuar a ser aprovados após a migração. Os testes que validam padrões de chamadas de API ou o ciclo de vida de objetos COM precisarão ser atualizados para refletir o modelo de inicialização e resultados mais simples do IronOCR.

