Come i PDF memorizzano testo e immagini (sotto il cofano)
Un PDF è un file di testo con blob binari dentro. La struttura è sorprendentemente leggibile: un'intestazione, una lista di oggetti numerati, una tabella di riferimenti incrociati e un trailer. Questa pagina percorre questa struttura e mostra dove vivono realmente il testo, i font e le immagini. Scritto per sviluppatori e chiunque voglia capire cosa fa uno strumento PDF quando legge o scrive un file.
Vista d'insieme
Le quattro parti di un PDF
Ogni file PDF ha la stessa disposizione in quattro parti:
- Intestazione — una riga, p. es.
%PDF-1.7, che dichiara la versione. - Corpo — una sequenza di oggetti indiretti numerati. È qui che tutto vive: pagine, font, immagini, metadati.
- Tabella dei riferimenti incrociati (xref) — offset di byte di ogni oggetto, così un lettore può trovarli senza scansionare tutto il file.
- Trailer — punta all'oggetto radice (il catalogo del documento), la posizione del xref e informazioni di cifratura opzionali. Il lettore legge il trailer per primo, poi salta alla radice.
La concezione trailer-prima è perché un PDF può essere letto in tempo costante senza caricare tutto il file — importante per documenti voluminosi e lettori in flusso.
Corpo
Oggetti indiretti
Ogni oggetto nel corpo è numerato e assomiglia a questo:
3 0 obj
<< /Type /Page /MediaBox [0 0 612 792] /Contents 4 0 R /Resources << /Font << /F1 5 0 R >> >> >>
endobjIl 3 0 obj dice «questo è l'oggetto 3, generazione 0». Il corpo dentro << ... >>è un dizionario — una lista di coppie chiave/valore. I valori possono essere numeri, stringhe, nomi (prefissati da /), array, altri dizionari o riferimenti come 4 0 R («va a cercare l'oggetto 4»). È così che una pagina punta al suo flusso di contenuto e ai suoi font senza incorporarli.
Il numero di generazione è generalmente 0. Si incrementa quando un aggiornamento incrementale rimuove e riscrive un oggetto — una funzionalità che permette di modificare PDF aggiungendo cambiamenti alla fine del file senza riscrivere tutto. La maggior parte dei writer moderni riscrive tutto il file, quindi le generazioni restano a 0.
Contenuto
Come il testo è memorizzato
Il contenuto di una pagina vive in un flusso di contenuto — un oggetto il cui valore è un flusso di byte (spesso compresso con Flate) contenente operatori di disegno PDF. Il testo viene disegnato con operatori comeBT (begin text), Tf (set font e size), Td (move position), Tj(show text) e ET (end text). Un semplice «Hello» assomiglia all'incirca a:
BT
/F1 24 Tf
100 700 Td
(Hello) Tj
ETLa stringa (Hello) usa la codifica del font. Per testo latino semplice, è spesso WinAnsiEncoding o la codifica integrata del font. Per testo Unicode, la stringa è una stringa di byte codificata a 16-bit e il font ha una mappatura /ToUnicode che permette ai lettori di recuperare i code point reali per copiare-incollare e cercare. Se un PDF ha un copia-incolla corrotto ma testo visibile, la mappatura /ToUnicode è mancante o errata — un bug di esportazione comune.
Il testo non è memorizzato come HTML o paragrafi. Non c'è un oggetto semantico «paragrafo». Righe, interruzioni di riga e posizionamento sono tutti comandi di disegno espliciti. Ecco perché rifare il reflow di un PDF a una larghezza di pagina diversa è difficile: il lettore dovrebbe fare ingegneria inversa del layout a partire dai comandi di disegno.
Font
Incorporamento dei font
Un oggetto font in PDF ha due parti: un dizionario font che nomina il font e punta ai suoi dati, e ilprogramma font stesso (Type 1, TrueType o OpenType) incorporato come flusso. La specifica PDF richiede che i font siano incorporati così il documento renderizza identicamente ovunque — ma non lo impone, ecco perché alcuni PDF sostituiscono font su macchine che non li hanno.
Il subsetting incorpora solo i glifi effettivamente usati nel documento. Un font di 250 KB usato per un solo titolo diventa un sottoinsieme di 8 KB. La maggior parte degli esportatori moderni fa subsetting per default. Gli esportatori vecchi o alcuni percorsi «Print to PDF» incorporano a volte il font completo, che è una causa comune di file gonfiati. Vedi la nostra guida alla dimensione del file per il dettaglio completo.
Immagini
Come le immagini sono memorizzate
Le immagini sono memorizzate come XObject(oggetti esterni) — flussi di dati pixel raw o compressi con un dizionario che descrive larghezza, altezza, spazio colore, bit per componente e filtro. Il flusso di contenuto della pagina poi disegna l'immagine con l'operatoreDo.
PDF supporta diversi filtri di immagine (compressione):
- DCTDecode — JPEG. Con perdita, buono per le foto. La fonte più comune di dimensione nei PDF ricchi di immagini.
- FlateDecode — zlib/deflate. Senza perdita, buono per disegni a tratto e immagini con pochi colori.
- JPXDecode — JPEG2000. Compressione migliore di JPEG ad alta qualità, ma più lento e meno universalmente supportato.
- JBIG2Decode — per testo scansionato bitonale (1-bit). Può ridurre drasticamente le pagine scansionate.
- CCITTFaxDecode — compressione fax classica per immagini bitonali.
Un PDF ricco di immagini è soprattutto una sequenza di flussi di immagini compresse. Ricodificare questi flussi con una qualità JPEG più aggressiva è il singolo levatore più importante di dimensione per documenti scansionati.
Indice
Tabella xref e trailer
La tabella xref elenca l'offset di byte di ogni oggetto indiretto. Un lettore apre il file, legge il trailer (che è a un offset noto dalla fine del file), trova il xref e lo usa per saltare direttamente a qualsiasi oggetto senza analizzare tutto il file. È questo che rende PDF ad accesso diretto.
PDF 1.5 ha aggiunto i flussi di riferimenti incrociati, che comprimono la tabella xref stessa. Combinato con i flussi di oggetti (molti piccoli oggetti impacchettati in un flusso compresso), questa è la compressione strutturale che rende i PDF moderni più piccoli dei loro equivalenti 1.4. Vedi il nostroexplainer sulla compressione per cosa fa in pratica.
Il trailer punta anche a/Root (il catalogo del documento, che elenca l'albero delle pagine), il dizionario /Info(Title, Author, CreationDate — i metadati) e opzionalmente il dizionario /Encrypt se il file è cifrato.
Compressione
Flussi e filtri
Ogni oggetto il cui valore è dato binario (un flusso di contenuto, un'immagine, un font incorporato) è unflusso: un dizionario seguito dastream, byte raw e endstream. L'entry /Filter del dizionario indica al lettore come decodificare i byte — FlateDecodeper zlib, DCTDecode per JPEG, ecc. Più filtri possono essere concatenati, p. es. un'immagine che viene decodificata poi sotto-campionata.
Ecco perché «comprimere un PDF» non è un'operazione. Ogni flusso è compresso indipendentemente con il proprio filtro. Uno strumento di compressione che risalva con flussi di oggetti riduce l'overhead strutturale; ricodificare le immagini con una qualità JPEG più aggressiva riduce i flussi di immagini. Sono levatori indipendenti.
In pratica
Perché questo conta per gli strumenti PDF
Quando uno strumento come IXPDF fonde, divide o ruota un PDF, analizza il xref, percorre l'albero delle pagine, copia o riarrangia gli oggetti di pagina e riscrive il xref e il trailer. I flussi di contenuto (testo e immagini) vengono copiati byte per byte — nessuna ricodifica, nessuna perdita di qualità. Ecco perché le operazioni strutturali sono rapide e senza perdita: riarrangiano i riferimenti degli oggetti, non re-renderizzano la pagina.
La compressione è l'eccezione: re-serializza la struttura con flussi di oggetti. Anche allora, i flussi di immagini e font vengono copiati tal quali salvo se l'utente richiede esplicitamente di ricodificarli.
Tutto questo avviene nel tuo browser via un Web Worker — il file viene analizzato, modificato e re-serializzato localmente. Il tuo PDF non lascia mai il tuo dispositivo.
Da leggere dopo