PDF Oxide vs lopdf
lopdf es un crate Rust de bajo nivel para manipular objetos PDF directamente — sin extracción de texto ni renderizado incorporados. PDF Oxide es la biblioteca de alto nivel con extracción, creación y edición de fábrica. Son crates orientados a casos de uso distintos.
Diferencias clave
Nivel de abstracción. lopdf te da objetos PDF crudos — diccionarios, streams y tablas de referencias cruzadas. No hay extracción de texto, no hay decodificación de fuentes, no hay exportación de imágenes. PDF Oxide proporciona métodos diseñados específicamente: extract_text(), extract_images(), to_markdown().
Confiabilidad. lopdf falla al parsear el 20% del corpus de prueba de 3,830 PDFs. De los PDFs que sí puede parsear, el 57% produce una salida vacía porque lopdf no tiene extracción de texto — obtienes los objetos pero no el texto. PDF Oxide pasa el 100%.
Velocidad en PDFs parseables. lopdf es más rápido en el parseo crudo de objetos: 0.3ms promedio vs 0.8ms de PDF Oxide. Pero lopdf no realiza trabajo de extracción de texto — necesitarías construir decodificación de fuentes, resolución de CMap, análisis de espaciado y orden de lectura tú mismo.
Comparación rápida
| PDF Oxide | lopdf | |
|---|---|---|
| Nivel de API | Alto nivel | Bajo nivel |
| Extracción de texto | Integrada (nivel de producción) | Ninguna |
| Tasa de éxito (3,830 PDFs) | 100% | 80.2% |
| Tiempo promedio de parseo | 0.8ms | 0.3ms |
| Extracción de imágenes | Integrada | Manual (streams crudos) |
| Campos de formulario | Lectura + Escritura | Manual (diccionarios crudos) |
| Creación de PDF | Sí (Markdown/HTML) | Sí (objetos crudos) |
| Salida Markdown/HTML | Sí | No |
| Cifrado | Lectura + Escritura | No |
| Renderizado | Sí | No |
| Validación PDF/A | Sí | No |
| Licencia | MIT | MIT |
Lo que lopdf no puede hacer
lopdf proporciona acceso a objetos PDF, pero la extracción de texto requiere interpretar esos objetos según la especificación PDF. Esto es lo que tendrías que construir tú mismo:
- Parseo de content stream — parsear operadores tipo PostScript (Tj, TJ, Tm, Tf, etc.)
- Resolución de fuentes — buscar recursos /Font, resolver referencias indirectas
- Decodificación CMap/ToUnicode — convertir IDs de glifos a caracteres Unicode
- Espaciado por métricas de fuente — calcular anchos de caracteres desde descriptores de fuente
- Transformaciones de matriz de texto — aplicar operadores Tm, Td, T* para posicionar texto
- Orden de lectura — determinar el orden correcto para layouts multicolumna
- Reconstrucción de ligaduras — manejar ligaduras fi, fl, ffi
- Codificación CJK — decodificar codificaciones de texto chino, japonés y coreano
Esto son miles de líneas de código y conocimiento profundo de ISO 32000. PDF Oxide maneja todo esto internamente.
Código lado a lado
Extracción de texto
PDF Oxide:
use pdf_oxide::PdfDocument;
let mut doc = PdfDocument::open("report.pdf")?;
let text = doc.extract_text(0)?;
println!("{}", text);
lopdf:
use lopdf::Document;
let doc = Document::load("report.pdf")?;
// lopdf no proporciona extracción de texto.
// Solo obtienes acceso a objetos PDF:
let page_id = doc.page_iter().next().unwrap();
let page = doc.get_dictionary(page_id)?;
let contents = page.get("Contents")?;
let stream = doc.get_object(contents.as_reference()?)?;
// Para obtener texto real, debes:
// 1. Parsear operadores del content stream
// 2. Resolver referencias de fuentes desde /Resources
// 3. Decodificar mapeos CMap/ToUnicode
// 4. Aplicar transformaciones de matriz de texto
// 5. Manejar diferencias de codificación
// ... (cientos a miles de líneas de código)
Creación de PDF
PDF Oxide:
use pdf_oxide::api::Pdf;
let pdf = Pdf::from_markdown("# Report\n\n| Q1 | Q2 |\n|---|---|\n| $1M | $2M |")?;
pdf.save("report.pdf")?;
lopdf:
use lopdf::{Document, Object, Stream, dictionary};
let mut doc = Document::with_version("1.5");
// Crear diccionario de fuente
let font_id = doc.add_object(dictionary! {
"Type" => "Font",
"Subtype" => "Type1",
"BaseFont" => "Helvetica",
});
// Crear recursos
let resources_id = doc.add_object(dictionary! {
"Font" => dictionary! { "F1" => font_id },
});
// Crear content stream (operadores PostScript crudos)
let content = Stream::new(
dictionary! {},
b"BT /F1 12 Tf 72 720 Td (Hello World) Tj ET".to_vec(),
);
let content_id = doc.add_object(content);
// Crear página
let page_id = doc.add_object(dictionary! {
"Type" => "Page",
"MediaBox" => vec![0.into(), 0.into(), 612.into(), 792.into()],
"Contents" => content_id,
"Resources" => resources_id,
});
// Conectar árbol de páginas
let pages_id = doc.add_object(dictionary! {
"Type" => "Pages",
"Kids" => vec![page_id.into()],
"Count" => 1,
});
doc.add_object(dictionary! {
"Type" => "Catalog",
"Pages" => pages_id,
});
doc.save("report.pdf")?;
PDFs cifrados
PDF Oxide:
use pdf_oxide::PdfDocument;
let doc = PdfDocument::open_with_password("encrypted.pdf", "secret")?;
let text = doc.extract_text(0)?;
println!("{}", text);
lopdf:
// lopdf no soporta PDFs cifrados.
// Cargar un PDF cifrado fallará o producirá streams sin descifrar.
Comparación de confiabilidad
| Métrica | PDF Oxide | lopdf |
|---|---|---|
| PDFs parseados exitosamente | 3,823 / 3,823 (100%) | 3,071 / 3,823 (80.2%) |
| PDFs con salida de texto | 3,823 / 3,823 | ~1,320 / 3,823 (estimado) |
| Soporte de PDFs cifrados | Sí | No |
| Recuperación de PDFs malformados | Sí | No |
La tasa de éxito del 80.2% de lopdf significa que falla en aproximadamente 1 de cada 5 PDFs. Los fallos ocurren en documentos cifrados, PDFs con tablas xref no estándar y documentos que usan streams de referencias cruzadas. PDF Oxide maneja todos estos con parseo permisivo y estrategias de respaldo.
Cuándo usar cada uno
Elige PDF Oxide si:
- Necesitas extracción de texto, extracción de imágenes o cualquier operación a nivel de contenido
- Quieres un único crate para lectura + escritura + creación
- Necesitas manejar todos los PDFs de manera confiable (cifrados, malformados, complejos)
- Necesitas salida Markdown/HTML, renderizado u OCR
- Quieres validación de conformidad (PDF/A, PDF/X, PDF/UA)
Elige lopdf si:
- Necesitas acceso directo a objetos PDF para procesamiento personalizado
- Estás construyendo una herramienta PDF especializada que trabaja a nivel de objetos
- Necesitas fusionar documentos manipulando directamente árboles de objetos
- Tus PDFs son simples y bien formados (no cifrados, tablas xref estándar)
Combinar ambos:
Usa PDF Oxide para operaciones de alto nivel y lopdf para casos extremos que requieran acceso crudo a objetos:
[dependencies]
pdf_oxide = "0.3"
lopdf = "0.32"
Páginas relacionadas
- Benchmarks de rendimiento — resultados completos del corpus
- vs Bibliotecas PDF para Rust — todos los crates de Rust comparados
- Primeros pasos con Rust — instalación y primera extracción