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:
- Análise de content stream — analisar operadores semelhantes a PostScript (Tj, TJ, Tm, Tf, etc.)
- Resolução de fontes — buscar recursos /Font, resolver referências indiretas
- Decodificação CMap/ToUnicode — converter IDs de glifos para caracteres Unicode
- Espaçamento por métricas de fonte — calcular larguras de caracteres a partir de descritores de fonte
- Transformações de matriz de texto — aplicar operadores Tm, Td, T* para posicionar texto
- Ordem de leitura — determinar a ordem correta para layouts de múltiplas colunas
- Reconstrução de ligaturas — lidar com ligaturas fi, fl, ffi
- 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
- Benchmarks de Desempenho — resultados completos do corpus
- vs Bibliotecas PDF para Rust — todos os crates Rust comparados
- Primeiros Passos com Rust — instalação e primeira extração