Migración de XImage.OCR a IronOCR
Esta guía está dirigida a desarrolladores de .NET que están migrando una integración existente de XImage.OCR a IronOCR. Abarca el proceso de consolidación de paquetes, los cambios en los espacios de nombres y las API, y ejemplos concretos de migración de código para los escenarios en los que la arquitectura fragmentada de XImage.OCR genera más fricciones. No es necesario haber leído previamente el artículo comparativo.
¿Por qué migrar desde XImage.OCR?
XImage.OCR es un envoltorio comercial de Tesseract de RasterEdge que distribuye su funcionalidad a través de una cadena de paquetes NuGet coordinados. La arquitectura funciona a pequeña escala, pero genera costes de mantenimiento crecientes a medida que las aplicaciones crecen.
El número de paquetes crece con cada idioma. Añadir un idioma significa añadir un paquete NuGet. Una aplicación de cinco idiomas lleva seis paquetes en su .csproj. Una aplicación en diez idiomas vale por once. Cada paquete debe estar vinculado a la misma versión que el núcleo, una restricción que provoca fallos silenciosos en tiempo de ejecución cuando un desarrollador actualiza solo una parte de la cadena.IronOCR ofrece un único paquete para más de 125 idiomas.
La sincronización de versiones es un riesgo constante. dotnet outdated actualiza paquetes de manera codiciosa. Cuando RasterEdge.XImage.OCR avanza a 12.5.0 pero XImage.OCR.Language.French se queda en 12.4.0, el error aparece en tiempo de ejecución, no en tiempo de compilación, y el mensaje rara vez señala la sincronización de versiones como la causa. Los equipos que ejecutan pipelines de CI/CD aprenden a añadir una fijación de versión explícita para cada paquete XImage.OCR, una sobrecarga que no tiene otra finalidad que compensar el modelo fragmentado.
Sin preprocesamiento integrado. Precisión en documentos reales. XImage.OCR pasa las imágenes directamente al motor Tesseract subyacente. Un escaneo a 150 ppp con dos grados de inclinación se introduce en Tesseract sin cambios. El nivel máximo de precisión de este tipo de entradas es del 60-75 %, independientemente del envoltorio de Tesseract que se utilice.IronOCR envía un pipeline de preprocesamiento — Deskew(), DeNoise(), Contrast(), Binarize(), Sharpen() — que corrige estos problemas antes de que se ejecute el reconocimiento.
La salida estructurada requiere un análisis sintáctico manual. XImage.OCR devuelve una cadena de texto sin formato. Extraer posiciones de palabras, límites de línea o el nivel de confianza por palabra requiere analizar esa cadena tú mismo.IronOCR devuelve un objeto OcrResult con Pages, Paragraphs, Lines, Words y datos por carácter con coordenadas de píxeles y puntajes de confianza incorporados.
Los formatos de salida se limitan al texto sin formato. Para crear un PDF con capacidad de búsqueda a partir de un resultado de XImage.OCR se requiere el SDK de PDF de RasterEdge, lo que supone una segunda compra comercial.IronOCR produce PDFs con capacidad de búsqueda a través de result.SaveAsSearchablePdf() sin dependencias adicionales.
No se admite la implementación multiplataforma. XImage.OCR está destinado a Windows. Los contenedores de Linux, los entornos de desarrollo de macOS y las implementaciones nativas en la nube en Azure o AWS requieren una biblioteca diferente.IronOCR se ejecuta en Windows, Linux, macOS, Docker, Azure App Service y AWS Lambda desde el mismo paquete.
El problema fundamental
XImage.OCR requiere un paquete NuGet por idioma. Diez idiomas significan once paquetes, todos bloqueados por versión entre sí:
<!-- XImage.OCR: 11 packages to support 10 languages — every version must match -->
<PackageReference Include="RasterEdge.XImage.OCR" Version="12.4.0" />
<PackageReference Include="XImage.OCR.Language.English" Version="12.4.0" />
<PackageReference Include="XImage.OCR.Language.German" Version="12.4.0" />
<PackageReference Include="XImage.OCR.Language.French" Version="12.4.0" />
<PackageReference Include="XImage.OCR.Language.Spanish" Version="12.4.0" />
<PackageReference Include="XImage.OCR.Language.Italian" Version="12.4.0" />
<PackageReference Include="XImage.OCR.Language.Portuguese" Version="12.4.0" />
<PackageReference Include="XImage.OCR.Language.ChineseSimplified" Version="12.4.0" />
<PackageReference Include="XImage.OCR.Language.Japanese" Version="12.4.0" />
<PackageReference Include="XImage.OCR.Language.Korean" Version="12.4.0" />
<PackageReference Include="XImage.OCR.Language.Arabic" Version="12.4.0" />
IronOCR sustituye todo el bloque por una sola línea:
<!-- IronOCR: One package. 125+ languages. No version coordination. -->
<PackageReference Include="IronOcr" Version="2024.x.x" />
##IronOCR frente a XImage.OCR: comparación de características
La tabla siguiente recoge las capacidades más relevantes para la decisión de migración.
| Característica | XImage.OCR | IronOCR |
|---|---|---|
| Paquetes NuGet solo en inglés | 2 (núcleo + paquete de idiomas) | 1 |
| Paquetes NuGet para 10 idiomas | 11 | 1 |
| Se requiere sincronización de versiones | Sí, todos los paquetes deben coincidir | No |
| Idiomas disponibles | ~15 como paquetes independientes | Más de 125 incluidas |
| Preprocesamiento integrado | None | Enderezar, Reducir ruido, Contraste, Binarizar, Enfocar, Escalar, Dilatar, Erosionar, Invertir |
| Eliminación profunda del ruido | None | Sí (DeepCleanBackgroundNoise()) |
| Entrada de PDF nativa | Requiere el SDK de PDF de RasterEdge | Sí (input.LoadPdf()) |
| Salida en PDF con capacidad de búsqueda | Requiere el SDK de PDF de RasterEdge | Sí (result.SaveAsSearchablePdf()) |
| Entrada TIFF de varias páginas | Limitado | Sí (input.LoadImageFrames()) |
| Entrada de matriz de bytes | Manuala través de MemoryStream | Sí (input.LoadImage(bytes)) |
| Entrada de flujo | Manual | Sí (input.LoadImage(stream)) |
| Salida estructurada | Cadena simple | Páginas, párrafos, líneas, palabras, caracteres con coordenadas |
| Puntuaciones de confianza por palabra | No disponible | Sí |
| Lectura de BarCodes | No disponible | Sí (ocr.Configuration.ReadBarCodes = true) |
| Exportación hOCR | No disponible | Sí |
| Seguridad de los hilos | No es seguro para subprocesos | Total seguridad de subprocesos |
| Modelo de memoria (paralelo) | Una instancia de controlador por subproceso | Instancia única compartida |
| Multiplataforma | Windows principalmente | Windows, Linux, macOS, Docker, Azure, AWS |
| Compatibilidad con .NET | .NET Standard 2.0, .NET Framework 4.5+ | .NET Framework 4.6.2+, .NET Core, .NET 5/6/7/8/9 |
| Tipo de licencia | Comercial (RasterEdge) | Perpetual (Lite $999, Pro $1,499, Enterprise $2,999) |
| Soporte comercial | Asistencia de RasterEdge | Sí, por niveles según la licencia |
Inicio rápido: Migración de XImage.OCR a IronOCR
Paso 1: Sustituir paquetes NuGet
Elimina todos los paquetes XImage.OCR. El número de comandos coincide con el número de paquetes de idioma que hayas instalado:
dotnet remove package RasterEdge.XImage.OCR
dotnet remove package XImage.OCR.Language.English
dotnet remove package XImage.OCR.Language.German
dotnet remove package XImage.OCR.Language.French
# Repeat for every language pack in your project
Instala IronOCR desde NuGet :
Paso 2: Actualizar los espacios de nombres
Sustituya las importaciones del espacio de nombres RasterEdge por el único espacio de nombres IronOCR:
// Before (XImage.OCR)
using RasterEdge.XImage.OCR;
using RasterEdge.Imaging.Basic;
// After (IronOCR)
using IronOcr;
Paso 3: Inicializar licencia
Añadir la inicialización de la licencia una vez al iniciar la aplicación, antes de cualquier llamada a OCR:
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY"Almacena la clave en una variable de entorno o en un gestor de secretos en lugar de codificarla de forma estática:
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE_KEY");Imports System
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE_KEY")Ejemplos de migración de código
Consolidación de la inicialización de múltiples paquetes
La primera tarea de migración consiste en fusionar el bloque de inicialización de XImage.OCR —activación de la licencia, creación del controlador y asignación del idioma basada en cadenas— con su equivalente en IronOCR.
Enfoque de XImage.OCR:
// Requires: RasterEdge.XImage.OCR + one XImage.OCR.Language.* package per language
// Language strings must exactly match installed package names or OCR fails at runtime
RasterEdge.XImage.OCR.License.LicenseManager.SetLicense("your-ximage-license-key");
var ocrHandler = new OCRHandler();
// String codes — typo "enh" instead of "eng" silently fails or throws at runtime
ocrHandler.Languages = new[] { "eng", "deu", "fra", "spa", "ita" };
// Process returns a plain string — no structure, no confidence
string extractedText = ocrHandler.Process("document.png");
Console.WriteLine(extractedText);
Enfoque IronOCR:
// Requires: IronOcr (single package — all languages included)
IronOcr.License.LicenseKey = "YOUR-IRONOCR-LICENSE-KEY";
var ocr = new IronTesseract();
// Type-safe enum — compiler catches typos, no runtime surprises
ocr.Language = OcrLanguage.English + OcrLanguage.German +
OcrLanguage.French + OcrLanguage.Spanish + OcrLanguage.Italian;
using var input = new OcrInput();
input.LoadImage("document.png");
var result = ocr.Read(input);
Console.WriteLine(result.Text);
Console.WriteLine($"Confidence: {result.Confidence}%");
Los códigos de idioma basados en cadenas en XImage.OCR ("eng", "deu") fallan en tiempo de ejecución cuando el paquete NuGet correspondiente está ausente o en la versión incorrecta. El enumerador OcrLanguage en IronOCR hace que las combinaciones de idiomas inválidas sean imposibles de compilar. La guía de configuración de IronTesseract cubre completamente las opciones de configuración del motor, y la guía de varios idiomas documenta cómo funcionan las combinaciones de idioma primario y secundario para documentos en varios idiomas.
Unificación del manejo de formatos de imagen
XImage.OCR gestiona cada fuente de imagen de forma diferente según el formato. Las matrices de bytes, los flujos y las rutas de archivo requieren cada uno rutas de código ligeramente diferentes.IronOCR acepta todos a través de los mismos métodos OcrInput.
Enfoque de XImage.OCR:
// XImage.OCR: different handling per image source type
var ocrHandler = new OCRHandler();
ocrHandler.Language = "eng";
// File path — works directly
string resultFromFile = ocrHandler.Process("invoice.jpg");
// Byte array — must write to temp file first, then process
byte[] imageBytes = File.ReadAllBytes("invoice.jpg");
string tempPath = Path.GetTempFileName() + ".jpg";
File.WriteAllBytes(tempPath, imageBytes);
try
{
string resultFromBytes = ocrHandler.Process(tempPath);
Console.WriteLine(resultFromBytes);
}
finally
{
File.Delete(tempPath); // Manualcleanup — easy to forget
}
// Multi-page TIFF — must split frames manually
// No built-in TIFF frame iteration in base XImage.OCR
Enfoque IronOCR:
// IronOCR: unified OcrInput accepts all source types identically
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var ocr = new IronTesseract();
// File path
using (var input = new OcrInput())
{
input.LoadImage("invoice.jpg");
var result = ocr.Read(input);
Console.WriteLine($"From file: {result.Text}");
}
// Byte array — no temp file needed
byte[] imageBytes = File.ReadAllBytes("invoice.jpg");
using (var input = new OcrInput())
{
input.LoadImage(imageBytes);
var result = ocr.Read(input);
Console.WriteLine($"From bytes: {result.Text}");
}
// Multi-page TIFF — all frames processed in one call
using (var input = new OcrInput())
{
input.LoadImageFrames("scanned-archive.tiff");
var result = ocr.Read(input);
Console.WriteLine($"TIFF pages: {result.Pages.Count}");
foreach (var page in result.Pages)
Console.WriteLine($"Page {page.PageNumber}: {page.Text}");
}
El patrón de archivos temporales para matrices de bytes en XImage.OCR es una causa habitual de saturación del disco y de fuga de archivos en rutas de error. El LoadImage(byte[]) de IronOCR elimina el archivo intermedio por completo. La guía de entrada de imágenes y la guía de entrada de TIFF/GIF cubren todos los tipos de fuente compatibles, incluidos los flujos y el procesamiento de fotogramas múltiples.
Optimización del formato de salida
XImage.OCR devuelve una cadena de texto sin formato. Para generar un PDF con capacidad de búsqueda se necesita un segundo producto de RasterEdge.IronOCR genera texto sin formato, archivos PDF con capacidad de búsqueda y datos estructurados a partir del mismo objeto de resultado sin necesidad de paquetes adicionales.
Enfoque de XImage.OCR:
// XImage.OCR: plain text output only
// Searchable PDF requires purchasing the RasterEdge PDF SDK separately
var ocrHandler = new OCRHandler();
ocrHandler.Language = "eng";
string plainText = ocrHandler.Process("scanned-contract.jpg");
// To produce a searchable PDF from this text, you would need:
// 1. Purchase RasterEdge PDF SDK (separate commercial license)
// 2. Create a PDF document programmatically
// 3. Embed the extracted text as invisible text layer over the image
// 4. Manage the PDF document lifecycle manually
// No built-in path from OCR result to searchable PDF in XImage.OCR alone
Console.WriteLine(plainText);
Enfoque IronOCR:
// IronOCR: plain text, searchable PDF, and structured data from one result
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage("scanned-contract.jpg");
var result = ocr.Read(input);
// Plain text
Console.WriteLine(result.Text);
// Searchable PDF — no extra package required
result.SaveAsSearchablePdf("searchable-contract.pdf");
// Structured data: paragraphs with bounding box coordinates
foreach (var page in result.Pages)
{
foreach (var paragraph in page.Paragraphs)
{
Console.WriteLine($"Paragraph at ({paragraph.X}, {paragraph.Y}): {paragraph.Text}");
}
}
// Per-word confidence for quality gating
var lowConfidenceWords = result.Pages
.SelectMany(p => p.Words)
.Where(w => w.Confidence < 70)
.ToList();
Console.WriteLine($"Words below 70% confidence: {lowConfidenceWords.Count}");
La llamada SaveAsSearchablePdf() incrusta el texto reconocido como una capa oculta debajo de la imagen original, haciendo que el documento sea completamente buscable sin alterar su apariencia visual. El manual en PDF con función de búsqueda cubre las opciones de rango de páginas y la configuración de DPI. Para patrones de extracción de datos estructurados, la guía de lectura de resultados documenta la jerarquía completa OcrResult, incluyendo coordenadas de palabras y acceso a confianza. El ejemplo de PDF con capacidad de búsqueda proporciona una implementación completa y funcional.
Procesamiento de documentos por lotes
XImage.OCR no es seguro para subprocesos. Cada hilo de trabajo concurrente debe crear su propia instancia de OCRHandler, multiplicando el consumo de memoria por el recuento de hilos.IronOCR utiliza una única instancia compartida en todos los subprocesos.
Enfoque de XImage.OCR:
// XImage.OCR: one handler per thread — memory multiplies with concurrency
// 4 threads processing English documents: 4 x ~100MB = ~400MB for OCR alone
// 4 threads processing 5 languages: 4 x ~250MB = ~1GB just for OCR handlers
var results = new ConcurrentDictionary<string, string>();
string[] documentPaths = Directory.GetFiles("./incoming", "*.png");
Parallel.ForEach(documentPaths,
new ParallelOptions { MaxDegreeOfParallelism = 4 },
documentPath =>
{
// Each thread must create and dispose its own handler
var ocrHandler = new OCRHandler();
ocrHandler.Language = "eng";
try
{
string text = ocrHandler.Process(documentPath);
results[documentPath] = text;
}
finally
{
// Manualdisposal required — no using statement support shown
ocrHandler.Dispose();
}
});
foreach (var kvp in results)
Console.WriteLine($"{Path.GetFileName(kvp.Key)}: {kvp.Value.Length} chars");
Enfoque IronOCR:
// IronOCR: single IronTesseract instance shared across all threads
// Memory stays flat regardless of thread count
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var ocr = new IronTesseract(); // Create once outside the parallel loop
var results = new ConcurrentDictionary<string, string>();
string[] documentPaths = Directory.GetFiles("./incoming", "*.png");
Parallel.ForEach(documentPaths, documentPath =>
{
// OcrInput is created per thread — IronTesseract instance is shared
using var input = new OcrInput();
input.LoadImage(documentPath);
input.Deskew(); // Preprocessing runs per-document, not per-thread engine
input.DeNoise();
var result = ocr.Read(input);
results[documentPath] = result.Text;
});
foreach (var kvp in results)
Console.WriteLine($"{Path.GetFileName(kvp.Key)}: {kvp.Value.Length} chars");
El patrón de controlador por subproceso de XImage.OCR implica que un trabajo por lotes de cuatro subprocesos que carga cinco idiomas ocupa aproximadamente 1 GB de memoria del controlador OCR antes de procesar un solo documento. La instancia compartida de IronOCR mantiene la memoria limitada al espacio de memoria de una sola instancia, independientemente del paralelismo. El ejemplo de multithreading muestra el patrón en su totalidad, y la guía de optimización de la velocidad aborda el ajuste de la configuración para cargas de trabajo por lotes centradas en el rendimiento.
Extracción combinada de BarCode y texto
XImage.OCR no tiene capacidad para leer códigos de barras. Los documentos que contengan tanto texto como BarCodes requieren dos bibliotecas distintas y dos pasadas separadas.IronOCR extrae ambos en una sola operación de lectura.
Enfoque de XImage.OCR:
// XImage.OCR: text only — barcodes require a separate library and second pass
var ocrHandler = new OCRHandler();
ocrHandler.Language = "eng";
// Pass 1: text extraction with XImage.OCR
string documentText = ocrHandler.Process("warehouse-label.png");
Console.WriteLine($"Text: {documentText}");
// Pass 2: barcode reading requires a completely separate library
// e.g., ZXing.Net, Dynamsoft Barcode Reader, or another commercial SDK
// - Additional NuGet package required
// - Additional license required
// - Additional code for result merging
// No combined text + barcode result object exists in XImage.OCR
Enfoque IronOCR:
// IronOCR: text and barcodes from a single Read() call
IronOcr.License.LicenseKey = "YOUR-LICENSE-KEY";
var ocr = new IronTesseract();
ocr.Configuration.ReadBarCodes = true; // Enable barcode extraction
using var input = new OcrInput();
input.LoadImage("warehouse-label.png");
var result = ocr.Read(input);
// Text and barcodes in one result object
Console.WriteLine($"Document text:\n{result.Text}");
if (result.Barcodes.Any())
{
Console.WriteLine($"\nBarcodes found: {result.Barcodes.Count}");
foreach (var barcode in result.Barcodes)
Console.WriteLine($" [{barcode.BarcodeType}] {barcode.Value}");
}
Configurar ReadBarCodes = true añade detección de códigos de barras al paso de reconocimiento sin requerir una segunda biblioteca o una segunda lectura. La guía práctica de lectura de códigos de barras y el ejemplo de OCR de códigos de barras abarcan los formatos de códigos de barras compatibles y las opciones de configuración para documentos de contenido mixto.
Referencia de mapeo de la API XImage.OCR a IronOCR
| XImage.OCR | Equivalente a IronOCR |
|---|---|
new OCRHandler() | new IronTesseract() |
RasterEdge.XImage.OCR.License.LicenseManager.SetLicense("key") | IronOcr.License.LicenseKey = "key" |
ocrHandler.Language = "eng" | ocr.Language = OcrLanguage.English |
ocrHandler.Languages = new[] { "eng", "deu" } | ocr.Language = OcrLanguage.English + OcrLanguage.German |
ocrHandler.Process(imagePath) | ocr.Read(input).Text (después de input.LoadImage(path)) |
ocrHandler.Process(image) (desde objeto) | input.LoadImage(bytes) o input.LoadImage(stream) |
ocrHandler.ProcessRegion(path, rect) | input.LoadImage(path, new CropRectangle(x, y, w, h)) |
ocrHandler.SetVariable("tessedit_char_whitelist", "0-9") | ocr.Configuration.WhiteListCharacters = "0123456789" |
result (cadena simple) | result.Text |
result.MeanConfidence | result.Confidence |
| No existe equivalente | result.Pages / result.Paragraphs / result.Lines |
| No existe equivalente | result.Words (con .X, .Y, .Confidence) |
| No existe equivalente | result.SaveAsSearchablePdf("output.pdf") |
| No existe equivalente | input.Deskew() |
| No existe equivalente | input.DeNoise() |
| No existe equivalente | input.Contrast() |
| No existe equivalente | input.Binarize() |
| No existe equivalente | input.Sharpen() |
| No existe equivalente | input.LoadImageFrames("file.tiff") (multitrama) |
| Requiere el SDK de PDF de RasterEdge | input.LoadPdf(pdfPath) |
| Requiere el SDK de PDF de RasterEdge | result.SaveAsSearchablePdf("output.pdf") |
| No disponible | ocr.Configuration.ReadBarCodes = true |
Instancias OCRHandler por hilo | Instancia IronTesseract compartida única |
Problemas comunes de migración y soluciones
Problema 1: Fallos en tiempo de ejecución tras una actualización parcial del paquete
XImage.OCR: Ejecutar dotnet outdated o dotnet restore con un caché de paquetes obsoleto puede avanzar RasterEdge.XImage.OCR a una nueva versión, mientras deja los paquetes de idioma en la versión anterior. El fallo se produce en tiempo de ejecución durante la primera llamada al OCR con un mensaje de error que no identifica claramente la incompatibilidad de versiones como la causa principal. Encontrar la discrepancia requiere verificar todas las entradas PackageReference manualmente.
Solución: Tras eliminar los paquetes XImage.OCR e instalar IronOCR, ya no hay que mantener la sincronización de versiones. El paquete único IronOcr lleva todo. Si necesitas paquetes de idiomas más allá de los valores predeterminados incluidos, instala paquetes IronOcr.Languages.* independientemente; no necesitan coincidir en versión con el núcleo:
Problema 2: Los códigos de idioma en las cadenas provocan fallos silenciosos en el OCR
XImage.OCR: Los códigos de idioma son cadenas ("eng", "deu", "fra"). Un error tipográfico en un código de idioma — "engg", "ger" en lugar de "deu" — retrocede silenciosamente a un idioma predeterminado o lanza una excepción en tiempo de ejecución, dependiendo de la versión de XImage.OCR. Ninguno de los dos resultados se detecta en tiempo de compilación.
**Solución:**IronOCR utiliza el enumerador OcrLanguage. Los valores no válidos son errores de compilación, no sorpresas en tiempo de ejecución. Migrar matrices de cadenas a expresiones de enumeración:
// Before (XImage.OCR) — typos compile fine, fail at runtime
ocrHandler.Languages = new[] { "eng", "deu", "fra" };
// After (IronOCR) — typos are compile errors
ocr.Language = OcrLanguage.English + OcrLanguage.German + OcrLanguage.French;
Consulte la guía de idiomas múltiples para combinar idiomas principales y secundarios en documentos con contenido en varios idiomas.
Problema 3: Archivos temporales que quedan en el disco tras el procesamiento de matrices de bytes
XImage.OCR: Procesar imágenes desde matrices de bytes requiere escribir un archivo temporal porque OCRHandler.Process() acepta una ruta de archivo, no un buffer. Las rutas de excepción que omiten el bloque finally dejan esos archivos temporales en el disco. En aplicaciones de alto rendimiento, esto se acumula rápidamente.
Solución: OcrInput.LoadImage() acepta byte[] directamente. No se crea ningún archivo temporal:
// Before (XImage.OCR) — temp file required
string tempPath = Path.GetTempFileName() + ".png";
File.WriteAllBytes(tempPath, imageBytes);
try { text = ocrHandler.Process(tempPath); }
finally { File.Delete(tempPath); }
// After (IronOCR) — direct byte array loading, no disk I/O
using var input = new OcrInput();
input.LoadImage(imageBytes);
var result = ocr.Read(input);
string text = result.Text;
Problema 4: Agotamiento de memoria bajo carga paralela
XImage.OCR: El procesamiento en paralelo requiere un OCRHandler por hilo. Ocho subprocesos que procesan documentos en cinco idiomas cargan ocho instancias de motor independientes, cada una de las cuales contiene los cinco paquetes de idiomas. Con un consumo aproximado de 50 MB por idioma y por instancia, ocho subprocesos consumen aproximadamente 2 GB de memoria del motor OCR antes incluso de que entren en juego los datos del documento.
Solución: Una instancia única de IronTesseract maneja todos los hilos. Crea OcrInput por documento (es desechable y ligero), reutiliza IronTesseract durante toda la aplicación:
// Single instance — shared safely across all threads
var ocr = new IronTesseract();
ocr.Language = OcrLanguage.English + OcrLanguage.German +
OcrLanguage.French + OcrLanguage.Spanish + OcrLanguage.Italian;
Parallel.ForEach(documentPaths, path =>
{
using var input = new OcrInput(); // Per-document, lightweight
input.LoadImage(path);
var result = ocr.Read(input); // Thread-safe call on shared instance
ProcessResult(result.Text);
});
Problema 5: La canalización de CI/CD se interrumpe después de una restauración parcial.
XImage.OCR: Un agente de CI/CD con una caché de paquetes precalentada suele tener algunos paquetes de idioma XImage.OCR almacenados en caché en una versión antigua. Cuando solo se actualiza el paquete principal en el archivo del proyecto, la restauración se realiza correctamente, pero el entorno de ejecución carga ensamblados que no coinciden. La compilación se realiza correctamente; El despliegue falla.
Solución: Tras la migración a IronOCR, la canalización de CI/CD restaura un paquete. Agregue un paso de validación para confirmar que la versión esperada está presente:
# In your CI pipeline — verify single package restore
dotnet restore
dotnet list package | grep IronOcr
# No version coordination logic needed — only one package to check
Problema 6: Falta de datos estructurados para el análisis posterior
XImage.OCR: Devuelve una cadena de texto simple. Las aplicaciones que necesitan conocer la posición de las palabras, agrupar las líneas o determinar el nivel de confianza por palabra deben analizar la cadena utilizando heurísticas de espacios en blanco o lógica personalizada. La precisión de este análisis disminuye en documentos con diseños de varias columnas, tablas o texto girado.
Solución: El OcrResult de IronOCR expone directamente la jerarquía completa del documento. No se necesita análisis de cadenas:
var result = ocr.Read(input);
// Direct access to structured data — no string manipulation
foreach (var page in result.Pages)
{
foreach (var line in page.Lines)
{
// Line text, bounding box, and per-word data all available
Console.WriteLine($"Line [{line.X},{line.Y}]: {line.Text}");
foreach (var word in line.Words)
Console.WriteLine($" Word '{word.Text}' confidence: {word.Confidence}%");
}
}
Para obtener información completa sobre la API de datos estructurados, consulte la página de instrucciones para leer los resultados y las funciones de los resultados de OCR.
Lista de verificación de migración de XImage.OCR
Pre-Migración
Antes de realizar cambios, revise el código fuente para encontrar todos los puntos de contacto de XImage.OCR:
# Find all XImage.OCR namespace imports
grep -r "RasterEdge.XImage.OCR\|Yiigo.Image.Ocr\|XImage.OCR" --include="*.cs" .
# Find all OCRHandler usages
grep -r "OCRHandler\|ocrHandler" --include="*.cs" .
# Find all string-based language assignments
grep -r "\.Language\s*=\s*\"" --include="*.cs" .
grep -r "\.Languages\s*=\s*new\[\]" --include="*.cs" .
# Find all XImage.OCR package references in project files
grep -r "RasterEdge.XImage.OCR\|XImage.OCR.Language" --include="*.csproj" .
# Count distinct language packs installed
grep "XImage.OCR.Language" --include="*.csproj" -r . | wc -l
Indique qué tipos de origen de imagen se utilizan (rutas de archivo, matrices de bytes, flujos, TIFF) e identifique cualquier ubicación que utilice archivos temporales para el procesamiento de matrices de bytes. Estos son objetivos de limpieza de alta prioridad.
Migración de código
- Elimina todas las referencias a paquetes
RasterEdge.XImage.OCRyXImage.OCR.Language.*de cada archivo.csproj - Agrega la referencia al paquete
IronOcr(dotnet add package IronOcr) - Reemplaza
using RasterEdge.XImage.OCRconusing IronOcren todos los archivos - Agrega
IronOcr.License.LicenseKey = ...al inicio de la aplicación (una vez por proceso) - Reemplaza
new OCRHandler()connew IronTesseract() - Reemplaza las asignaciones de idiomas en cadenas (
"eng","deu") con valores del enumeradorOcrLanguage - Reemplaza
ocrHandler.Process(path)coninput.LoadImage(path)+ocr.Read(input).Text - Reemplaza patrones de matriz de bytes a archivo temporal con
input.LoadImage(byte[]) - Reemplaza el particionado manual de cuadros de TIFF de varias páginas con
input.LoadImageFrames("file.tiff") - Elimina la instanciación de
OCRHandlerpor hilo de los buclesParallel.ForEach: utiliza una instanciaIronTesseractcompartida única - Añade llamadas de preprocesamiento (
input.Deskew(),input.DeNoise()) después de cadaLoadImage()para documentos de fuentes de calidad variable - Reemplaza el manejo de resultados de cadena simple con
result.Textpara texto oresult.SaveAsSearchablePdf()para salida PDF - Reemplaza
ocrHandler.SetVariable("tessedit_char_whitelist", ...)conocr.Configuration.WhiteListCharacters = ... - Actualiza el pipeline de CI/CD: elimina los pasos de restauración de múltiples paquetes, elimina la lógica de sincronización de versiones, verifica la restauración de un solo paquete
IronOcr
Posmigración
- Confirmar que la extracción básica de texto produce un resultado correcto a partir de una imagen de prueba conocida y válida.
- Verificar que los documentos multilingües devuelvan el texto para todos los idiomas configurados.
- Las rutas de entrada de la matriz de bytes de prueba producen una salida correcta sin crear archivos temporales en el disco.
- Confirma que los documentos TIFF de varias páginas devuelvan el número correcto de páginas en
result.Pages - Ejecutar el procesamiento por lotes en paralelo bajo carga y medir el pico de memoria: debería ser sustancialmente menor que la línea base de XImage.OCR.
- Verifique que el archivo PDF con capacidad de búsqueda se abra correctamente en Adobe Acrobat o en un visor de PDF y que el texto sea seleccionable.
- Pruebe el preprocesamiento en un escaneo de baja calidad o sesgado y compare la precisión del texto extraído con la línea base de XImage.OCR.
- Confirme que la inicialización de la clave de licencia se ejecuta antes de la primera llamada de OCR y no genera ningún error.
- Validar que la restauración de CI/CD se realice correctamente en un entorno limpio sin paquetes en caché.
- Verifica que la salida de datos estructurados (
result.Words,result.Paragraphs) coincida con el diseño de documento esperado
Principales ventajas de migrar a IronOCR
Un solo paquete reemplaza un gráfico de dependencia completo. Cada paquete XImage.OCR.Language.*, el paquete central RasterEdge.XImage.OCR y la sobrecarga de sincronización de versiones entre ellos se colapsan en un solo comando dotnet add package IronOcr. El conteo de entradas .csproj disminuye de once a uno. El paso de restauración de CI/CD pasa de ser una operación de múltiples paquetes con once puntos de fallo independientes a la restauración de un único paquete. Esa simplificación se multiplica: menos paquetes que auditar en busca de vulnerabilidades de seguridad, menos entradas que actualizar cuando cambia la compatibilidad con .NET y ninguna lógica de coordinación de versiones que mantener en las canalizaciones de actualización automatizadas. La página del producto IronOCR y el centro de documentación proporcionan una referencia completa sobre sus características e implementación.
Las mejoras en la precisión del preprocesamiento son inmediatas. La migración no es un reemplazo directo, sino una mejora en la precisión. Cualquier documento que XImage.OCR haya procesado con precisión degradada debido a sesgo, ruido o baja resolución ahora tiene un camino directo a la mejora a través de input.Deskew(), input.DeNoise() y input.Contrast(). No se requiere ninguna biblioteca externa de procesamiento de imágenes, el equipo de desarrollo carece de experiencia en procesamiento de imágenes y no hay ninguna dependencia aparte que licenciar y mantener. Añadir tres líneas después de LoadImage() recupera entre 20 y 35 puntos porcentuales de precisión en documentos escaneados que antes se consideraban suficientemente buenos. La guía de corrección de calidad de imagen y la página de características de preprocesamiento cubren el efecto de cada filtro en diferentes escenarios de calidad de documentos.
Los PDF con capacidad de búsqueda y los datos estructurados eliminan los costos de un segundo SDK. Las dos solicitudes más comunes de los usuarios de XImage.OCR (salida PDF con capacidad de búsqueda y datos a nivel de palabra con coordenadas) requieren productos RasterEdge adicionales que implican licencias comerciales separadas. Después de la migración, result.SaveAsSearchablePdf() produce documentos con calidad archivística y capacidad de búsqueda sin paquetes adicionales, y result.Words proporcionan datos estructurados con cuadros de delimitación y puntajes de confianza. La funcionalidad que antes costaba dos licencias ahora se obtiene con una sola. La documentación completa sobre el formato de salida se encuentra en la página de características de los resultados de OCR .
El procesamiento paralelo se escala sin penalizaciones de memoria. El modelo de controlador por hilo de XImage.OCR hace que la escalabilidad sea costosa. Duplicar el número de hilos duplica la memoria consumida por las instancias del motor OCR. El modelo de instancia compartida de IronOCR implica que la memoria se mantiene limitada al tamaño de una sola instancia, independientemente del paralelismo. Un servidor que procesa lotes de documentos en ocho hilos concurrentes consume la misma memoria del motor OCR que un servidor que procesa un documento a la vez. Esto se traduce directamente en menores costos de alojamiento y mayor capacidad de procesamiento en infraestructura fija.
El despliegue multiplataforma se abre sin cambios de código. El mismo paquete IronOcr y el mismo código de aplicación se ejecutan en Windows, Linux, macOS, Docker, Azure App Service y AWS Lambda. Sin código condicionado a la plataforma, sin variantes de paquetes específicas para cada plataforma, sin pruebas de implementación de la capa OCR en entornos específicos. Los equipos que utilizan contenedores para sus cargas de trabajo, ejecutan entornos de desarrollo macOS o implementan soluciones en infraestructuras en la nube basadas en Linux obtienen compatibilidad inmediata. La guía de implementación de Docker , la guía de implementación de Azure y la guía de implementación de Linux documentan la configuración para cada entorno de destino.
Más de 125 idiomas eliminan el límite de cobertura lingüística. XImage.OCR ofrece un máximo de aproximadamente quince idiomas disponibles en paquetes comerciales. Las distribuciones estándar de tessdata incluyen más de 100 idiomas sin costo.IronOCR incluye más de 125 idiomas y los expone a través de paquetes IronOcr.Languages.* opcionales que siguen un patrón de instalación limpia sin la restricción de bloqueo de versión. Están disponibles los 24 idiomas oficiales de la UE, todos los principales idiomas CJK, el árabe, el hebreo y los alfabetos especializados. El índice de idiomas enumera todos los idiomas compatibles con el nombre de su paquete correspondiente.
