Placez un rapport numérisé de 80 Mo derrière un lien, ouvrez-le dans un navigateur et observez ce qui se produit : le visualiseur reste sur un volet vide jusqu'à ce qu'une grande partie des octets soit arrivée, puis il dessine la première page d'un coup. Sautez à la page 40, et s'il s'agit d'un fichier mal structuré, tout le téléchargement peut recommencer depuis le début. Ce qui est frustrant, c'est que le lecteur ne voulait que la première page. La linéarisation (Linearization) est conçue pour répondre à cette question structurelle. Elle réorganise le PDF de sorte que le lecteur puisse restituer la page initiale à partir d'un petit préfixe du fichier, puis récupérer le reste à la demande, c'est pourquoi Adobe promeut cette fonctionnalité sous le nom de "Fast Web View" (Affichage Web rapide)
Il ne s'agit en aucun cas d'un format de fichier différent. Un PDF linéarisé est un PDF ordinaire, qu'un lecteur conforme ouvre sans traitement spécial. Son astuce réside entièrement dans la manière dont les octets sont ordonnés et dans les deux structures supplémentaires portées par le fichier. L'ISO 32000-1 normalise toute la disposition dans l'annexe F, et une fois que l'on voit sa mise en page, ce comportement ne ressemble plus à de la magie, mais à un compromis délibéré sur l'ordre du fichier pour réduire la latence du premier affichage
Le PDF linéarisé (optimisé pour le Web) ajoute une troisième variante : le fichier est physiquement réorganisé afin que le contenu de la première page apparaisse près du début du fichier pour un affichage rapide sur des connexions lentes. L'arbre des pages reste d'autorité pour l'ordre logique, mais la table des références croisées pointe vers les décalages réorganisés. Un analyseur s'appuyant sur l'emplacement des fichiers plutôt que sur la table xref interprétera de travers la première page même d'un fichier linéarisé
Un PDF ordinaire peut disperser ses objets dans presque n'importe quel ordre. La table de référence croisée (cross-reference table) située à la fin du fichier rend cela possible : le lecteur se positionne à la fin du fichier, lit le pointeur startxref, charge la table xref, puis localise chaque objet à partir de son décalage. Cette conception est extrêmement efficace pour les fichiers locaux, car le positionnement à la fin du fichier ne coûte rien ; en revanche, elle est très inefficace pour les fichiers transmis en continu sur le réseau, car la fin du fichier est la dernière partie à arriver. Pour effectuer le rendu de la première page, le lecteur traditionnel a besoin de l'objet de page, de son flux de contenu, des polices référencées et de toutes les images qu'il dessine, et dans un fichier non ordonné, ces éléments peuvent se trouver n'importe où, y compris dans le dernier mégaoctet
Ce que réorganise concrètement la linéarisation
Premier ensemble d'objets de page et dictionnaire de paramètres de linéarisation
Dans un fichier linéarisé, le tout premier objet suivant immédiatement l'en-tête %PDF est le dictionnaire de paramètres de linéarisation. Les lecteurs de flux le recherchent pour déterminer si l'optimisation existe et comment l'utiliser. Ce dictionnaire enregistre la longueur totale du fichier, le décalage d'octets du début de la zone de référence croisée principale, le numéro d'objet de la première page, ainsi que l'emplacement et la longueur du flux d'indices suivant. Grâce à ces chiffres, le lecteur peut savoir, à partir des premiers kilo-octets du fichier, quelle quantité de données doit être récupérée pour afficher la première page, et où chercher l'index pour naviguer vers d'autres emplacements
L'annexe F est très stricte sur la signification de "première page" ici. La zone de la première page doit contenir l'objet de page lui-même, son flux de contenu ainsi que les ressources référencées par ces flux, afin que cette page puisse se suffire à elle-même dès le téléchargement de cette partie initiale. Les ressources partagées (comme les polices utilisées sur chaque page, les logos répétés dans l'en-tête) font l'objet d'un traitement spécial : elles apparaissent assez tôt pour servir la première page, mais sont marquées comme partagées, de sorte que le lecteur ne les récupère pas à nouveau lors du rendu de la page 30 ultérieurement. Distinguer les objets privés de la page des objets partagés est le point sur lequel la plupart des "optimiseurs" locaux se trompent, ce qui explique pourquoi des fichiers se prétendant linéarisés peuvent encore subir des ralentissements
Flux d'indices : un index permettant des sauts de page moins coûteux
Afficher rapidement la première page ne représente que la moitié de la valeur. L'autre moitié consiste à pouvoir sauter à n'importe quelle page sans télécharger tout le contenu intermédiaire, ce que permettent précisément les flux d'indices (hint streams). Un fichier linéarisé comporte une table d'indices de décalage de page et une table d'indices d'objets partagés, stockées sous forme de flux référencés depuis le dictionnaire de paramètres. La table de décalage de page enregistre l'emplacement de début de l'objet de chaque page dans le fichier ainsi que sa longueur. La table d'objets partagés enregistre de même les informations sur les ressources utilisées sur plusieurs pages
Grâce à ces tables, un lecteur cherchant à obtenir la page 40 n'a pas besoin d'analyser le fichier de manière séquentielle. Il consulte la table des indices, apprend la plage d'octets occupée par la page 40, demande précisément cette plage au serveur, effectue le rendu de la page une fois ces octets reçus, et récupère par le même mécanisme toutes les ressources partagées qu'il ne détient pas encore. En pratique, le flux d'indices est une carte d'accès aléatoire superposée au document, ce qui explique pourquoi un fichier linéarisé de 500 pages bien construit reste réactif sous une connexion lente, alors qu'un fichier non optimisé de même taille ne le peut pas
Pourquoi la réutilisation d'un THotPDF terminé lève une erreur de chargement de document, fonctionnement du cycle de vie Create, BeginDoc, EndDoc, Free, et quand construire une nouvelle instance
La linéarisation suppose que la couche de transport est capable de fournir des tranches arbitraires du fichier ; il convient de vérifier cette hypothèse avant de blâmer le format pour de mauvaises performances. Le mécanisme est le service d'octets HTTP (byte-serving) : le lecteur émet des requêtes de plage (range requests), auxquelles le serveur répond par un code 206 Partial Content. Si le serveur ne diffuse pas Accept-Ranges: bytes, ou si les proxys ou CDN en amont regroupent les requêtes de plage en transferts complets, le lecteur ne pourra pas obtenir la page 40 de manière indépendante et devra télécharger l'intégralité du fichier. La structure interne du PDF est alors tout à fait correcte, mais totalement gaspillée
C'est la panne la plus fréquemment diagnostiquée à tort comme "la linéarisation ne fonctionne pas". Le fichier est correct, c'est le canal de transmission qui est défaillant. Avant de reconstruire le document, confirmez par une requête conditionnelle que l'hôte renvoie effectivement un contenu partiel (partial content) pour l'URL accédée par le lecteur. De nombreux hébergeurs statiques le font par défaut, contrairement à beaucoup de serveurs d'applications et de couches de cache mal configurés
Les mises à jour incrémentielles brisent discrètement la linéarisation
Cette méthode LoadFromCanvasDc capture le contenu rendu sur le DC virtuel sous forme de page PDF, préservant ainsi la mise en page exacte du document d'origine
L'effet secondaire est que les données de référence croisée les plus récentes du fichier se trouvent désormais à la fin, après le bloc de la première page soigneusement disposé, tandis que le dictionnaire de paramètres de linéarisation au début du fichier décrit une mise en page qui ne correspond plus au fichier. Les lecteurs conformes détectent cette incohérence et traitent le document comme un PDF ordinaire non linéarisé. L'affichage web rapide (Fast Web View) a disparu, même si la structure de linéarisation d'origine demeure dans la première moitié du fichier. Si vous ajoutez plusieurs mises à jour, chacune empilant une autre révision à la fin, l'écart entre l'ancien index frontal et l'état réel devient encore plus grand
Si votre flux de travail nécessite à la fois l'édition et un affichage web rapide, les règles découlent directement de la structure : effectuez des modifications incrémentielles lors des changements de documents, puis effectuez une nouvelle linéarisation à la fin. Une réécriture complète est l'opération qui restaure la mise en page. Avec HotPDF, cela signifie que les modifications en cours passent par BeginIncrementalUpdate et SaveIncrementalUpdate pour ajouter les différences, tandis que l'étape finale utilise LoadFromFile suivi de SaveLoadedDocument pour charger l'intégralité du document et le sérialiser à neuf, éliminant ainsi les révisions accumulées et produisant une mise en page propre. Les flux d'objets (object streams) partagent le même compromis : utiliser UseObjectStreams en combinaison avec UseXRefStream permet de compresser les références croisées et d'empaqueter les objets de manière compacte, aidant à réduire la taille du fichier, mais comme tout choix structurel, cela doit être appliqué lors de la réécriture finale et non ajouté aux révisions incrémentielles
// 正在进行的编辑:追加差异(delta),保持以前的修订完好无损。
// 这样留下的是一个非线性化(NOT linearized)的文件。
Pdf.BeginIncrementalUpdate('report.pdf');
Pdf.AddPage;
Pdf.CurrentPage.TextOut(72, 760, 0, 'Addendum');
Pdf.SaveIncrementalUpdate('report.pdf');
// 收尾步骤:完全重新序列化可产生一个干净的布局,
// 丢弃堆叠的修订版。在输出文件上重新运行您的线性化器。
Pdf.LoadFromFile('report.pdf');
Pdf.SaveLoadedDocument('report-final.pdf');
HotPDF ne fournit pas d'appel de "linéarisation" en un clic, la pratique consiste donc à générer d'abord un fichier propre et entièrement réécrit, puis à exécuter un optimiseur spécialisé sur celui-ci. Les outils en ligne de commande gèrent directement la réorganisation. qpdf utilise un seul indicateur pour réécrire le fichier sous forme linéarisée :
qpdf --linearize report-final.pdf report-web.pdf
Comment déterminer si un fichier est linéarisé
Des q et Q non équilibrés sont un moyen courant de corrompre les flux de contenu construits manuellement ou assemblés. Un q isolé sans Q correspondant laisse des résidus en profondeur dans la pile à la fin de la page ; un Q supplémentaire provoque un sous-dépassement de la pile. Dans les deux cas, le visualiseur peut conserver l'ancien détourage ou la transformation précédente, et le contenu disparaît ou atterrit au mauvais endroit. Lorsque des graphiques disparaissent sans raison (que les tracés peuvent expliquer), veuillez d'abord vérifier la pile d'états
Pour les vérifications scriptées, qpdf signale à la fois la présence de la structure et son intégrité. C'est important car un fichier portant un dictionnaire linéarisé peut ne plus refléter sa mise en page, ce qui est précisément l'état laissé après une mise à jour incrémentielle :
# 报告 "File is linearized" 并针对布局验证提示表
qpdf --check report-web.pdf
# 详细转储线性化参数和提示数据
qpdf --show-linearization report-web.pdf
L'étape de validation est la plus précieuse. Un scan vérifiant uniquement la présence du dictionnaire laissera facilement passer les fichiers dont l'index pointe vers des décalages erronés ; tandis qu'une vérification confrontant la table des indices aux positions réelles des objets vous indiquera si l'optimisation résistera aux requêtes de plages (range requests) d'un lecteur réel
La linéarisation mérite toujours d'être appliquée à tout grand document proposé sur le Web, en particulier pour les lecteurs mobiles disposant de connexions réseau instables, et elle ne coûte que quelques centièmes du volume du fichier pour cet index frontal. Deux points doivent être clairs : la structure interne du PDF et le service d'octets externe doivent être corrects, et toute modification ultérieure annulera l'optimisation jusqu'à ce que vous réécriviez le fichier. Considérez la relinéarisation comme la dernière étape du pipeline, après que toutes les modifications ont été finalisées. Les comportements de références croisées, de flux d'objets et de mises à jour incrémentielles décrits ici font partie du modèle structurel implémenté par le composant HotPDF pour Delphi et C++Builder ; pour un contexte plus large sur l'agencement des fichiers, consultez la Structure des fichiers PDF, et pour les flux de modifications incrémentielles et de fichiers volumineux, consultez la Gestion des grands PDF avec Delphi