To understand PDF compression, one must look past the visual representation and analyze the underlying ISO 32000 specification. In this technical deep dive, we explore the byte-level architecture of PDF documents and the algorithms that compress them.
The PDF Object Model
A PDF file consists of eight basic object types: Booleans, Numbers, Strings, Names (e.g. /Type), Arrays, Dictionaries, Streams, and the Null object. Indirect objects are indexed with object and generation numbers (e.g. 12 0 obj ... endobj).
Stream Objects & Compression Filters
Heavy content (text layout operators, embedded fonts, bitmap graphics) is stored in Stream Objects. Every stream object has a dictionary that specifies one or more filters applied to its binary payload:
15 0 obj
<<
/Type /XObject
/Subtype /Image
/Width 1920
/Height 1080
/ColorSpace /DeviceRGB
/BitsPerComponent 8
/Filter /FlateDecode
/Length 412890
>>
stream
... [Binary Compressed Data] ...
endstream
endobj
Object Streams & Cross-Reference Streams (PDF 1.5+)
Prior to PDF 1.5, only stream payloads could be compressed; object dictionaries, headers, and XRef tables remained uncompressed ASCII. PDF 1.5 introduced Object Streams (/ObjStm) and XRef Streams, allowing non-stream objects and cross-reference tables themselves to be compressed inside FlateDecode streams, eliminating up to 40% of overhead in vector documents.
Frequently Asked Questions
Can PDF streams have multiple compression filters chained together?
Yes! The PDF standard allows filter arrays like [/ASCII85Decode /FlateDecode], though modern compressors typically use single FlateDecode or DCTDecode streams for efficiency.