L’anatomie d’un fichier PDF
Ouvre n’importe quel PDF dans un éditeur de texte brut et la première chose que tu vois est
rassurante : un en-tête %PDF-1.x ou %PDF-2.0. La dernière chose que tu vois est %%EOF.
Tout ce qui se trouve entre ces deux lignes est une petite machine bien rangée pour retrouver
des objets par numéro. Cette page est une dissection. Nous ouvrons le fichier, nommons chaque
organe et montrons comment ils se connectent.
C’est le pendant structurel de deux pages voisines. Ce qu’est vraiment un PDF traite le fichier comme un graphe d’objets ; les mises à jour incrémentales couvrent la façon dont il grandit au fil du temps. Cette page reste au plus près des octets — les régions physiques qu’un analyseur parcourt, dans l’ordre où elles reposent sur le disque.
Pourquoi c’est important
Section intitulée « Pourquoi c’est important »Tu n’as presque jamais besoin de cela pour utiliser un PDF. Tu en as besoin le jour où l’un d’eux tourne mal. Un fichier s’ouvre dans un visualiseur mais pas dans un autre ; un validateur signale une « table de références croisées endommagée » ; un document signé cesse soudain de se vérifier. Aucun de ces phénomènes n’est un mystère dès que tu sais lire l’anatomie. Ce sont un nombre qui ne correspond plus à une position, une région au mauvais endroit, ou une queue qui pointe vers rien.
Connaître la disposition transforme « le PDF est corrompu » en un diagnostic sur lequel tu peux agir. C’est la différence entre hausser les épaules devant une boîte noire et désigner l’octet exact qui ment.
La version courte
Section intitulée « La version courte »Un PDF conforme comporte quatre parties physiques, dans cet ordre de fichier (Spec: ISO 32000-2, §7.5.1ISO 32000-2 §7.5.1) :
- Un en-tête — une ligne,
%PDF-2.0, qui nomme la version. - Un corps — l’essentiel du fichier : une suite d’objets indirects numérotés.
- Une section de références croisées — un index qui associe le numéro d’objet au décalage d’octets où réside cet objet. Les PDF classiques utilisent une table textuelle ; PDF 2.0 utilise un flux xref compressé.
- Un trailer — un petit dictionnaire qui nomme le point d’entrée, suivi de
startxref, d’un décalage, et de%%EOF.
La subtilité : un lecteur ne commence pas par le haut. Il commence par le bas, lit
startxref pour trouver l’index, et utilise cet index pour atteindre directement n’importe
quel objet. Le fichier est écrit de l’avant vers l’arrière mais lu de l’arrière vers l’avant.
Comment NextPDF l’aborde
Section intitulée « Comment NextPDF l’aborde »Parcourons les quatre régions dans l’ordre, les octets sous les yeux.
L’en-tête est une ligne. NextPDF écrit %PDF-2.0, et par convention une seconde ligne de
commentaire faite d’octets à bit de poids fort pour que les outils de transfert naïfs traitent
le fichier comme binaire, et non comme texte. C’est cette seconde ligne qui fait qu’un PDF
ouvert en texte brut affiche un petit charabia juste après la version.
Le corps est l’endroit où vit le document. Chaque objet indirect est un numéro, une
génération, le mot-clé obj, une valeur, et endobj
(Spec: ISO 32000-2, §7.3.10ISO 32000-2 §7.3.10). La valeur est l’une de quelques formes —
mais deux portent presque tout le poids :
- Un dictionnaire,
<< /Key value … >>, est une table associant des noms à des valeurs. L’arbre des pages, le catalogue, les descripteurs de police : tous des dictionnaires. - Un flux est un dictionnaire suivi de
stream, d’un bloc d’octets arbitraires, et deendstream. Le contenu des pages, les polices intégrées et les images sont des flux, presque toujours compressés. (Leurs filtres sont une histoire à part, racontée dans flux et filtres.)
Les objets se pointent les uns les autres par référence indirecte — 2 0 R signifie
« objet 2, génération 0 ». C’est le câblage qui transforme une liste plate d’objets en
graphe.
La section de références croisées est la partie que la plupart des gens ne se
représentent jamais correctement. Dans la forme classique, c’est du texte brut : le mot-clé
xref, puis des sous-sections de lignes de 20 octets à largeur fixe (Spec: ISO 32000-2, §7.5.4ISO 32000-2 §7.5.4). Chaque ligne est un décalage d’octets à dix chiffres, une génération à
cinq chiffres, et un seul drapeau — n pour en usage, f pour libre — complété à exactement
vingt octets pour qu’un lecteur puisse se positionner sur n’importe quelle entrée par le seul
calcul. PDF 2.0 remplace cela par un flux de références croisées : le même index, mais
binaire et compressé à l’intérieur d’un objet flux marqué /Type /XRef
(Spec: ISO 32000-2, §7.5.8ISO 32000-2 §7.5.8). Plus petit, et capable de décrire des
objets empaquetés à l’intérieur de flux d’objets.
Le trailer est la table des matières du fichier (Spec: ISO
32000-2, §7.5.5ISO
32000-2 §7.5.5). Il nomme /Root — le catalogue du document, l’unique objet
auquel tout le reste est suspendu — et /Size, le nombre d’objets. Vient ensuite la poignée
de main qui rend possible la lecture à rebours : startxref, un décalage d’octets sur sa
propre ligne, et %%EOF. Un lecteur se positionne à la fin, lit ce décalage, saute droit
vers la section de références croisées, et c’est parti.
- HeaderOne line, %PDF-2.0, naming the version. A binary-marker comment usually follows.
- BodyNumbered indirect objects — dictionaries and streams — referenced by N G R.
- Cross-reference sectionA text table of 20-byte entries, or a compressed /Type /XRef stream in PDF 2.0.
- TrailerNames /Root and /Size, then startxref + offset + %%EOF.
- Read orderA reader starts at %%EOF, follows startxref to the index, then reaches each object directly.
Il existe une cinquième région qu’un fichier de longue durée fait croître : une mise à jour
incrémentale. Une modification n’est pas écrite sur place. Les objets modifiés, une nouvelle
section de références croisées et un nouveau trailer sont ajoutés après le premier %%EOF,
et ce nouveau trailer porte /Prev — le décalage de la section de références croisées
précédente (Spec: ISO 32000-2, §7.5.6ISO 32000-2 §7.5.6). Les sections forment une chaîne
arrière ; pour tout numéro d’objet, l’entrée la plus récente l’emporte. Comme les octets
d’origine ne bougent jamais, le contrôle cryptographique sur la plage d’octets qu’une
signature couvre réellement tient toujours après une mise à jour. Une mise à jour
incrémentale ultérieure peut tout de même changer ce qu’un validateur rapporte sur le
document dans son ensemble — si les modifications postérieures à la signature sont autorisées,
et ce que la signature est réputée certifier — mais elle ne peut pas altérer les octets signés
eux-mêmes. Cette propriété est tout le sujet des mises à jour
incrémentales.
Exemple pratique
Section intitulée « Exemple pratique »Voici l’anatomie entière dans un fichier minimal. Les nombres sous xref sont des décalages
d’octets, et ils doivent être exacts — pointe un caractère après le début d’un objet et un
lecteur strict abandonne.
%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%%EOFLis-le comme le fait un analyseur. Dernière ligne : %%EOF. Au-dessus : startxref 186,
donc positionne-toi à l’octet 186, où commence xref. La table indique que l’objet 1 réside
à l’octet 9. Le /Root 1 0 R du trailer pointe là — le catalogue — et depuis le catalogue tu
parcours /Pages jusqu’à l’arbre des pages et trouves l’unique page. L’objet 0 est toujours
la tête de la liste des objets libres, avec la génération 65535, un fossile de la toute
première conception du format que tout lecteur s’attend encore à voir.
Idée fausse courante
Section intitulée « Idée fausse courante »Le piège est de lire un PDF comme une histoire — de haut en bas, dans l’ordre. Ce n’est pas
une histoire ; c’est un index muni d’un pointeur arrière. Les numéros d’objets n’ont pas à
être séquentiels dans le fichier, les objets peuvent apparaître dans n’importe quel ordre
physique, et un lecteur ne s’appuie jamais sur leur position. La seule carte qui fasse
autorité est la section de références croisées, et la seule façon de trouver cette carte est
le décalage startxref à la toute fin.
La conséquence surprend. Un PDF doté d’un corps impeccable mais d’un seul chiffre erroné dans
startxref est illisible — le lecteur ne peut pas trouver l’index. Un PDF dont les objets
sont dans un ordre brouillé mais qui a une section de références croisées correcte est
parfaitement valide. La position physique ne porte aucun sens. La position enregistrée en
porte tout.
Limites et périmètre
Section intitulée « Limites et périmètre »Cette page décrit la structure physique, pas le contenu des pages. La manière dont les marques
apparaissent sur une page — opérateurs de flux de contenu, affichage du texte, état graphique
— est un sujet distinct. Elle décrit aussi un fichier bien formé. Les PDF du monde réel
sont fréquemment un peu cassés et ne survivent que parce que des visualiseurs indulgents
reconstruisent la table de références croisées en cherchant les mots-clés obj. Ce sauvetage
est un comportement de visualiseur, et non quelque chose que le format garantit.
| Edition | Availability |
|---|---|
| Core | NextPDF est un générateur. Il enregistre chaque décalage depuis le tampon de sortie au moment où chaque objet est émis, si bien que les fichiers qu’il produit ont une section de références croisées qui correspond au corps par construction. |
| Pro | Analyser, reconstruire ou réparer une table de références croisées endommagée dans un fichier que NextPDF n’a pas écrit est hors périmètre dans toutes les éditions. |
| Enterprise | Pour inspecter la structure d’un fichier existant, utilise un analyseur ou un validateur dédié ; NextPDF garantit la correction de ce qu’il écrit, et non de ce qu’il lit. |
Mini-FAQ
Section intitulée « Mini-FAQ »Pourquoi un PDF a-t-il une ligne de marqueur binaire après l’en-tête ? Certains anciens outils de transfert dénaturaient un fichier qu’ils croyaient être du texte brut. Le commentaire à bit de poids fort fait paraître le fichier sans ambiguïté binaire, si bien qu’il survit au trajet sans modification.
Le flux xref n’est-il qu’une table en plus petit ? Pour l’essentiel, oui, avec un pouvoir supplémentaire. Au-delà d’être compressé, un flux xref peut décrire des objets stockés à l’intérieur de flux d’objets — des entrées que la table textuelle classique de 20 octets n’a aucun moyen d’exprimer.
Puis-je avoir à la fois une table et un flux dans un même fichier ? Une révision unique utilise l’un ou l’autre. Mais un fichier hybride peut associer une table classique pour les anciens lecteurs et un flux de références croisées pour les nouveaux, si bien que chaque type de lecteur trouve un index qu’il comprend.
Documents associés
Section intitulée « Documents associés »- Ce qu’est vraiment un PDF — les mêmes quatre parties vues comme un graphe d’objets plutôt que comme une disposition physique.
- Les mises à jour incrémentales et pourquoi elles comptent — comment la cinquième région ajoutée fait croître un fichier et protège les signatures.
- Flux et filtres — ce qu’il y a à l’intérieur des objets flux du corps et comment ils sont compressés.
- PDF 2.0 : ce qui a changé — pourquoi le flux de références croisées est la structure par défaut que NextPDF écrit.
Glossaire
Section intitulée « Glossaire »- En-tête — la première ligne,
%PDF-2.0, qui nomme la version ; généralement suivie d’un commentaire marqueur binaire. - Objet indirect — un objet numéroté dans le corps, écrit
N G obj … endobj, oùNest le numéro d’objet etGla génération. - Dictionnaire — une table
<< /Key value … >>associant des noms à des valeurs ; la forme d’objet la plus courante. - Flux — un dictionnaire plus un bloc d’octets entre
streametendstream, utilisé pour le contenu, les polices et les images. - Table de références croisées (xref) — l’index associant le numéro d’objet au décalage
d’octets ; une table textuelle de 20 octets par entrée classiquement, un flux
/Type /XRefen PDF 2.0. - Trailer — le dictionnaire qui nomme
/Rootet/Size, localisé via le décalagestartxrefà la fin du fichier. - Mise à jour incrémentale — des objets modifiés, une nouvelle section de références
croisées et un nouveau trailer ajoutés après
%%EOF, avec/Prevchaînant vers la section précédente.