Ir para o conteúdo do rodapé
VíDEOS

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

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
SHELL

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

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

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

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

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

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

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

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

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

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

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

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

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" .
SHELL
// 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";
$vbLabelText   $csharpLabel

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

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(() =&gt; { 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
$vbLabelText   $csharpLabel

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

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

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" .
SHELL

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 chamada Read
  • 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

  1. Remova o pacote NuGet asprise-ocr-api de todos os projetos
  2. Instale o pacote NuGet IronOcr em cada projeto que execute OCR
  3. Substitua using asprise.ocr por using IronOcr em todos os arquivos
  4. Adicione IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY" na inicialização do aplicativo.
  5. Remova chamadas Ocr.SetUp() de todo o código de inicialização e inicialização
  6. Substitua todo bloco Ocr.StartEngine / Recognize / StopEngine por new IronTesseract().Read(path).Text
  7. Substitua blocos de análise OUTPUT_FORMAT_XML por tentativa de objeto result.Pages
  8. Substitua alternativas OUTPUT_FORMAT_PDF por result.SaveAsSearchablePdf(path)
  9. Substitua código de divisão de TIFF multi-frame por input.LoadImageFrames(tiffPath)
  10. Substitua envoltórios baseados em fluxo Task.Run por await ocr.ReadAsync(input)
  11. Remova SemaphoreSlim ou proteções de serialização que protegiam Asprise do uso simultâneo
  12. Remova instruções de cópia de binário nativo de arquivos .csproj e Dockerfiles
  13. Remova configurações LD_LIBRARY_PATH da configuração do ambiente e scripts de CI
  14. Substitua códigos de idioma em string ("eng", "eng+fra") por valores enum OcrLanguage
  15. Substitua verificações result.StartsWith("ERROR:") por blocos try/catch

Pós-migração

  • Verifique se dotnet build conclui com zero avisos sobre bibliotecas nativas ausentes
  • Confirme que nenhuma ocorrência de DllNotFoundException ou BadImageFormatException ocorre 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 OcrInputDeskew, 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.

ObserveAsprise OCR, PDFSharp, Tesseract e iText são marcas registradas de seus respectivos proprietários. Este site não é afiliado, endossado ou patrocinado por Asprise, Google, empira Software GmbH, ou iText Group. Todos os nomes de produtos, logotipos e marcas são propriedade de seus respectivos proprietários. As comparações são apenas para fins informativos e refletem informações disponíveis publicamente no momento da redação.

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.

Kannaopat Udonpant
Engenheiro de Software
Antes de se tornar Engenheiro de Software, Kannapat concluiu um doutorado em Recursos Ambientais pela Universidade de Hokkaido, no Japão. Durante o doutorado, Kannapat também integrou o Laboratório de Robótica Veicular, que faz parte do Departamento de Engenharia de Bioprodução. Em 2022, ele utilizou suas habilidades ...
Leia mais

Equipe de Suporte Iron

Estamos online 24 horas por dia, 5 dias por semana.
Bater papo
E-mail
Liga para mim