Tehnični članak

Linearizacija PDF in Fast Web View: kako deluje

Če postavite 80 MB skenirano poročilo za spletno povezavo in ga odprete v brskalniku, se zgodi naslednje: pregledovalnik prikazuje prazno okno, dokler se ne prenese velik del bajtov, nato pa naenkrat izriše prvo stran. Če skočite na 40. stran, se lahko pri slabo zgrajeni datoteki prenos začne povsem znova. Najbolj frustrirajoče je, da je bralnik potreboval le prvo stran. Linearizacija je strukturni odgovor na to težavo. PDF preuredi tako, da lahko pregledovalnik izriše prvo stran iz majhnega začetnega dela datoteke, preostanek pa prenaša po potrebi. Adobe to funkcijo trži pod imenom "Fast Web View" (hitri spletni ogled)

Pri tem ne gre za drugačen format datoteke. Lineariziran PDF je običajen PDF, ki ga skladen bralnik odpre brez posebne obravnave. Trik je izključno v vrstnem redu bajtov in v dveh dodatnih strukturah, ki ju datoteka vsebuje. Standard ISO 32000-1 opredeljuje to strukturo v Prilogi F. Ko enkrat spoznate to postavitev, celotno obnašanje ni več čarovnija, temveč premišljena zamenjava vrstnega reda datoteke za hitrejši začetni izris strani

Kaj linearizacija dejansko preuredi

Običajen PDF lahko svoje objekte razprši v skoraj poljubnem vrstnem redu. Tabela navzkrižnih sklicev na koncu datoteke omogoča, da to deluje: bralnik skoči na konec, prebere kazalec startxref, naloži tabelo xref in iz nje določi položaj vsakega objekta prek njegovega odmika. Ta zasnova je odlična za lokalne datoteke, kjer skok na konec ne stane nič, in zelo slaba za pretakanje datotek prek omrežja, saj je konec datoteke natanko tisti del, ki prispe zadnji. Za izris prve strani običajen bralnik potrebuje objekt strani, njen tok vsebine, pisave, na katere se sklicuje, in slike, ki jih izrisuje, v neurejeni datoteki pa se ti deli lahko nahajajo kjer koli, tudi v zadnjem megabajtu

Linearizacija to odpravi s preureditvijo vrstnega reda. Objekti, potrebni za prikaz prve strani, so združeni v neprekinjen blok blizu začetka datoteke, takoj za kratkim delom glave, tako da v toku bajtov prispejo zelo zgodaj. Vse ostalo, preostale strani in skupni viri, sledi v predvidljivem zaporedju. Druga, popolna tabela navzkrižnih sklicev se še vedno nahaja na koncu za bralnike, ki to optimizacijo prezrejo, vendar linearizirana datoteka na začetek postavi tudi tabelo navzkrižnih sklicev za prvo stran in parametre, ki jih pretočni bralnik potrebuje. Bralniku tako ni več treba doseči konca datoteke, preden lahko sploh kaj izriše

Nabor objektov prve strani in slovar parametrov linearizacije

Prvi objekt v linearizirani datoteki, takoj za glavo %PDF, je slovar parametrov linearizacije. To je tisto, kar pretočni bralnik išče, da ugotovi, ali je optimizacija prisotna in kako jo uporabiti. Slovar beleži dolžino celotne datoteke, bajtni odmik do glavnega dela navzkrižnih sklicev, številka objekta prve strani ter lokacija in dolžina toka namigov (hint stream), ki sledi. S temi številkami bralnik že iz prvih nekaj kilobajtov ve, koliko podatkov mora prenesti za prikaz prve strani in kje poiskati kazalo za skok na druge dele dokumenta

Priloga F (Annex F) strogo določa, kaj pomeni "prva stran". Odsek prve strani mora vsebovati sam objekt strani, njene tokove vsebine in vire, na katere se ti tokovi sklicujejo, tako da je stran samozadostna takoj, ko je ta začetni del prenesen. Skupni viri (pisava, ki se uporablja na vsaki strani, ali logotip v glavi) se obravnavajo posebej: pojavijo se dovolj zgodaj, da služijo prvi strani, vendar so označeni kot skupni, da jih bralnik ne prenaša znova, ko kasneje izrisuje npr. 30. stran. To razlikovanje med zasebnimi in skupnimi objekti strani je del, ki ga doma narejeni "optimizatorji" najpogosteje izvedejo napačno, kar ustvari datoteko, ki trdi, da je linearizirana, a se še vedno zatika

Tokovi namigov (Hint streams): kazalo za hitre skoke med stranmi

Hiter prikaz prve strani je le polovica vrednosti. Druga polovica je skok na poljubno stran brez prenašanja vseh vmesnih podatkov, kar omogočajo tokovi namigov. Linearizirana datoteka vsebuje tabelo namigov za odmike strani (page offset hint table) in tabelo namigov za skupne objekte (shared object hint table), ki sta shranjeni kot tok, na katerega kaže slovar parametrov. Tabela odmikov strani za vsako stran beleži, kje v datoteki se začnejo njeni objekti in kako dolgo potekajo. Tabela skupnih objektov počne enako za vire, ki se uporabljajo na več straneh

S pomočjo teh tabel bralnik, ki potrebuje 40. stran, ne pregleduje datoteke zaporedno. V tabeli namigov preveri bajtno območje, ki ga zaseda 40. stran, od strežnika zahteva natanko to območje in izriše stran takoj, ko ti bajti prispejo. Morebitne skupne vire, ki jih še nima, prenese prek enakega mehanizma. Tok namigov je dejansko zemljevid za naključni dostop do dokumenta in je razlog, da je dobro linearizirana datoteka s 500 stranmi odzivna tudi na počasi povezavi, medtem ko neoptimizirana datoteka enake velikosti ni

Praktični kontekst

Linearizacija predvideva, da lahko prenosna pot dostavi poljubne rezine datoteke. To predpostavko je priporočljivo preveriti, preden za slabe rezultate okrivite sam format. Mehanizem deluje prek streženja bajtov HTTP (HTTP byte-serving): bralnik pošlje zahteve za obseg (range requests), strežnik pa nanje odgovori z 206 Partial Content (delna vsebina). Če strežnik ne javlja glave Accept-Ranges: bytes ali pa proksi oziroma omrežje CDN pred njim združi zahteve za obseg v celotne prenose, bralnik ne more prenesti le 40. strani in mora prenesti celotno datoteko. Notranja struktura PDF-ja je v tem primeru sicer povsem pravilna, a povsem neuporabna

To je napaka, ki jo najpogosteje napačno označijo z "linearizacija ne deluje". Datoteka je v redu, prenosna pot pa ne. Preden ponovno gradite dokument, s pogojno zahtevo preverite, ali gostitelj dejansko vrača delno vsebino za ciljni naslov URL. Veliko strežnikov za statične vsebine to počne privzeto, medtem ko napačno nastavljeni aplikacijski strežniki in predpomnilniški sloji tega ne omogočajo

Postopne posodobitve tiho pokvarijo linearizacijo

Tukaj je omejitev, ki preseneča tiste, ki pravilno ustvarijo linearizirane datoteke, nato pa se sprašujejo, zakaj je optimizacija izginila. Linearizacija temelji na enotni, natančno urejeni postavitvi z indeksom na začetku. Postopna posodobitev (incremental update) to načrtno krši. Ko orodje doda podpis, izpolni polje obrazca ali doda opombo prek postopnega shranjevanja, datoteke ne zapiše znova. Spremenjene objekte, novo tabelo navzkrižnih sklicev in nov napovednik preprosto doda na konec, prvotne bajte pa pusti nedotaknjene. To dodajanje je bistvo postopnih posodobitev: je hitro in ohranja prejšnjo različico za revizijo ali potrditev podpisa

Stranski učinek tega je, da ima datoteka zdaj najnovejše podatke o navzkrižnih sklicih na samem koncu (za skrbno nameščenim blokom prve strani), slovar parametrov linearizacije na začetku pa opisuje postavitev, ki se ne ujema več z dejanskim stanjem datoteke. Skladen bralnik zazna to neskladje in obravnava dokument kot običajen, nelineariziran PDF. Funkcija Fast Web View je izgubljena, čeprav prvotna linearizirana struktura še vedno leži v prvi polovici datoteke. Če dodate več posodobitev, vsaka izmed njih naloži novo različico na konec, razkorak med zastarelim indeksom na začetku in dejanskim stanjem pa se poveča

Če vaš delovni proces zahteva tako urejanje kot Fast Web View, pravilo izhaja neposredno iz strukture: med urejanjem uporabljajte postopne posodobitve, na koncu pa datoteko enkrat ponovno linearizirajte. Celotno ponovno zapisovanje je tisto, kar obnovi postavitev. Pri HotPDF to pomeni, da vmesno urejanje uporabite z BeginIncrementalUpdate in SaveIncrementalUpdate, ki dodata spremembo, zaključni korak pa celoten dokument naloži in ga sveže zapiše z LoadFromFile ter SaveLoadedDocument. S tem se stare revizije odstranijo in nastane ena čista postavitev. Enaka odločitev velja za objektne tokove: UseObjectStreams skupaj z UseXRefStream zmanjša velikost navzkrižnih sklicev in tesneje zapakira objekte, vendar mora biti to vključeno pri končnem ponovnem zapisu, ne dodano naknadno na že pripeto revizijo

// 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 ne ponuja klica z enim ukazom za linearizacijo, zato je praktično ustvariti čisto, popolnoma ponovno zapisano datoteko in jo nato optimizirati s posebnim orodjem. Ukazno orodje qpdf to opravi z enim stikalom:

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

Kako ugotoviti, ali je datoteka linearizirana

Ne zaupajte imenu datoteke ali orodju, ki trdi, da jo je ustvarilo; raje preverite bajte. Najbolj neposredno preverjanje je na samem začetku datoteke: odprite jo in poiščite slovar parametrov linearizacije kot prvi objekt za glavo, ki vsebuje ključ /Linearized. Hitra pot za uporabnika pa je pogovorno okno z lastnostmi dokumenta v programu Acrobat, ki izpiše "Fast Web View: Yes" le takrat, ko je struktura dejansko prisotna in posodobljena

Za samodejno preverjanje orodje qpdf poroča o prisotnosti in celovitosti strukture. To je pomembno, saj lahko datoteka vsebuje slovar linearizacije, ki ne odraža več njene postavitve; natanko takšno stanje namreč pusti postopna posodobitev:

# 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

Korak validacije je tisti, ki je resnično koristen. Prehod, ki le potrdi obstoj slovarja, bo brez težav odobril datoteko, katere indeks kaže na napačne odmike; preverjanje, ki uskladi tabele namigov z dejanskimi položaji objektov, pa vam pove, ali bo optimizacija dejansko delovala ob zahtevah za obseg realnega bralnika

Linearizacija je še vedno priporočljiva za vsak večji dokument, ki se prenaša prek spleta, zlasti za mobilne bralnike na nestabilnih povezavah, stane pa vas le nekaj odstotkov velikosti datoteke za indeks na začetku. Pomembno je razumeti, da morata biti pravilno nastavljeni tako struktura znotraj PDF-ja kot streženje bajtov na strežniku ter da vsako naknadno urejanje izniči to optimizacijo, dokler datoteke ponovno ne zapišete. Ponovno linearizacijo obravnavajte kot zadnji korak v cevovodu, ko so vse ostale spremembe dokončne. Obnašanje navzkrižnih sklicev, tokov objektov in postopnih posodobitev, opisano tukaj, je del strukturnega modela, ki ga implementira knjižnica HotPDF Component za Delphi in C++Builder; za širše ozadje postavitve datotek si oglejte članek o zgradbi datotek PDF, za delo s postopnimi posodobitvami in velikimi datotekami v kodi pa članek o obdelavi velikih datotek PDF iz Delphija