Skip to content

PDF Oxide vs lopdf

O lopdf é um crate Rust de baixo nível para manipulação direta de objetos PDF. O PDF Oxide é uma biblioteca de alto nível com extração de texto, criação e edição integradas. Os dois atendem a casos de uso fundamentalmente diferentes.

Principais diferenças

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

Confiabilidade. O lopdf falha ao analisar 20% do corpus de testes de 3.830 PDFs. Dos PDFs que ele 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 em 100%.

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

Comparação rápida

PDF Oxide lopdf
Nível da 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,8 ms 0,3 ms
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 em 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 consegue fazer

O lopdf dá acesso aos objetos PDF, mas a extração de texto exige interpretar esses objetos de acordo com a especificação do PDF. Veja o que você teria que construir por conta própria:

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

São milhares de linhas de código e um conhecimento profundo da ISO 32000. O PDF Oxide cuida de 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 PDF criptografado Sim Não
Recuperação de PDF malformado Sim Não

A taxa de aprovação de 80,2% do lopdf significa que ele falha em cerca de 1 a cada 5 PDFs. As falhas ocorrem em documentos criptografados, PDFs com tabelas xref não padronizadas e documentos que usam streams de referência cruzada. O PDF Oxide trata todos esses casos com análise tolerante e estratégias de fallback.

Quando usar cada um

Escolha o 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 tratar todos os PDFs de forma confiável (criptografados, malformados, complexos)
  • Você precisa de saída em Markdown/HTML, renderização ou OCR
  • Você precisa de validação de conformidade (PDF/A, PDF/X, PDF/UA)

Escolha o lopdf se:

  • Você precisa de acesso direto aos objetos PDF para processamento personalizado
  • Você está construindo uma ferramenta PDF especializada que trabalha em nível de objeto
  • 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 os dois:

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

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

Páginas relacionadas