Artículo técnico

Linealización de PDF y Fast Web View: Cómo funciona

Ponga un informe escaneado de 80 MB detrás de un enlace, ábralo en un navegador y observe lo que sucede: el visor permanece en un panel en blanco hasta que una gran fracción de esos bytes ha llegado, luego pinta la página uno de una vez. Salte a la página 40 y, en un archivo mal construido, toda la descarga puede reiniciarse. La parte frustrante es que el lector solo quería la primera página. La linealización es la respuesta estructural a ese problema. Reorganiza un PDF para que un visor pueda renderizar la página de inicio desde un pequeño prefijo del archivo y buscar el resto a pedido, por lo que Adobe comercializa la función como "Fast Web View" (Vista web rápida)

Nada de esto es un formato de archivo diferente. Un PDF linealizado es un PDF ordinario que un lector conforme abrirá sin ningún manejo especial. El truco está completamente en cómo se ordenan los bytes y en dos estructuras adicionales que lleva el archivo. La norma ISO 32000-1 especifica toda la disposición en el Anexo F, y una vez que ha visto el diseño, el comportamiento deja de parecer mágico y comienza a verse como un intercambio deliberado del orden de los archivos por la latencia de primer pintado (first-paint)

Lo que realmente reorganiza la linealización

Un PDF normal puede esparcir sus objetos en casi cualquier orden. La tabla de referencias cruzadas al final del archivo es lo que hace que eso funcione: un lector busca al final, lee el puntero startxref, carga la tabla de referencias cruzadas (xref) y, a partir de ahí, puede ubicar cada objeto por su desplazamiento. Ese diseño es excelente para archivos locales, donde buscar hasta el final no cuesta nada, y deficiente para un archivo que se transmite a través de una red, donde el final es exactamente la parte que llega al último. Para representar la página uno, un lector convencional necesita el objeto de la página, su flujo de contenido, las fuentes a las que hace referencia y cualquier imagen que dibuje, y en un archivo sin ordenar estos pueden ubicarse en cualquier lugar, incluido el megabyte final

La linealización arregla el orden. Los objetos necesarios para mostrar la primera página se reúnen en un bloque contiguo cerca del frente, justo después de una pequeña sección de encabezado, para que lleguen temprano en el flujo de bytes. Todo lo demás, las páginas restantes y los recursos que comparten, sigue en una secuencia predecible. Una segunda tabla completa de referencias cruzadas todavía vive al final para los lectores que ignoran la optimización, pero un archivo linealizado también coloca una referencia cruzada de la primera página y los parámetros que necesita un lector de transmisión al frente. El lector ya no tiene que llegar a la cola antes de poder dibujar algo

El conjunto de objetos de la primera página y el diccionario de parámetros de linealización

El primer objeto en un archivo linealizado, después del encabezado %PDF, es el diccionario de parámetros de linealización. Es lo que busca un lector de transmisión (streaming) para decidir si la optimización está presente y cómo usarla. El diccionario registra la longitud de todo el archivo, el desplazamiento de bytes donde comienza la sección de referencias cruzadas principal, el número de objeto de la primera página y la ubicación y longitud del flujo de pistas (hint stream) que sigue. Con esos números, un lector sabe, solo por los kilobytes iniciales, cuánto debe buscar para mostrar la página uno y dónde buscar el índice que le permita saltar a otro lugar

El Anexo F es estricto sobre lo que significa "primera página" aquí. La sección de la primera página debe contener el objeto de la página en sí, sus flujos de contenido y los recursos a los que hacen referencia esos flujos, para que la página sea autosuficiente una vez que ese prefijo se haya descargado. Los recursos compartidos, una fuente usada en cada página, un logotipo que se repite en un encabezado, se manejan de manera especial: aparecen lo suficientemente temprano para servir a la primera página pero se marcan como compartidos para que el lector no vuelva a buscarlos cuando luego renderice la página 30. Esa distinción entre objetos privados de la página y compartidos es la parte que más equivocan los "optimizadores" de cosecha propia, y equivocarse es lo que produce un archivo que dice estar linealizado pero aún se estanca

Flujos de pistas (hint streams): el índice que abarata los saltos de página

Mostrar la página uno rápidamente es solo la mitad del valor. La otra mitad es saltar a una página arbitraria sin descargar todo lo que hay en el medio, y eso es lo que proporcionan los flujos de pistas. Un archivo linealizado contiene una tabla de pistas de desplazamiento de página y una tabla de pistas de objetos compartidos, almacenadas como un flujo referenciado desde el diccionario de parámetros. La tabla de desplazamiento de página registra, para cada página, dónde comienzan sus objetos en el archivo y cuánto duran. La tabla de objetos compartidos hace lo mismo para los recursos utilizados en varias páginas

Dadas esas tablas, un lector que quiere la página 40 no analiza el archivo secuencialmente. Consulta la tabla de pistas para aprender el rango de bytes que ocupa la página 40, le pide al servidor exactamente ese rango y renderiza la página una vez que llegan esos bytes, extrayendo los recursos compartidos que aún no tiene a través del mismo mecanismo. El flujo de pistas es, en efecto, un mapa de acceso aleatorio sobre el documento, y es la razón por la que un archivo de 500 páginas bien linealizado se siente receptivo a través de un enlace lento mientras que uno no optimizado del mismo tamaño no lo hace

Por qué el servidor tiene que cooperar

La linealización asume que el transporte puede entregar porciones arbitrarias del archivo, y vale la pena verificar esa suposición antes de dar crédito al formato por los malos resultados. El mecanismo es la entrega de bytes HTTP (HTTP byte-serving): el lector emite solicitudes de rango (range requests) y el servidor las responde con respuestas 206 Partial Content. Si el servidor no anuncia Accept-Ranges: bytes, o si un proxy o CDN frente a él colapsa las solicitudes de rango en transferencias completas, el lector no tiene forma de recuperar la página 40 de forma aislada y recurre a la descarga de todo el archivo. La estructura dentro del PDF es entonces perfectamente correcta y se desperdicia por completo

Esta es la falla que con mayor frecuencia se diagnostica erróneamente como "la linealización no funciona". El archivo está bien; la ruta de entrega no lo está. Antes de reconstruir un documento, confirme con una solicitud condicional que el host realmente devuelva contenido parcial para la URL a la que accede el lector. Muchos hosts estáticos hacen esto por defecto, y muchos servidores de aplicaciones y capas de almacenamiento en caché mal configurados no lo hacen

Las actualizaciones incrementales rompen silenciosamente la linealización

Aquí está la restricción que sorprende a la gente que genera archivos linealizados correctamente y luego se pregunta por qué se evapora la optimización. La linealización depende de un diseño único, cuidadosamente ordenado con su índice en la parte delantera. Una actualización incremental viola eso por diseño. Cuando una herramienta agrega una firma, completa un campo de formulario o agrega una anotación a través de un guardado incremental, no reescribe el archivo. Agrega los objetos cambiados, una nueva sección de referencias cruzadas y un nuevo tráiler al final, dejando los bytes originales intactos. Esa adición es el punto principal de las actualizaciones incrementales: es rápida y conserva la revisión anterior para la validación de auditoría o firma

El efecto secundario es que el archivo ahora tiene sus datos de referencias cruzadas más nuevos en la cola, después del bloque de la primera página cuidadosamente colocado, y el diccionario de parámetros de linealización en el frente describe un diseño que ya no coincide con el archivo. Un lector conforme detecta la falta de coincidencia y trata el documento como un PDF normal, no linealizado. Fast Web View ha desaparecido, a pesar de que la estructura linealizada original todavía está allí sentada en la primera mitad del archivo. Si usted agrega varias actualizaciones, cada una apila otra revisión en el extremo y la brecha entre el índice frontal obsoleto y el estado real se amplía

Si su flujo de trabajo necesita tanto ediciones como Fast Web View, la regla se deriva directamente de la estructura: edite de forma incremental mientras el documento está en proceso, luego vuelva a linealizar una vez al final. Una reescritura completa es lo que restaura el diseño. En términos de HotPDF, eso significa que una edición en curso pasa por BeginIncrementalUpdate y SaveIncrementalUpdate, que agregan un delta, mientras que el paso final carga todo el documento y lo serializa fresco con LoadFromFile seguido de SaveLoadedDocument, que elimina las revisiones antiguas acumuladas y emite un diseño limpio. El mismo intercambio aparece con los flujos de objetos: habilitar UseObjectStreams junto con UseXRefStream comprime la referencia cruzada y empaqueta los objetos firmemente, lo que ayuda al tamaño del archivo pero, como cualquier elección estructural, debe aplicarse durante esa reescritura final en lugar de atornillarse a una revisión adjunta

// In-flight edits: append a delta, keep prior revisions intact.
// This leaves the file NOT linearized.
Pdf.BeginIncrementalUpdate('report.pdf');
Pdf.AddPage;
Pdf.CurrentPage.TextOut(72, 760, 0, 'Addendum');
Pdf.SaveIncrementalUpdate('report.pdf');

// Finishing step: full re-serialization produces one clean layout,
// dropping the stacked revisions. Re-run your linearizer on the output.
Pdf.LoadFromFile('report.pdf');
Pdf.SaveLoadedDocument('report-final.pdf');

HotPDF no expone una rutina de "linealizar" de una sola llamada, por lo que el patrón práctico es producir un archivo limpio, completamente reescrito y ejecutar un optimizador dedicado sobre él. Las herramientas de línea de comandos manejan el reordenamiento directamente. qpdf reescribe un archivo a forma linealizada con un solo indicador:

qpdf --linearize report-final.pdf report-web.pdf

Cómo saber si un archivo está linealizado

No confíe en el nombre del archivo o en la herramienta que dice haberlo producido; verifique los bytes. La verificación más directa es el encabezado del archivo: ábralo y busque el diccionario de parámetros de linealización como el primer objeto después del encabezado, que lleva la clave /Linearized. Un atajo para el lector es el cuadro de diálogo Propiedades del documento de Acrobat, que informa "Fast Web View: Sí" solo cuando la estructura está genuinamente presente y actualizada

Para comprobaciones mediante scripts, qpdf informa tanto la presencia como la integridad de la estructura, lo que importa porque un archivo puede llevar un diccionario de linealización que ya no refleja su diseño, exactamente el estado que deja una actualización incremental:

# Reports "File is linearized" and validates hint tables against the layout
qpdf --check report-web.pdf

# Dumps the linearization parameters and hint data in detail
qpdf --show-linearization report-web.pdf

El paso de validación es el que se gana el sueldo. Una pasada que solo confirme que el diccionario existe bendecirá felizmente un archivo cuyo índice apunte a los desplazamientos incorrectos; una verificación que concilie las tablas de pistas con las posiciones reales de los objetos es lo que le dice si la optimización resistirá bajo las solicitudes de rango de un lector real

Aún vale la pena aplicar la linealización a cualquier documento grande servido a través de la web, especialmente para lectores móviles en conexiones irregulares, y cuesta un pequeño porcentaje del tamaño del archivo para el índice cargado al principio. Las dos cosas a tener en cuenta son que la estructura dentro del PDF y la entrega de bytes fuera de él deben ser correctas, y que cualquier edición posterior deshace la optimización hasta que se reescribe el archivo. Trate la re-linealización como el último paso en la tubería (pipeline), después de que todos los demás cambios estén resueltos. El comportamiento de referencias cruzadas, flujos de objetos y actualizaciones incrementales descrito aquí es parte del modelo estructural que implementa el componente HotPDF para Delphi y C++Builder; para conocer los antecedentes más amplios del diseño de archivos, consulte cómo está estructurado un PDF, y para el flujo de trabajo de archivos grandes y actualización incremental en código, consulte el procesamiento de PDF grandes desde Delphi