Skip to content

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. SaveOptions completo con compress / garbage_collect / linearize está expuesto en Rust (editor.save_with_options(path, opts)) y Python (vía doc.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 que SaveOptions quede 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 con FlateDecode. Los streams ya comprimidos (imágenes JBIG2, tablas CCITT, Flate existente) se dejan intactos.
  • garbage_collect — hace un escaneo de alcance desde /Root e /Info, marca cada objeto indirecto vivo y escribe solo esos en la xref de salida. Útil tras ediciones intensas donde remove_page, flatten_forms o erase_region dejan 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_redactions o 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 FlateDecode con buen predictor, puede que solo ahorres un par de por ciento. Ejecuta pdf-oxide compress una 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