Skip to content

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 No
Cifrado Lectura + Escritura No
Renderizado No
Validación PDF/A 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:

  1. Parseo de content stream — parsear operadores tipo PostScript (Tj, TJ, Tm, Tf, etc.)
  2. Resolución de fuentes — buscar recursos /Font, resolver referencias indirectas
  3. Decodificación CMap/ToUnicode — convertir IDs de glifos a caracteres Unicode
  4. Espaciado por métricas de fuente — calcular anchos de caracteres desde descriptores de fuente
  5. Transformaciones de matriz de texto — aplicar operadores Tm, Td, T* para posicionar texto
  6. Orden de lectura — determinar el orden correcto para layouts multicolumna
  7. Reconstrucción de ligaduras — manejar ligaduras fi, fl, ffi
  8. 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 No
Recuperación de PDFs malformados 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