La anatomía de un archivo PDF
De un vistazo
Sección titulada «De un vistazo»Abre cualquier PDF en un editor de texto plano y lo primero que ves es
tranquilizador: un encabezado %PDF-1.x o %PDF-2.0. Lo último que ves es
%%EOF. Todo lo que hay entre esas dos líneas es una pequeña y ordenada máquina
para encontrar objetos por número. Esta página es una disección. Abrimos el
archivo, nombramos cada órgano y mostramos cómo se conectan.
Es el complemento estructural de dos páginas vecinas. Qué es realmente un PDF trata el archivo como un grafo de objetos; actualizaciones incrementales cubre cómo crece con el tiempo. Esta página se mantiene cerca de los bytes: las regiones físicas que recorre un analizador, en el orden en que están en el disco.
Por qué esto importa
Sección titulada «Por qué esto importa»Casi nunca se necesita esto para usar un PDF. Se necesita el día en que uno se estropea. Un archivo se abre en un visor y en otro no; un validador informa de una «tabla de referencias cruzadas dañada»; un documento firmado de pronto no se verifica. Ninguno de esos es un misterio una vez que se sabe leer la anatomía. Son un número que ya no coincide con una posición, una región en el lugar equivocado o una cola que no apunta a nada.
Conocer la disposición convierte «el PDF está corrupto» en un diagnóstico sobre el que se puede actuar. Es la diferencia entre encogerse de hombros ante una caja negra y señalar el byte exacto que miente.
La versión corta
Sección titulada «La versión corta»Un PDF conforme tiene cuatro partes físicas, en este orden dentro del archivo (Spec: ISO 32000-2, §7.5.1ISO 32000-2 §7.5.1):
- Un encabezado: una línea,
%PDF-2.0, que nombra la versión. - Un cuerpo: el grueso del archivo: una sucesión de objetos indirectos numerados.
- Una sección de referencias cruzadas: un índice que va del número de objeto al desplazamiento de bytes donde reside ese objeto. Los PDF clásicos usan una tabla de texto; PDF 2.0 usa un flujo xref comprimido.
- Un tráiler: un pequeño diccionario que nombra el punto de entrada, seguido
de
startxref, un desplazamiento y%%EOF.
El giro: un lector no empieza por arriba. Empieza por abajo, lee startxref
para encontrar el índice y usa ese índice para llegar a cualquier objeto
directamente. El archivo se escribe de principio a fin pero se lee de fin a
principio.
Cómo lo aborda NextPDF
Sección titulada «Cómo lo aborda NextPDF»Recorramos las cuatro regiones en orden, con los bytes delante.
El encabezado es una línea. NextPDF escribe %PDF-2.0 y, por convención, una
segunda línea de comentario con bytes de bit alto para que las herramientas de
transferencia ingenuas traten el archivo como binario, no como texto. Esa segunda
línea es la razón por la que un PDF abierto como texto plano muestra un poco de
basura justo después de la versión.
El cuerpo es donde vive el documento. Cada objeto indirecto es un número,
una generación, la palabra clave obj, un valor y endobj
(Spec: ISO 32000-2, §7.3.10ISO 32000-2 §7.3.10). El valor es una de unas pocas
formas, pero dos soportan casi todo el peso:
- Un diccionario,
<< /Key value … >>, es un mapa de nombres a valores. El árbol de páginas, el catálogo, los descriptores de fuentes: todos son diccionarios. - Un flujo es un diccionario seguido de
stream, un bloque de bytes arbitrarios yendstream. El contenido de página, las fuentes incrustadas y las imágenes son flujos, casi siempre comprimidos. (Sus filtros son toda una historia aparte, contada en flujos y filtros.)
Los objetos se apuntan unos a otros mediante referencia indirecta: 2 0 R
significa «objeto 2, generación 0». Ese es el cableado que convierte una lista
plana de objetos en un grafo.
La sección de referencias cruzadas es la parte que la mayoría nunca se imagina
correctamente. En la forma clásica es texto plano: la palabra clave xref, luego
subsecciones de líneas de ancho fijo de 20 bytes (Spec: ISO 32000-2, §7.5.4ISO 32000-2 §7.5.4). Cada línea es un desplazamiento de bytes de diez dígitos, una
generación de cinco dígitos y un único indicador —n para en uso, f para
libre— rellenado hasta exactamente veinte bytes para que un lector pueda
desplazarse a cualquier entrada solo con aritmética. PDF 2.0 reemplaza esto por un
flujo de referencias cruzadas: el mismo índice, pero binario y comprimido
dentro de un objeto de flujo marcado /Type /XRef
(Spec: ISO 32000-2, §7.5.8ISO 32000-2 §7.5.8). Más pequeño, y capaz de
describir objetos empaquetados dentro de flujos de objetos.
El tráiler es el índice del archivo (Spec: ISO
32000-2, §7.5.5ISO
32000-2 §7.5.5). Nombra /Root —el catálogo del documento, el único
objeto del que cuelga todo lo demás— y /Size, el número de objetos. Luego viene
el apretón de manos que hace posible la lectura hacia atrás: startxref, un
desplazamiento de bytes en su propia línea y %%EOF. Un lector se desplaza al
final, lee ese desplazamiento, salta directo a la sección de referencias cruzadas
y se pone en marcha.
- EncabezadoUna línea, %PDF-2.0, que nombra la versión. Suele seguir un comentario marcador de binario.
- CuerpoObjetos indirectos numerados —diccionarios y flujos— referenciados por N G R.
- Sección de referencias cruzadasUna tabla de texto de entradas de 20 bytes, o un flujo /Type /XRef comprimido en PDF 2.0.
- TráilerNombra /Root y /Size, luego startxref + desplazamiento + %%EOF.
- Orden de lecturaUn lector empieza en %%EOF, sigue startxref hasta el índice y luego llega a cada objeto directamente.
Hay una quinta región que un archivo de larga vida hace crecer: una
actualización incremental. Un cambio no se escribe en su sitio. Los objetos
modificados, una nueva sección de referencias cruzadas y un nuevo tráiler se
anexan después del primer %%EOF, y ese nuevo tráiler lleva /Prev: el
desplazamiento de la sección de referencias cruzadas anterior
(Spec: ISO 32000-2, §7.5.6ISO 32000-2 §7.5.6). Las secciones forman una
cadena hacia atrás; para cualquier número de objeto, prevalece la entrada más
reciente. Como los bytes originales nunca se mueven, la comprobación
criptográfica sobre el rango de bytes que una firma realmente cubre sigue siendo
válida tras una actualización. Una actualización incremental posterior aún puede
cambiar lo que un validador informa sobre el documento en su conjunto —si los
cambios posteriores a la firma están permitidos y qué se considera que certifica
la firma—, pero no puede alterar los propios bytes firmados. Esa propiedad es
todo el tema de actualizaciones
incrementales.
Ejemplo práctico
Sección titulada «Ejemplo práctico»Aquí está toda la anatomía en un archivo mínimo. Los números bajo xref son
desplazamientos de bytes, y tienen que ser exactos: apunta un carácter más allá
de donde empieza un objeto y un lector estricto se rinde.
%PDF-2.01 0 obj<< /Type /Catalog /Pages 2 0 R >>endobj2 0 obj<< /Type /Pages /Kids [3 0 R] /Count 1 >>endobj3 0 obj<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] >>endobjxref0 40000000000 65535 f0000000009 00000 n0000000058 00000 n0000000115 00000 ntrailer<< /Size 4 /Root 1 0 R >>startxref186%%EOFLéelo como lo hace un analizador. Última línea: %%EOF. Encima: startxref 186,
así que desplázate al byte 186, donde empieza xref. La tabla dice que el objeto
1 reside en el byte 9. El /Root 1 0 R del tráiler apunta ahí —el catálogo— y
desde el catálogo recorres /Pages hasta el árbol de páginas y encuentras la
única página. El objeto 0 es siempre la cabecera de la lista de libres con
generación 65535, un fósil del primer diseño del formato que todo lector aún
espera ver.
Concepto erróneo habitual
Sección titulada «Concepto erróneo habitual»La trampa es leer un PDF como una historia: de arriba abajo, en orden. No es una
historia; es un índice con un puntero hacia atrás. Los números de objeto no tienen
por qué ser secuenciales en el archivo, los objetos pueden aparecer en cualquier
orden físico, y un lector nunca depende de su posición. El único mapa con
autoridad es la sección de referencias cruzadas, y la única forma de encontrar ese
mapa es el desplazamiento startxref al final del todo.
La consecuencia sorprende a la gente. Un PDF con un cuerpo impecable y un dígito
equivocado en startxref es ilegible: el lector no puede encontrar el índice. Un
PDF con sus objetos en orden desordenado pero una sección de referencias cruzadas
correcta está perfectamente bien. La posición física no tiene significado. La
posición registrada lo tiene todo.
Límites y fronteras
Sección titulada «Límites y fronteras»Esta página describe la estructura física, no el contenido de la página. Cómo
llegan las marcas a una página —operadores del flujo de contenido, presentación de
texto, estado gráfico— es un tema aparte. También describe un archivo bien
formado. Los PDF del mundo real están con frecuencia un poco rotos y sobreviven
solo porque los visores indulgentes reconstruyen la tabla de referencias cruzadas
buscando palabras clave obj. Ese rescate es un comportamiento del visor, no algo
que el formato garantice.
| Edition | Availability |
|---|---|
| Core | NextPDF es un escritor. Registra cada desplazamiento del búfer de salida en el momento en que se emite cada objeto, de modo que los archivos que produce tienen una sección de referencias cruzadas que coincide con el cuerpo por construcción. |
| Pro | Analizar, reconstruir o reparar una tabla de referencias cruzadas dañada en un archivo que NextPDF no escribió queda fuera de alcance en todas las ediciones. |
| Enterprise | Para inspeccionar la estructura de un archivo existente, usa un analizador o validador dedicado; NextPDF garantiza la corrección de lo que escribe, no de lo que lee. |
Mini-FAQ
Sección titulada «Mini-FAQ»¿Por qué un PDF tiene una línea marcadora de binario después del encabezado? Algunas herramientas de transferencia más antiguas estropeaban un archivo que creían texto plano. El comentario de bit alto hace que el archivo parezca inequívocamente binario, así que sobrevive al trayecto sin cambios.
¿El flujo xref es solo una tabla más pequeña? Más o menos, con un poder extra. Además de estar comprimido, un flujo xref puede describir objetos almacenados dentro de flujos de objetos: entradas que la clásica tabla de texto de 20 bytes no tiene forma de expresar.
¿Puedo tener a la vez una tabla y un flujo en un mismo archivo? Una única revisión usa una u otro. Pero un archivo híbrido puede emparejar una tabla clásica para lectores antiguos con un flujo de referencias cruzadas para los nuevos, de modo que cada tipo de lector encuentre un índice que entienda.
Documentos relacionados
Sección titulada «Documentos relacionados»- Qué es realmente un PDF: las mismas cuatro partes vistas como un grafo de objetos en lugar de una disposición física.
- Actualizaciones incrementales y por qué importan: cómo la quinta región anexada hace crecer un archivo y protege las firmas.
- Flujos y filtros: qué hay dentro de los objetos de flujo del cuerpo y cómo se comprimen.
- PDF 2.0: qué cambió: por qué el flujo de referencias cruzadas es la estructura por defecto que NextPDF escribe.
Glosario
Sección titulada «Glosario»- Encabezado: la primera línea,
%PDF-2.0, que nombra la versión; suele ir seguida de un comentario marcador de binario. - Objeto indirecto: un objeto numerado en el cuerpo, escrito
N G obj … endobj, dondeNes el número de objeto yGla generación. - Diccionario: un mapa
<< /Key value … >>de nombres a valores; la forma de objeto más común. - Flujo: un diccionario más un bloque de bytes entre
streamyendstream, usado para contenido, fuentes e imágenes. - Tabla de referencias cruzadas (xref): el índice que va del número de objeto
al desplazamiento de bytes; clásicamente una tabla de texto de 20 bytes por
entrada, un flujo
/Type /XRefen PDF 2.0. - Tráiler: el diccionario que nombra
/Rooty/Size, localizado mediante el desplazamientostartxrefal final del archivo. - Actualización incremental: objetos modificados, una nueva sección de
referencias cruzadas y un nuevo tráiler anexados después de
%%EOF, con/Prevencadenando hacia atrás a la sección anterior.