Skip to content

PDF Oxide vs lopdf

O lopdf é um crate Rust de baixo nível para manipular objetos PDF diretamente — sem extração de texto nem renderização embutidos. O PDF Oxide é a biblioteca de alto nível que já vem com extração, criação e edição. Os dois atingem casos de uso fundamentalmente diferentes.

Principais Diferenças

Nível de abstração. O lopdf fornece objetos PDF brutos — dicionários, streams e tabelas de referência cruzada. Não há extração de texto, decodificação de fontes ou exportação de imagens. O PDF Oxide fornece métodos dedicados: extract_text(), extract_images(), to_markdown().

Confiabilidade. O lopdf falha ao analisar 20% do corpus de teste de 3.830 PDFs. Dos PDFs que consegue analisar, 57% produzem saída vazia porque o lopdf não tem extração de texto — você obtém os objetos mas nenhum texto. O PDF Oxide passa 100%.

Velocidade em PDFs analisáveis. O lopdf é mais rápido na análise bruta de objetos: 0.3ms de média vs 0.8ms do PDF Oxide. Mas o lopdf não faz nenhum trabalho de extração de texto — você precisaria construir decodificação de fontes, resolução de CMap, análise de espaçamento e ordem de leitura por conta própria.

Comparação Rápida

PDF Oxide lopdf
Nível de API Alto nível Baixo nível
Extração de texto Integrada (nível de produção) Nenhuma
Taxa de aprovação (3.830 PDFs) 100% 80.2%
Tempo médio de análise 0.8ms 0.3ms
Extração de imagens Integrada Manual (streams brutos)
Campos de formulário Leitura + Escrita Manual (dicionários brutos)
Criação de PDF Sim (Markdown/HTML) Sim (objetos brutos)
Saída Markdown/HTML Sim Não
Criptografia Leitura + Escrita Não
Renderização Sim Não
Validação PDF/A Sim Não
Licença MIT MIT

O Que o lopdf Não Pode Fazer

O lopdf fornece acesso a objetos PDF, mas a extração de texto requer interpretar esses objetos de acordo com a especificação PDF. Veja o que você precisaria construir por conta própria:

  1. Análise de content stream — analisar operadores semelhantes a PostScript (Tj, TJ, Tm, Tf, etc.)
  2. Resolução de fontes — buscar recursos /Font, resolver referências indiretas
  3. Decodificação CMap/ToUnicode — converter IDs de glifos para caracteres Unicode
  4. Espaçamento por métricas de fonte — calcular larguras de caracteres a partir de descritores de fonte
  5. Transformações de matriz de texto — aplicar operadores Tm, Td, T* para posicionar texto
  6. Ordem de leitura — determinar a ordem correta para layouts de múltiplas colunas
  7. Reconstrução de ligaturas — lidar com ligaturas fi, fl, ffi
  8. Codificação CJK — decodificar codificações de texto chinês, japonês e coreano

Isso são milhares de linhas de código e profundo conhecimento da ISO 32000. O PDF Oxide lida com tudo isso internamente.

Código Lado a Lado

Extração 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 does not provide text extraction.
// You get access to PDF objects only:
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()?)?;

// To get actual text, you must:
// 1. Parse content stream operators
// 2. Resolve font references from /Resources
// 3. Decode CMap/ToUnicode mappings
// 4. Apply text matrix transformations
// 5. Handle encoding differences
// ... (hundreds to thousands of lines of code)

Criação 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");

// Create font dictionary
let font_id = doc.add_object(dictionary! {
    "Type" => "Font",
    "Subtype" => "Type1",
    "BaseFont" => "Helvetica",
});

// Create resources
let resources_id = doc.add_object(dictionary! {
    "Font" => dictionary! { "F1" => font_id },
});

// Create content stream (raw PostScript operators)
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);

// Create page
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,
});

// Wire up page tree
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 Criptografados

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 does not support encrypted PDFs.
// Loading an encrypted PDF will fail or produce undecrypted streams.

Comparação de Confiabilidade

Métrica PDF Oxide lopdf
PDFs analisados com sucesso 3.823 / 3.823 (100%) 3.071 / 3.823 (80.2%)
PDFs com saída de texto 3.823 / 3.823 ~1.320 / 3.823 (estimado)
Suporte a PDFs criptografados Sim Não
Recuperação de PDFs malformados Sim Não

A taxa de aprovação de 80.2% do lopdf significa que ele falha em aproximadamente 1 em cada 5 PDFs. As falhas ocorrem em documentos criptografados, PDFs com tabelas xref não padrão e documentos usando streams de referência cruzada. O PDF Oxide lida com todos esses casos com análise leniente e estratégias de fallback.

Quando Usar Cada Uma

Escolha PDF Oxide se:

  • Você precisa de extração de texto, extração de imagens ou qualquer operação em nível de conteúdo
  • Você quer um único crate para leitura + escrita + criação
  • Você precisa lidar com todos os PDFs de forma confiável (criptografados, malformados, complexos)
  • Você precisa de saída Markdown/HTML, renderização ou OCR
  • Você quer validação de conformidade (PDF/A, PDF/X, PDF/UA)

Escolha lopdf se:

  • Você precisa de acesso direto a objetos PDF para processamento personalizado
  • Você está construindo uma ferramenta PDF especializada que trabalha no nível de objetos
  • Você precisa mesclar documentos manipulando árvores de objetos diretamente
  • Seus PDFs são simples e bem formados (não criptografados, tabelas xref padrão)

Combine ambos:

Use PDF Oxide para operações de alto nível e lopdf para casos extremos que requerem acesso bruto a objetos:

[dependencies]
pdf_oxide = "0.3"
lopdf = "0.32"

Páginas Relacionadas