IRONSOFTWAREHOME
VIDEOS

Migración de Tesseract.NET SDK a IronOCR

Kannaopat Udonpant
Kannapat Udonpant
Updated: 1 de agosto de 2026

Esta guía guía a los desarrolladores de .NET a través de una migración concreta de SDK de Tesseract .NET (Tesseract.Net.SDK, namespace Patagames.Ocr) a IronOCR. Se centra específicamente en equipos que trasladan patrones de inicialización de la era del .NET Framework, expresiones idiomáticas de eliminación heredadas y canalizaciones exclusivamente sincrónicas a un entorno que ahora funciona con .NET 8, contenedores Linux y marcos web que priorizan la asincronía. Si su servicio OCR compila contra net472 y falla en el momento en que alguien agrega <TargetFramework>net8.0</TargetFramework> al .csproj, esta guía está escrita para usted.

¿Por qué migrar desde Tesseract.NET SDK?

El SDK de Patagames aportó un valor real cuando .NET Framework 4.5 era la base de implementación y Windows Server era el único destino. Ese contexto ha cambiado. La mayoría de las organizaciones ahora contenedorizan los servicios, ejecutan la integración continua (CI) en entornos Linux y se estandarizan en .NET 6, 8 o 9. SDK de Tesseract .NET no puede seguirles el ritmo.

Límite duro en .NET Framework 4.5. El paquete tiene como destino net20 a través de net45. No produce ni netstandard ni ensamblaje net6.0. Un archivo de proyecto que incluye Tesseract.Net.SDK no puede establecer <TargetFramework>net8.0</TargetFramework>. La actualización de .NET que el resto del código fuente completa en un sprint se queda atascada indefinidamente en la capa de OCR.

Sin ruta de contenedor. El SDK incluye llamadas P/Invoke exclusivas de Windows en binarios nativos de Windows. En cualquier imagen base de Linux — mcr.microsoft.com/dotnet/aspnet:8.0, ubuntu:22.04, alpine:3.19 — la aplicación lanza DllNotFoundException antes de procesar un solo documento. Los contenedores de Windows existen como solución alternativa, pero conllevan imágenes de mayor tamaño, un coste de licencia adicional y la incompatibilidad con la mayoría de los servicios gestionados de Kubernetes que utilizan por defecto grupos de nodos Linux.

API solo sincrónica bloquea los pipelines de ASP.NET Core. El método OcrApi.GetTextFromImage() es sincrónico. En .NET Core, llamar a operaciones síncronas que bloquean los subprocesos de solicitud degrada el rendimiento bajo carga y conlleva el riesgo de agotamiento del grupo de subprocesos.IronOCR proporciona ReadAsync() para integración no bloqueante. Consulte la guía de OCR asíncrono para ver el patrón.

La creación de motor por solicitud consume memoria. El código de .NET Framework comúnmente crea una instancia OcrApi por llamada al método o por solicitud, desechándola al salir. Se trata de la gestión del ciclo de vida de .NET Framework. También es caro: cada Init() carga 40–100 MB de datos de idioma. Diez solicitudes simultáneas cargan el mismo modelo de lenguaje diez veces. El IronTesseract de IronOCR es seguro para el uso por hilos — una instancia vive durante la vida útil de la aplicación y atiende a todos los llamadores concurrentes desde una sola carga de modelo de idioma.

Los patrones de eliminación heredados acumulan riesgos. El uso correcto del SDK requiere un using (var api = OcrApi.Create()) { ... } statement that predates declaraciones de var. Las bases de código escritas antes de C# 8.0 a menudo incluyen try/finally patrones de disposición o, en casos de errores, ninguna disposición en absoluto. Esos patrones se compilan y se ejecutan en .NET Framework, pero conllevan una deuda técnica que impide una refactorización moderna.

No async, no DI, no inicio moderno. El SDK no tiene concepto de integración de inyección de dependencias, vida útil del servicio alojado, o configuración de IOptions<T>. Su integración en una aplicación .NET Core requiere el registro manual del servicio y evitar cuidadosamente la instanciación por solicitud.IronOCR se integra perfectamente como un servicio singleton en el contenedor DI estándar.

El problema fundamental

// Tesseract.NET SDK: .NET Framework 4.5 ceiling — will not compile on net8.0
// Every project referencing this package is locked below the upgrade line
using Patagames.Ocr;  // Patagames.Ocr targets net45; no netstandard or net8 assembly

public class OcrService
{
    public string ProcessDocument(string imagePath)
    {
        // Synchronous-only — blocks ASP.NET Core request threads
        // No DI support — must be instantiated manually each time
        using (var api = OcrApi.Create())    // C# 1.0 using statement, 40-100MB load per call
        {
            api.Init(Languages.English);
            return api.GetTextFromImage(imagePath);
        }
        // Project cannot target net6.0, net8.0, or any Linux container base image
    }
}
C#
// IronOCR: same logic, any runtime from net462 to net9.0, any platform
using IronOcr;  // Single NuGet, supports .NET Framework 4.6.2+, .NET 5/6/7/8/9

// Register once as singleton — load language model once, share across all requests
// Call ReadAsync() in ASP.NET Core for non-blocking operation
var ocr = new IronTesseract();
var result = await ocr.ReadAsync("document.jpg");  // Async-first, no thread blocking
Console.WriteLine(result.Text);
C#

IronOCR frente a Tesseract.NET SDK: comparación de características

La tabla siguiente recoge las capacidades directamente relevantes para una migración de modernización de .NET.

CaracterísticaSDK de Tesseract .NETIronOCR
.NET Framework 2.0-4.5No
.NET Framework 4.6.2-4.8No
.NET Core 2.x / 3.xNo
.NET 5No
.NET 6No
.NET 7No
.NET 8No
.NET 9No
Implementación de Windows
Implementación de LinuxNo
Implementación de macOSNo
Contenedores Linux de DockerNo
Azure App Service (Linux)No
AWS LambdaNo
API asíncrona (ReadAsync)No
Instancia única segura para subprocesosNo
Integración de DI en ASP.NET Core.NET CoreManualServicio Singleton
Entrada nativa de PDFNo
Preprocesamiento integradoNo
Salida en PDF con capacidad de búsquedaNo
Datos estructurados (palabras, líneas, párrafos)No
Soporte comercial / SLANo (desarrollador individual)
Precio de la licencia perpetua~20–50 $ (un solo desarrollador)Desde $999

Inicio rápido: Migración de SDK de Tesseract .NET a IronOCR

Paso 1: Sustituir el paquete NuGet

Eliminar Tesseract.NET SDK:

dotnet remove package Tesseract.Net.SDK
SHELL

Si se instaló PdfiumViewer o una biblioteca de renderización de PDF similar con el único fin de proporcionar páginas PDF al SDK, elimínela también;IronOCR lee archivos PDF de forma nativa:

dotnet remove package PdfiumViewer
SHELL

Instala IronOCR desde NuGet :

dotnet add package IronOcr

Paso 2: Actualizar los espacios de nombres

// Before (Tesseract.NET SDK)
using Patagames.Ocr;
using Patagames.Ocr.Enums;

// After (IronOCR)
using IronOcr;
C#

Paso 3: Inicializar licencia

Agregue la llamada de clave de licencia una vez en el inicio de la aplicación — en Program.cs, Startup.cs, o en el host builder de la aplicación:

IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";

Hay disponible una licencia de prueba gratuita para evaluar el producto sin marcas de agua.

Ejemplos de migración de código

Patrón de inicio de .NET Framework para Modern Host Builder

Las aplicaciones de .NET Framework generalmente inicializan el motor OCR en un constructor estático, un evento Application_Start, o un manejador Global.asax. Ninguna de estas funciones existe en las aplicaciones .NET 6+ creadas sobre el modelo de host genérico.

Enfoque del SDK de Tesseract.NET:

// Global.asax.cs — .NET Framework MVC application
// OcrApi lifecycle managed manually; no DI container involved
public class MvcApplication : System.Web.HttpApplication
{
    // Static field — one engine for the app lifetime
    // But: NOT thread-safe; concurrent requests share a single OcrApi instance
    private static OcrApi _globalApi;

    protected void Application_Start()
    {
        // Initialize OCR engine on app startup
        // Path to tessdata hardcoded for deployment environment
        _globalApi = OcrApi.Create();
        _globalApi.Init(Languages.English);

        AreaRegistration.RegisterAllAreas();
        RouteConfig.RegisterRoutes(RouteTable.Routes);
    }

    protected void Application_End()
    {
        // Must manually dispose on shutdown
        _globalApi?.Dispose();
    }
}
C#

Enfoque IronOCR:

// Program.cs — .NET 8ASP.NET Core application
// IronTesseract es seguro para subprocesos; register as singleton, inject where needed
var builder = WebApplication.CreateBuilder(args);

IronOcr.License.LicenseKey = builder.Configuration["IronOcr:LicenseKey"];

// Register as singleton — one instance, thread-safe, shared across all requests
builder.Services.AddSingleton<IronTesseract>();

builder.Services.AddControllers();

var app = builder.Build();
app.MapControllers();
app.Run();
C#

El patrón Global.asax desaparece completamente. IronTesseract se registra como un servicio singleton estándar, inyectado en controladores y servicios a través del constructor. El modelo de idioma se carga una vez al iniciarlo y permanece en la memoria durante toda la vida útil de la aplicación. La guía de configuración de IronTesseract describe las opciones de configuración, incluida la selección de idioma y el modo del motor en el momento del registro.

Modernización del patrón de eliminación de sistemas heredados

El código de .NET Framework 2.0 utiliza la declaración de bloque using (var x = ...) { }. C# 8.0 introdujo declaraciones using var que delimitan la disposición al bloque envolvente. Las bases de código más antiguas también llevan try/finally guardas de disposición escritas cuando las declaraciones using no se confiaban en todos los escenarios. Todos estos patrones indican código escrito para .NET Framework y deben modernizarse durante la migración.

Enfoque del SDK de Tesseract.NET:

// .NET Framework 4.x disposal patterns — three variants encountered in production
public class LegacyOcrProcessor
{
    // Pattern 1: try/finally guard (pre-C# 2.0 style, still common in legacy code)
    public string ProcessWithTryFinally(string imagePath)
    {
        OcrApi api = null;
        try
        {
            api = OcrApi.Create();
            api.Init(Languages.English);
            return api.GetTextFromImage(imagePath);
        }
        finally
        {
            if (api != null)
                api.Dispose();  // Manualnull check required
        }
    }

    // Pattern 2: nested using blocks — one for engine, one for image object
    public string ProcessWithNestedUsing(string imagePath)
    {
        using (var api = OcrApi.Create())
        {
            api.Init(Languages.English);
            using (var img = OcrImage.FromFile(imagePath))
            {
                api.SetImage(img);
                return api.GetText();
            }   // img disposed here
        }       // api disposed here — nested indentation grows with each resource
    }

    // Pattern 3: missing disposal — memory leak, common in older service code
    public string ProcessUnsafe(string imagePath)
    {
        var api = OcrApi.Create();   // WARNING: never disposed
        api.Init(Languages.English);
        return api.GetTextFromImage(imagePath);
    }
}
C#

Enfoque IronOCR:

// Modern C# 8.0+ disposal — flat, readable, no nesting
public class ModernOcrProcessor
{
    private readonly IronTesseract _ocr;  // Injected singleton, never disposed per-request

    public ModernOcrProcessor(IronTesseract ocr) => _ocr = ocr;

    // Pattern 1: using var declaration — scoped to method, no nesting
    public string ProcessDocument(string imagePath)
    {
        using var input = new OcrInput();  // OcrInput is the disposable resource, not the engine
        input.LoadImage(imagePath);
        return _ocr.Read(input).Text;
    }   // input disposed here automatically — no nesting, no try/finally

    // Pattern 2: multiple inputs in one scope — still flat
    public string ProcessMultipleInputs(string imagePath, string pdfPath)
    {
        using var imageInput = new OcrInput();
        imageInput.LoadImage(imagePath);

        using var pdfInput = new OcrInput();
        pdfInput.LoadPdf(pdfPath);

        var imageText = _ocr.Read(imageInput).Text;
        var pdfText = _ocr.Read(pdfInput).Text;

        return $"{imageText}\n{pdfText}";
    }   // both inputs disposed here — zero nesting
}
C#

OcrInput es el único recurso desechable en IronOCR. El motor mismo (IronTesseract) no se desecha por solicitud — es un singleton. Esto elimina la recarga del modelo de idioma de 40–100 MB por solicitud que imponían OcrApi.Create() + api.Init(). La guía de entrada de imágenes cubre todos los métodos de carga de OcrInput, incluidos flujos, matrices de bytes y URLs.

Integración asíncrona para controladores ASP.NET Core

Tesseract.NET SDK no tiene API asíncrona. Todas las llamadas son síncronas. En .NET Core, llamar a operaciones de bloqueo síncronas desde acciones de controlador asíncronas supone un riesgo de agotamiento del grupo de subprocesos bajo carga. La solución común — envolver llamadas síncronas en Task.Run() — delega el trabajo de bloqueo a un hilo del pool de hilos pero no elimina el consumo de hilos. El ReadAsync() de IronOCR proporciona una integración genuina de I/O asíncrono.

Enfoque del SDK de Tesseract.NET:

// ASP.NET Core controller — forced workaround for synchronous OCR API
[ApiController]
[Route("api/ocr")]
public class OcrController : ControllerBase
{
    [HttpPost("extract")]
    public async Task<IActionResult> ExtractText(IFormFile file)
    {
        // Must copy upload to temp file — OcrApi does not accept streams directly
        var tempPath = Path.GetTempFileName();
        await using (var stream = System.IO.File.OpenWrite(tempPath))
            await file.CopyToAsync(stream);

        string text;
        try
        {
            // Task.Run wraps synchronous call — still consumes a thread-pool thread
            // Does NOT free the calling thread during OCR processing
            text = await Task.Run(() =>
            {
                using (var api = OcrApi.Create())   // 40-100MB load per request
                {
                    api.Init(Languages.English);
                    return api.GetTextFromImage(tempPath);  // synchronous, blocking
                }
            });
        }
        finally
        {
            System.IO.File.Delete(tempPath);  // Manualtemp file cleanup
        }

        return Ok(new { text });
    }
}
C#

Enfoque IronOCR:

// ASP.NET Core controller — genuine async OCR, no temp files, no thread blocking
[ApiController]
[Route("api/ocr")]
public class OcrController : ControllerBase
{
    private readonly IronTesseract _ocr;  // Singleton injected via DI

    public OcrController(IronTesseract ocr) => _ocr = ocr;

    [HttpPost("extract")]
    public async Task<IActionResult> ExtractText(IFormFile file)
    {
        // Load stream directly — no temp file needed
        using var input = new OcrInput();
        input.LoadImage(file.OpenReadStream());  // Stream input, no disk write

        // ReadAsync — genuinely non-blocking, integrates with ASP.NET Core pipeline
        var result = await _ocr.ReadAsync(input);

        return Ok(new
        {
            text = result.Text,
            confidence = result.Confidence
        });
    }
}
C#

El ciclo de ida y vuelta del archivo temporal desaparece. El envoltorio Task.Run desaparece. Desaparecen el OcrApi.Create() por solicitud y la carga de 40–100 MB que la seguía. La guía práctica de OCR asíncrono y la guía de entrada de flujos documentan el proceso asíncrono completo, incluida la compatibilidad con tokens de cancelación.

Procesamiento de archivos TIFF multifotograma

El artículo comparativo de la Fase 1 cubrió el procesamiento básico de imágenes y PDF. El formato TIFF multiframe es un caso concreto muy común en el archivo de documentos, los sistemas de fax y los procesos de imágenes médicas. SDK de Tesseract .NET requiere iterar manualmente los cuadros TIFF utilizando System.Drawing.Bitmap, extrayendo cada cuadro a un archivo PNG temporal, ejecutando OCR en el archivo temporal y limpiando. El patrón obliga a llamadas explícitas a GC en documentos grandes para evitar errores de falta de memoria.

Enfoque del SDK de Tesseract.NET:

// Multi-frame TIFF: manual frame extraction to temp files + forced GC
using System.Drawing;
using System.Drawing.Imaging;
using Patagames.Ocr;

public List<string> ProcessMultiFrameTiff(string tiffPath)
{
    var pageTexts = new List<string>();

    using (var api = OcrApi.Create())
    {
        api.Init(Languages.English);

        using (var bitmap = new Bitmap(tiffPath))
        {
            var dimension = new FrameDimension(bitmap.FrameDimensionsList[0]);
            int frameCount = bitmap.GetFrameCount(dimension);

            for (int i = 0; i < frameCount; i++)
            {
                bitmap.SelectActiveFrame(dimension, i);

                // Must write each frame to a temp file — no in-memory path
                var tempPath = Path.GetTempFileName() + ".png";
                bitmap.Save(tempPath, ImageFormat.Png);

                try
                {
                    pageTexts.Add(api.GetTextFromImage(tempPath));
                }
                finally
                {
                    File.Delete(tempPath);  // Manualcleanup on every frame
                }

                // Force GC every 10 frames — workaround for memory pressure
                // Slows processing; indicates memory management is manual
                if (i % 10 == 0)
                {
                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                }
            }
        }
    }

    return pageTexts;
}
C#

Enfoque IronOCR:

// Multi-frame TIFF: one method call, no temp files, no manual GC
using IronOcr;

public List<string> ProcessMultiFrameTiff(string tiffPath)
{
    var ocr = new IronTesseract();

    using var input = new OcrInput();
    input.LoadImageFrames(tiffPath);  // Loads all frames natively — no temp files

    var result = ocr.Read(input);

    // Pages map directly to TIFF frames
    return result.Pages.Select(page => page.Text).ToList();
}
C#

De treinta líneas se reducen a ocho. No hay archivos temporales, no hay iteración de cuadros Bitmap, no hay llamadas GC.Collect(). LoadImageFrames maneja TIFFs multiframes de tamaño arbitrario sin escribir archivos intermedios. La guía de entrada de TIFF y GIF cubre la carga selectiva de fotogramas (por rango de índice) y las llamadas de retorno de progreso para documentos de gran tamaño.

Preparación para la implementación de contenedores Docker

El código del SDK de Tesseract.NET que se ejecuta en el equipo Windows de un desarrollador falla en el paso de compilación o ejecución de Docker cuando la imagen base es Linux. La solución no consiste en un ajuste del Dockerfile: los binarios nativos son exclusivos de Windows y no se pueden cargar en Linux en absoluto. El soporte de Linux de IronOCR requiere una pequeña adición apt-get al Dockerfile y nada más en el código de la aplicación.

Enfoque del SDK de Tesseract.NET:

# Dockerfile attempt — fails at runtime on Linux base image
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
# This base image is Linux (Debian) by default
# Tesseract.Net.SDK's Windows native DLLs cannot load here
# Application throws DllNotFoundException on first OCR call

WORKDIR /app
COPY --from=build /app/publish .

# Even copying the Windows tessdata folder has no effect —
# the P/Invoke DLL cannot be loaded regardless of file placement
COPY tessdata/ ./tessdata/

ENTRYPOINT ["dotnet", "MyApp.dll"]
# Runtime error: DllNotFoundException: Unable to load DLL 'libtesseract'
# No fix available within Tesseract.Net.SDK — requires replacing the library
Text

Enfoque IronOCR:

# Dockerfile for IronOCR on Linux — add one apt-get line, nothing else changes
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base

# Required system dependency for IronOCR on Debian/Ubuntu base images
RUN apt-get update && apt-get install -y libgdiplus \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app
COPY --from=build /app/publish .

# No tessdata folder — language data is bundled with the IronOcr NuGet packages
# No platform check code —IronOCR runs identically on Windows and Linux

ENTRYPOINT ["dotnet", "MyApp.dll"]
Text

Una línea apt-get. No hay carpeta tessdata. No hay código condicional a la plataforma en la aplicación. El mismo binario de la aplicación que se ejecuta en el equipo Windows de un desarrollador se ejecuta en este contenedor Linux sin modificaciones. La guía de implementación de Docker cubre imágenes basadas en Alpine (que utilizan apk en lugar de apt-get), optimización de construcción multi-etapa, y configuración de variables de entorno para la clave de licencia. La guía de implementación de Linux cubre escenarios de Linux en máquina física y WSL2.

Referencia de mapeo de la API del SDK de Tesseract.NET a IronOCR

SDK de Tesseract .NETEquivalente a IronOCRNotas
Install-Package Tesseract.Net.SDKdotnet add package IronOcrIronOCR está destinado a .NET Framework 4.6.2+ y .NET 5–9
using Patagames.Ocr;using IronOcr;Espacio de nombres único
using Patagames.Ocr.Enums;(not needed)Los enums están en el namespace IronOcr
OcrApi.Create()new IronTesseract()IronTesseract es seguro para subprocesos; utilizar como singleton
api.Init(Languages.English)ocr.Language = OcrLanguage.EnglishAsignación de propiedades, no llamada a métodos
api.Init(Languages.English | Idiomas.Alemán)ocr.Language = OcrLanguage.English + OcrLanguage.GermanOperador +, no OR bit a bit
api.GetTextFromImage(path)ocr.Read("path.jpg").TextDirecto o a través de OcrInput
api.GetTextFromImage(path) (async)await ocr.ReadAsync(input)Genuino async — no se necesita envoltura Task.Run
OcrImage.FromFile(path)input.LoadImage(path)OcrInput reemplaza a OcrImage
OcrImage.FromBitmap(bitmap)input.LoadImage(bitmap)
new MemoryStream(bytes)OcrImage.FromBitmapinput.LoadImage(bytes)Compatibilidad directa con matrices de bytes
api.SetImage(img); api.GetText()ocr.Read(input).TextOcrInput se pasa a Read
api.GetMeanConfidence()result.ConfidenceDevuelve un porcentaje; also available per-word
api.SetRectangle(x, y, w, h)input.LoadImage(path, new CropRectangle(x, y, w, h))OCR basado en regiones a través de CropRectangle
api.SetVariable("tessedit_char_whitelist", x)ocr.Configuration.WhiteListCharacters = x
api.SetVariable("tessedit_char_blacklist", x)ocr.Configuration.BlackListCharacters = x
Iteración de fotogramas de mapa de bits + archivo temporalinput.LoadImageFrames(tiffPath)Compatibilidad nativa con TIFF multiframe
(synchronous only)result.SaveAsSearchablePdf("out.pdf")No hay equivalente en SDK de Tesseract .NET
(no structured output)result.Pages, result.Words, result.LinesCoordenadas a nivel de palabra y nivel de confianza
Soluciones alternativas GC.Collect()(not needed)IronOCR gestiona la memoria internamente
Verificación de plataforma: IsOSPlatform(Windows)(remove entirely)IronOCR es multiplataforma
Gestión de carpetas de Tessdata(remove entirely)Idiomas incluidos en los paquetes NuGet

Problemas comunes de migración y soluciones

Problema 1: Conflicto entre los marcos de trabajo de los proyectos

Tesseract.NET SDK: Después de eliminar Tesseract.Net.SDK y agregar IronOcr, el proyecto todavía está dirigido por net45 o net472 del requisito antiguo.IronOCR soporta net462 y posteriores, por lo que los proyectos net45 necesitan actualizar el framework objetivo antes de que el paquete se restaure correctamente.

Solución: Actualice el <TargetFramework> en el archivo .csproj antes de agregar IronOCR. Si el proyecto debe ser compatible tanto con entornos de ejecución antiguos como nuevos durante una migración por fases, utilice la traducción multiobjetivo:

<!-- Single modern target (preferred) -->
<TargetFramework>net8.0</TargetFramework>

<!-- Multi-targeting during phased migration — supports both simultaneously -->
<TargetFrameworks>net462;net8.0</TargetFrameworks>
XML

IronOCR determina automáticamente el ensamblado correcto para cada destino. El mismo comando dotnet add package IronOcr funciona para ambos. La página de la biblioteca OCR de .NET enumera todos los marcos de trabajo compatibles.

Problema 2: Campo OcrApi estático sustituido por DI Singleton

Tesseract.NET SDK: El código heredado registra una sola instancia OcrApi como un campo estático (en Global.asax, un localizador de servicios estático, o una clase envoltura singleton). Este patrón era necesario porque OcrApi no es seguro para hilos — compartir una instancia entre hilos causa condiciones de carrera, por lo que el campo estático estaba protegido por un lock o realmente fue recreado por solicitud a pesar del nombre del campo.

Solución: Registrar IronTesseract como un verdadero singleton seguro para hilos a través del contenedor DI. Eliminar el bloqueo, eliminar el campo estático, eliminar cualquier recreación por solicitud:

// Remove: private static OcrApi _instance; / private static readonly object _lock = new();

// Replace with DI registration in Program.cs
builder.Services.AddSingleton<IronTesseract>();

// In consuming classes — constructor injection
public class DocumentProcessor
{
    private readonly IronTesseract _ocr;
    public DocumentProcessor(IronTesseract ocr) => _ocr = ocr;

    public async Task<string> ProcessAsync(string path)
    {
        using var input = new OcrInput();
        input.LoadImage(path);
        var result = await _ocr.ReadAsync(input);
        return result.Text;
    }
}
C#

Problema 3: Falta la carpeta Tessdata tras la implementación

Tesseract.NET SDK: Tras cambiar a IronOCR, los equipos a veces dejan los pasos de implementación de tessdata en los flujos de CI/CD. La carpeta tessdata/ referenciada en scripts de construcción y manifiestos de implementación ya no existe — era parte de la gestión de modelos de idioma del antiguo SDK. Los scripts fallan cuando intentan copiar o verificar una carpeta que ya no existe.

Solución: Eliminar todas las referencias a tessdata de scripts de implementación, objetivos de copia .csproj, comandos Docker COPY, y pasos de pipeline CI/CD. Los datos de idioma de IronOCR se distribuyen junto con los paquetes NuGet. Ejecutar dotnet restore y los datos de idioma estarán disponibles. No se necesita nada más:

# Remove from CI/CD pipeline
# BEFORE (delete these lines):
# - cp -r tessdata/ $DEPLOY_PATH/tessdata/
# - test -f $DEPLOY_PATH/tessdata/eng.traineddata

# AFTER: nothing — language data is in the NuGet package restore output
dotnet restore   # Downloads IronOcr and any IronOcr.Languages.* packages
dotnet publish   # Includes language data automatically
SHELL

La guía de idiomas múltiples describe la instalación de paquetes de idiomas específicos como paquetes NuGet para implementaciones sin conexión o en entornos aislados.

Problema 4: BadImageFormatException en desajuste 32/64-bit

Tesseract.NET SDK: El SDK incluye binarios nativos de Windows para x86 y x64 por separado. Los proyectos dirigidos a AnyCPU a veces se resuelven al binario incorrecto dependiendo de la arquitectura del proceso. El error se presenta como BadImageFormatException o DllNotFoundException en tiempo de ejecución en máquinas donde la arquitectura de proceso no coincide con el DLL nativo en la carpeta de salida.

**Solución:**IronOCR incluye el binario nativo correcto para cada plataforma dentro del paquete NuGet y resuelve el binario correcto automáticamente a través de la carpeta runtimes/ en la estructura del paquete. No hay configuración de objetivo Platform, no hay comandos de copia condicional de arquitectura, no hay subcarpetas de x64 para gestionar:

<!-- Remove architecture-specific build configurations from .csproj -->
<!-- BEFORE: Conditional native DLL copy based on Platform target -->
<!--
<ItemGroup Condition="'$(Platform)' == 'x64'">
  <Content Include="$(SolutionDir)libs\x64\*.dll">
    <CopyToOutputDirectory>Always</CopyToOutputDirectory>
  </Content>
</ItemGroup>
-->

<!-- AFTER: Nothing.IronOCR resolves the correct binary automatically. -->
XML

Tema 5: Migración de cadenas de configuración

Tesseract.NET SDK: Las variables del motor Tesseract se establecen a través de api.SetVariable(string name, string value) utilizando claves de cadena cruda de la referencia API de Tesseract (por ejemplo, "tessedit_char_whitelist", "tessedit_pageseg_mode"). Se trata de cadenas sin tipo y sin autocompletado en el IDE. Los errores tipográficos provocan fallos silenciosos: la variable se ignora, no se produce una excepción.

**Solución:**IronOCR expone la configuración del motor como propiedades tipadas en ocr.Configuration. Los errores tipográficos se convierten en errores de compilación:

// Before: untyped string variables, silent failures on typos
api.SetVariable("tessedit_char_whitelist", "0123456789");
api.SetVariable("tessedit_pageseg_mode", "7");

// After: typed properties, compile-time validation, IDE completion
ocr.Configuration.WhiteListCharacters = "0123456789";
ocr.Configuration.PageSegmentationMode = TesseractPageSegmentationMode.SingleLine;
C#

La referencia de la API de IronTesseract documenta todas las propiedades de configuración con sus tipos y valores aceptados.

N.º 6: Informes de progreso para trabajos por lotes largos

Tesseract.NET SDK: El código de procesamiento por lotes que informa el progreso utilizando IProgress<T> funciona a nivel de tarea (incrementa un contador después de cada archivo) pero no puede informar dentro de un solo documento — no hay mecanismo de callback dentro de GetTextFromImage(). En un documento de 500 páginas, la barra de progreso se queda atascada hasta que se termina todo el documento.

**Solución:**IronOCR proporciona seguimiento de progreso incorporado a través del evento OcrProgress en OcrInput. Indicadores de progreso por página, lo que permite barras de progreso precisas para documentos largos de varias páginas:

// IronOCR: page-level progress tracking for multi-page documents
using IronOcr;

var ocr = new IronTesseract();

using var input = new OcrInput();
input.LoadPdf("large-archive.pdf");

// Subscribe to page-level progress events
input.OcrProgress += (sender, e) =>
{
    Console.WriteLine($"Processing page {e.CurrentPage} of {e.TotalPages} " +
                      $"({e.ProgressPercent:F0}%)");
};

var result = ocr.Read(input);
Console.WriteLine($"Complete: {result.Pages.Count} pages extracted");
C#

La guía de seguimiento del progreso cubre la integración con ASP.NET Core SignalR para el envío de notificaciones de progreso en tiempo real a los clientes del navegador.

Lista de verificación para la migración de Tesseract.NET SDK

Pre-Migración

Revisa el código fuente para detectar todo uso del SDK de Tesseract.NET antes de modificar ningún código:

# Find all files referencing Patagames namespace
grep -rl "Patagames" --include="*.cs" .

# Find all OcrApi instantiation points
grep -rn "OcrApi.Create" --include="*.cs" .

# Find tessdata references in project and build files
grep -rn "tessdata" --include="*.cs" --include="*.csproj" --include="*.yaml" --include="*.yml" .

# Find platform guard checks that can be removed after migration
grep -rn "IsOSPlatform.*Windows" --include="*.cs" .

# Find Task.Run wrappers around synchronous OCR calls
grep -rn "Task.Run" --include="*.cs" . | grep -i "ocr\|image\|text"

# Count distinct OcrApi.Create() call sites to estimate migration scope
grep -c "OcrApi.Create" $(find . -name "*.cs")
SHELL

Documentar el conteo de sitios de llamada OcrApi.Create() — cada uno es un candidato para la inyección de singleton de reemplazo. Note cualquier patrón de disposición try/finally para modernización. Identificar cualquier inicialización Global.asax, Application_Start, o de constructor estático que se moverá a Program.cs.

Migración de código

  1. Actualizar <TargetFramework> a net8.0 (o el runtime moderno objetivo) en todos los archivos .csproj
  2. Ejecutar dotnet remove package Tesseract.Net.SDK en cada proyecto
  3. Ejecutar dotnet remove package PdfiumViewer (o el paquete de rendering PDF equivalente) si está presente
  4. Ejecutar dotnet add package IronOcr en cada proyecto
  5. Añadir IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"; a Program.cs o al host builder
  6. Registrar IronTesseract como un singleton en el contenedor DI: services.AddSingleton<IronTesseract>()
  7. Reemplazar todos los using Patagames.Ocr; y using Patagames.Ocr.Enums; con using IronOcr;
  8. Reemplazar OcrApi.Create() + api.Init(Languages.X) con IronTesseract inyectado en el constructor
  9. Reemplazar using (var api = OcrApi.Create()) { ... } blocks with using var input = new OcrInput() declarations
  10. Reemplazar api.GetTextFromImage(path) con ocr.Read(input).Text o await ocr.ReadAsync(input)
  11. Reemplazar Task.Run(() => { /* synchronous OCR */ }) con await ocr.ReadAsync(input) directo
  12. Reemplazar api.GetMeanConfidence() con result.Confidence
  13. Reemplazar bucles TIFF de iteración de cuadros Bitmap con input.LoadImageFrames(tiffPath)
  14. Reemplazar api.SetVariable("tessedit_char_whitelist", x) con ocr.Configuration.WhiteListCharacters = x
  15. Eliminar la carpeta tessdata del proyecto y eliminar todas las referencias a tessdata en los scripts de implementación

Posmigración

  • Compile el proyecto dirigido a net8.0 y confirme que no quedan referencias Patagames en la salida de la construcción
  • Ejecutar la aplicación en un host Linux o contenedor Linux Docker y confirmar no DllNotFoundException
  • Verificar que el texto resultante del OCR coincide con el resultado previo a la migración en una muestra representativa de documentos de producción (10-20 documentos)
  • Probar el procesamiento de archivos TIFF de varias páginas y confirmar que el recuento de páginas coincide con el recuento de fotogramas original
  • Ejecutar pruebas de carga en los puntos finales de ASP.NET Core usando ReadAsync() y verificar que las métricas del pool de hilos no muestran bloqueos
  • Confirme que el contenedor DI resuelve IronTesseract como un singleton (misma instancia entre solicitudes)
  • Verificar que el proceso de CI/CD se completa sin errores ahora que se han eliminado los pasos de copia de tessdata
  • Probar la compilación de la imagen de Docker y la ejecución del contenedor en una imagen base de Linux
  • Confirma que los eventos de progreso se activan correctamente en un documento de varias páginas (PDF o TIFF)
  • Comprueba que las puntuaciones de confianza se encuentren dentro del rango esperado para documentos de calidad contrastada

Principales ventajas de migrar a IronOCR

El bloqueo de actualización de .NET ha desaparecido. Antes de la migración, cualquier plan para trasladar el servicio de .NET Framework 4.x a .NET 8se detenía en la capa de OCR. Tras la migración, el servicio OCR se compila y se ejecuta en .NET Framework 4.6.2, .NET 6, .NET 8y .NET 9desde la misma referencia de paquete. La ruta de actualización está desbloqueada. Los equipos que mantenían una implementación de tiempo de ejecución heredada independiente solo para el OCR pueden consolidarse en un único entorno de tiempo de ejecución moderno.

La implementación en contenedor funciona sin compromiso. Se elimina el DllNotFoundException en imágenes base de Linux. El mismo binario de aplicación que se ejecuta en la estación de trabajo de Windows de un desarrollador se ejecuta dentro de un contenedor Debian o Alpine con una línea apt-get en el Dockerfile. Las implementaciones de Kubernetes, Aplicaciones de contenedores de Azure y tareas de AWS ECS en pools de nodo Linux funcionan sin licencias de contenedores de Windows, tamaños de imagen más grandes, o rutas de código condicionales de arquitectura. La guía de implementación de Docker y la guía de Azure documentan la configuración exacta para cada entorno de destino.

Las pipelines async-first eliminan la presión del pool de hilos. La solución alternativa Task.Run que envolvía OCR síncrono en un método async es reemplazada por ReadAsync(). Los subprocesos de solicitud de ASP.NET Core se liberan durante el procesamiento OCR en lugar de bloquearse. En condiciones de alta concurrencia, esto se traduce directamente en un mayor rendimiento de solicitudes y una menor latencia para toda la aplicación, no solo para los puntos finales de OCR.

El consumo de memoria disminuye proporcionalmente con la concurrencia. Un servicio que previamente creaba una instancia OcrApi por solicitud concurrente — cada una cargando 40–100 MB de datos de idioma — ahora carga esos datos una vez en una instancia singleton IronTesseract. Con diez solicitudes simultáneas, la diferencia es de 400-1000 MB frente a una única carga fija. Esta reducción se refleja inmediatamente en las métricas de recursos de los contenedores y permite límites de memoria de pod más reducidos, una mayor densidad de pods y un menor coste de la infraestructura en la nube.

Los patrones modernos de C# reemplazan la ceremonia de .NET Framework. Los guardas de disposición try/finally, los bloques anidados using, las llamadas GC.Collect() entre cuadros TIFF — todos estos desaparecen. using var input = new OcrInput() es todo el patrón de gestión de recursos. Las revisiones de código son más breves. La incorporación de nuevos desarrolladores al servicio de OCR lleva menos tiempo. La referencia de la API OcrResult documenta el modelo de objetos de resultados completo, incluyendo datos estructurados, puntuaciones de confianza y salida en PDF con capacidad de búsqueda, que sustituyen a los patrones de gestión manual de resultados del SDK heredado.

El soporte comercial sustituye a la dependencia de un único desarrollador. SDK de Tesseract .NET es gestionado por un desarrollador individual sin SLA y sin garantía de continuidad organizativa.IronOCR ha sido desarrollado por Iron Software, una entidad comercial con canales de asistencia dedicados, procesos documentados de divulgación de seguridad y condiciones de licencia que satisfacen los requisitos de adquisición de las empresas. La página de licencias de IronOCR cubre niveles de soporte y el modelo de licencia perpetua (de $999) que reemplaza tanto la tarifa del SDK de Patagames como el costo oculto de mantener infraestructura solo para Windows en un stack .NET en modernización.

Por favor nota: PDFium y Tesseract son marcas registradas de sus respectivos propietarios. Este sitio no está afiliado con, respaldado por, o patrocinado por el Proyecto Chromium o Google. Todos los nombres de producto, logotipos y marcas son propiedad de sus respectivos dueños. Las comparaciones son solo para fines informativos y reflejan información públicamente disponible en el momento de la redacción.

Artículos Relacionados

Key in blue circle

Obtenga su clave de prueba gratuita de 30 días al instante.

Your trial license will be sent to your email address

Sin limitaciones. 100 % desbloqueado. Sin tarjeta de crédito.

bullet_checkedNo se requiere tarjeta de crédito ni creación de cuentaSin limitaciones. 100 % desbloqueado. Sin tarjeta de crédito.
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
Obtén tu Consulta Sin Compromiso
Completa el formulario a continuación o envía un correo a sales@ironsoftware.com
Tus detalles siempre serán mantenidos confidenciales.
Confiado por millones de ingenieros en todo el mundo
Logos de clientes de Iron Software
Obtenga su Clave de Prueba de 30 días gratis al instante.
No se requiere tarjeta de crédito ni creación de cuenta