Compresión de PDF
DocumentEditor::save_with_options() puede recomprimir streams, recolectar objetos huérfanos y linealizar el archivo para vista web rápida — todo en una sola pasada. La forma más sencilla de aplicar los tres es la CLI pdf-oxide compress, que los envuelve en un único comando.
Cobertura de bindings.
SaveOptionscompleto concompress / garbage_collect / linearizeestá expuesto en Rust (editor.save_with_options(path, opts)) y Python (víadoc.save(..., compress=True, ...)donde esté enlazado). Desde Node, WASM, Go y C#, ejecuta la CLI (pdf-oxide compress input.pdf -o out.pdf) como subproceso o a través de un paso del build — la CLI es la interfaz estable que comparten estos bindings hasta queSaveOptionsquede cableado en cada superficie FFI.
CLI (todas las plataformas)
# Básico: produce input_compressed.pdf
pdf-oxide compress input.pdf
# Salida explícita
pdf-oxide compress input.pdf -o smaller.pdf
# Imprimir comparación de tamaños
pdf-oxide compress report.pdf
# → Compressed report.pdf -> report_compressed.pdf (3412901 -> 1847200 bytes)
La CLI activa compress: true, garbage_collect: true, linearize: true por defecto — esta combinación produce el archivo más pequeño manteniéndose válido según ISO 32000.
API Rust
use pdf_oxide::editor::{DocumentEditor, EditableDocument, SaveOptions};
let mut editor = DocumentEditor::open("input.pdf")?;
editor.save_with_options("output.pdf", SaveOptions {
compress: true, // aplicar FlateDecode a todos los streams sin comprimir
garbage_collect: true, // descartar objetos huérfanos
linearize: true, // linealizar para vista web rápida
..Default::default()
})?;
Campos de SaveOptions
| Campo | Por defecto | Efecto |
|---|---|---|
compress |
true en CLI / false por defecto |
Aplica FlateDecode a los streams almacenados sin compresión |
garbage_collect |
true en CLI |
Descarta objetos indirectos que ya no se referencian desde el trailer |
linearize |
true en CLI |
Emite el layout Linealizado (“Fast Web View”) para que los visores rendericen la página 1 antes de que se descargue el archivo completo |
encryption |
None |
Adjunta una EncryptionConfig para guardar cifrado — ver Cifrado y seguridad |
Lo que hace cada opción realmente
compress— recorre cada content stream, Form XObject, ToUnicode CMap y stream de metadatos; si el stream no tiene filtro o tiene un filtro desconocido, lo reenvuelve conFlateDecode. Los streams ya comprimidos (imágenes JBIG2, tablas CCITT, Flate existente) se dejan intactos.garbage_collect— hace un escaneo de alcance desde/Roote/Info, marca cada objeto indirecto vivo y escribe solo esos en la xref de salida. Útil tras ediciones intensas donderemove_page,flatten_formsoerase_regiondejan huérfanos.linearize— reordena los objetos para que el content stream de la primera página y sus dependencias de recursos aparezcan al inicio del archivo, con un diccionario de linealización y un hint stream. Los lectores PDF descargan el archivo en orden y renderizan la página 1 antes de que llegue todo el archivo, lo cual es el beneficio visible principal para PDFs servidos desde un CDN.
Cuándo comprimir
- Después de ediciones masivas — si ejecutaste
flatten_forms,flatten_all_annotations,apply_all_redactionso borraste varias páginas, GC + recompresión suele reducir el tamaño entre un 30 y un 60 %. - Antes de distribuir o enviar por correo — al usuario final le importa el tamaño, y Linearize hace que la primera página se sienta instantánea en conexiones lentas.
- Como último paso de pipelines ETL — tras la extracción y regeneración, comprime una sola vez al final del pipeline; no descomprimas y recomprimas en cada transformación.
Cuándo NO comprimir
- Durante ediciones incrementales frecuentes — las reescrituras completas pierden xref streams y object streams que mantienen pequeños los appends incrementales. Para bucles interactivos de edición, usa
SaveOptions::incremental()y deja la compresión para una pasada final. - En PDFs ya comprimidos agresivamente — si los streams ya tienen filtros
FlateDecodecon buen predictor, puede que solo ahorres un par de por ciento. Ejecutapdf-oxide compressuna vez y mide antes de cablearlo en tu pipeline.
Expectativas de reducción de tamaño
Ahorros típicos en PDFs del mundo real (medidos sobre un corpus de prueba de 3.830 archivos):
| Origen | Antes | Después | Ahorro |
|---|---|---|---|
| Factura escaneada (streams sin comprimir) | 2,4 MB | 0,8 MB | ~66 % |
| Artículo de investigación en LaTeX | 1,1 MB | 0,95 MB | ~14 % |
| Formulario de gobierno (tras flatten) | 890 KB | 240 KB | ~73 % |
| PDF de marketing ya optimizado | 1,8 MB | 1,75 MB | ~3 % |
Los archivos editados en lote y los formularios tras aplanar son los mayores triunfos. Los archivos ya optimizados ven ahorros modestos solo por la linealización.
Descifra / autentica primero
DocumentEditor por ahora no lleva una llamada de autenticación por contraseña, así que los PDFs cifrados deben descifrarse primero. Usa PdfDocument.open_with_password() para leer, guarda una copia sin cifrar y luego abre esa copia en el editor:
use pdf_oxide::api::Pdf;
use pdf_oxide::editor::{DocumentEditor, EditableDocument, SaveOptions};
let doc = Pdf::open_with_password("protected.pdf", "pw")?;
doc.save("temp-unencrypted.pdf")?;
let mut editor = DocumentEditor::open("temp-unencrypted.pdf")?;
editor.save_with_options("compressed.pdf", SaveOptions {
compress: true,
garbage_collect: true,
linearize: true,
..Default::default()
})?;
El mismo patrón desde Python vía PdfDocument(path, password="pw") + save() + CLI.
Páginas relacionadas
- Visión general de edición —
SaveOptionsy la superficie completa del editor - Cifrado y seguridad — combina
compressconsave_with_encryption - Primeros pasos con la CLI — los 22 comandos de la CLI