Learning Foundations

File anatomy

1.4 §3.41.7 §7.5

Anatomy of a real, minimal PDF

This is a complete PDF 1.4 file, 591 bytes, which passes qpdf --check. Pick a part of the file to see what it does. The xref offsets are exact.

Download hello.pdf
HeaderBody 1 0 obj (Catalog)2 0 obj (Pages)3 0 obj (Page)4 0 obj (Content)5 0 obj (Font)Cross-reference tableTrailer
Headerbyte 0

How a reader opens a file

Readers parse PDFs backwards, starting at the end:

Scan the last ~1 KB for startxref; the number after it is the byte offset of the last cross-reference section.Load the offset table and the trailer. If the trailer has /Prev, follow it to the previous xref section (incremental updates) and merge, newest entries winning.The trailer's /Root is the document catalog. From there: /Pages → page tree → leaf /Page objects.Each object is parsed only when it is needed, by seeking to its offset. This is why PDF is random-access.Gather the page's (possibly inherited) /Resources, decode /Contents, and run the operators.

Incremental updates

Edits can be appended instead of rewriting the file: new or changed objects, a new xref section listing only them, and a new trailer whose /Prev points to the old xref. The original bytes are untouched, which is what lets a document carry several digital signatures, each covering the file as it was when signed.

…original file…
%%EOF
3 0 obj                     % changed page
<< … /Annots [6 0 R] >>
endobj
6 0 obj                     % new annotation
<< /Type /Annot /Subtype /Text … >>
endobj
xref
0 1
0000000000 65535 f
3 1
0000000431 00000 n
6 1
0000000560 00000 n
trailer
<< /Size 7 /Root 1 0 R /Prev 338 >>
startxref
640
%%EOF

Offsets in this update snippet are illustrative. Worked example: 1.4 App. G.6, 1.7 Annex H.7

Linearization ("Fast Web View")

A linearized file reorders objects so that the first page, and a hint table, come first. A viewer can show page 1 while the rest downloads and fetch other pages with HTTP range requests. You can spot one by a /Linearized dictionary in the first object. It is fiddly to write correctly, and an incremental update breaks it. (1.4 App. F, 1.7 Annex F)

Q1. What does each in-use entry of a classic cross-reference table store?
The object's byte offset in the fileThe object's length in bytesA hash of the objectThe page number the object belongs to
Check
Q2. Where does a reader start when it opens a PDF?
At the %PDF- headerAt the end of the file, looking for startxrefAt the document catalogAt the first page object
Check
Q3. How does an incremental update change a file?
It rewrites the changed objects in placeIt replaces the trailer and nothing elseIt appends the changed objects, a new xref section and a trailer whose /Prev points to the old xrefIt rewrites the whole file with the changes merged in
Check
Reset3 questions

Section references such as 1.4 §3.4 1.7 §7.5 are to the Adobe PDF Reference, third edition (PDF 1.4) and ISO 32000-1:2008 (PDF 1.7). Where to get them: PDF specifications.