Everything large in a PDF is a stream: page contents, images, fonts, embedded files and metadata. A stream’s dictionary says how long the data is and which filters it went through when it was written. A reader undoes the filters, in order, to get the data back. PDF 1.0 to 1.4 have eight filters: two that turn binary into ASCII text, three general compressions and three for images.
The stream dictionary
Every stream dictionary can hold these keys, whatever the stream is for:
| Key | Type | Since | Meaning |
|---|---|---|---|
Length | integer | 1.0 | Required. The number of bytes between the line end after stream and the line end before endstream, as stored, after filtering |
Filter | name or array | 1.0 | The filter, or filters in the order they are to be applied to decode |
DecodeParms | dictionary or array | 1.0 | Parameters for the filter, or an array with one entry a filter (null for one with none) |
F | file specification | 1.2 | The data is in this external file, not in the PDF; the bytes between stream and endstream are ignored |
FFilter | name or array | 1.2 | Filters for the external file |
FDecodeParms | dictionary or array | 1.2 | Parameters for those filters |
Streams of particular kinds add their own keys, such as Width for an
image or Length1 for an embedded font. With two filters,
<< /Length 534 /Filter [/ASCII85Decode /LZWDecode] >>
Length is what the file holds, not the decoded size. A reader that
finds endstream somewhere other than where Length says
has a damaged file; many readers then trust the keyword and use the bytes up to
it.
The filters
| Filter | Short | Since | Parameters | What it undoes |
|---|---|---|---|---|
ASCIIHexDecode | AHx | 1.0 | none | Binary written as hexadecimal digits |
ASCII85Decode | A85 | 1.0 | none | Binary written in base 85 |
LZWDecode | LZW | 1.0 | yes | Lempel–Ziv–Welch compression |
FlateDecode | Fl | 1.2 | yes | zlib / deflate compression |
RunLengthDecode | RL | 1.0 | none | Byte-oriented run-length encoding |
CCITTFaxDecode | CCF | 1.0 | yes | Group 3 and Group 4 fax compression of one-bit images |
JBIG2Decode | none | 1.4 | yes | JBIG2 compression of one-bit images |
DCTDecode | DCT | 1.0 | yes | JPEG baseline and progressive compression |
The short names are used only in inline
images inside content streams. The image filters produce pixels for an image
and are not used on other streams. The order in Filter is the order of
decoding: the first filter listed was the last applied when writing.
ASCIIHexDecode
Each byte is written as two hexadecimal digits, upper or lower case. White space is
ignored. > ends the data; if the number of digits before it is odd,
the last digit is taken as followed by 0. The data doubles in size. So
48 65 6C 6C 6F> decodes to Hello.
ASCII85Decode
Each group of four bytes is read as a 32-bit number, high byte first, and written
as five digits in base 85, each digit plus 33, which gives the characters
! to u. The data grows by a quarter.
- A group of four zero bytes is written
zinstead of!!!!!. - At the end, a last group of one to three bytes is padded with zeros to four,
encoded, and only the first n + 1 characters written for n bytes. The decoder
pads the characters with
uand keeps n bytes. ~>ends the data. White space is ignored; any other character is an error.
The four bytes Man (4D 61 6E 20) are the number
1,298,230,816, which in base 85 is the digits 24, 73, 80, 78, 61: the characters
9jqo^.
LZWDecode
The adaptive Lempel–Ziv–Welch method used by TIFF. Codes are 9 to 12 bits long, high bit first. A table of strings starts with the 256 single bytes; code 256 clears the table and returns to 9-bit codes, and 257 ends the data. Each new code adds the previous string plus the first byte of the next to the table, from code 258.
| Parameter | Default | Meaning |
|---|---|---|
EarlyChange | 1 | 1: codes grow to 10, 11 and 12 bits one code early, when the next table entry would be 511, 1,023 and 2,047, as TIFF writers do. 0: when it would be 512, 1,024 and 2,048 |
Predictor, Colors, BitsPerComponent, Columns | see below | A predictor applied before compression |
Before PDF 1.2 LZW was the only general compression, so files from Acrobat 1 and 2 use it for content streams. Flate, added in PDF 1.2, usually compresses better and was not held back by the LZW patents of the time.
FlateDecode
From PDF 1.2: the data is a zlib stream (RFC 1950) holding deflate data (RFC 1951).
It starts with a two-byte header, usually 78 9C or 78 DA,
and ends with an Adler-32 checksum. It is the usual compression for content streams,
fonts and images that are not JPEG. Some writers leave off the checksum or add
bytes after it; readers usually accept what they could inflate.
| Parameter | Default | Meaning |
|---|---|---|
Predictor | 1 | The predictor: 1 none, 2 TIFF, 10–15 PNG |
Colors | 1 | Components a sample, for the predictor |
BitsPerComponent | 8 | Bits a component: 1, 2, 4, 8 or 16 |
Columns | 1 | Samples a row |
RunLengthDecode
The data is a series of runs, each starting with a length byte:
| Length byte | Meaning |
|---|---|
| 0 to 127 | Copy the next length + 1 bytes as they are (1 to 128 bytes) |
| 129 to 255 | Repeat the next byte 257 − length times (2 to 128 times) |
| 128 | End of data |
02 41 42 43 FE 2A 80 decodes to ABC***: three bytes
copied, then 2A repeated 257 − 254 = 3 times.
CCITTFaxDecode
One-bit images compressed as fax machines do, by ITU-T recommendations T.4 (Group 3) and T.6 (Group 4). The data has no header, so the parameters say how it was written:
| Parameter | Default | Meaning |
|---|---|---|
K | 0 | Below 0: pure two-dimensional, Group 4. 0: pure one-dimensional, Group 3 (Modified Huffman). Above 0: mixed Group 3, where at most K − 1 rows in a row are two-dimensional |
EndOfLine | false | Whether each row starts with an end-of-line code (000000000001) |
EncodedByteAlign | false | Whether each encoded row is padded with 0 bits so that it starts on a byte boundary |
Columns | 1728 | The width in pixels |
Rows | 0 | The height; 0 means not given, so the data or the image’s Height decides |
EndOfBlock | true | Whether the data ends with an end-of-block code (six end-of-line codes for Group 3, two for Group 4) |
BlackIs1 | false | false: 0 bits are black, as in fax; true: 1 bits are black |
DamagedRowsBeforeError | 0 | How many damaged rows to accept before reporting an error |
The output is rows of packed bits, each row padded to a whole byte.
JBIG2Decode
From PDF 1.4: one-bit images compressed by JBIG2 (ISO/IEC 11544 and ITU-T T.88), which can store the shapes of text characters once and place them many times. The stream holds the segments of one page in the embedded form of the standard, with no file header. Segments shared by several images, such as a symbol dictionary, can be in a separate stream:
| Parameter | Default | Meaning |
|---|---|---|
JBIG2Globals | none | A stream with the global segments, read before the image’s own |
1 bits are black, unlike CCITT’s default. The page segment’s size should match the
image’s Width and Height.
DCTDecode
JPEG data, as in a JPEG file, from the FF D8 start-of-image marker to
FF D9. Baseline and progressive JPEG with 1, 3 or 4 components are
allowed. The image dictionary’s Width, Height,
ColorSpace and BitsPerComponent (8) must match the JPEG.
| Parameter | Default | Meaning |
|---|---|---|
ColorTransform | 1 for 3 components, 0 otherwise | 0: no colour transform. 1: three components are YCbCr and are turned into RGB; four are YCCK and turned into CMYK. An Adobe APP14 marker in the data overrides this |
CMYK JPEGs written by Adobe programs often store the components inverted, which a
reader sees from the APP14 marker or from a Decode array of
[1 0 1 0 1 0 1 0] on the image.
Predictors
LZW and Flate compress images better if each sample is first replaced by its
difference from a neighbour. The Predictor parameter says which
method was used, and the decoder undoes it after decompressing:
| Predictor | Method |
|---|---|
| 1 | None (the default) |
| 2 | TIFF predictor 2: each component is stored as its difference from the same component of the sample to its left |
| 10 | PNG, None on every row |
| 11 | PNG, Sub on every row |
| 12 | PNG, Up on every row |
| 13 | PNG, Average on every row |
| 14 | PNG, Paeth on every row |
| 15 | PNG, chosen row by row |
The PNG predictors came with Flate in PDF 1.2. For any value from 10 to 15 the
data is the same: every row starts with a byte that names the PNG filter used on
that row, 0 None, 1 Sub, 2 Up, 3 Average, 4 Paeth, so the decoder follows that byte
whatever the value. A row has Colors × BitsPerComponent × Columns bits,
rounded up to whole bytes, plus the filter byte. Each predicted byte is added,
modulo 256, to:
- Sub: the byte one sample to the left (one byte for 8-bit grey, three for 8-bit RGB), or 0 at the start of the row;
- Up: the byte above it in the previous row, 0 on the first row;
- Average: half the sum of the left and above bytes, rounded down;
- Paeth: whichever of left, above and upper left is nearest to left + above − upper left.
An example with Up and Columns 3, after inflating: the rows
02 01 02 03 and 02 00 01 FF decode to 01 02 03
and 01 03 02, because the second row adds each byte to the one above
it, and 03 + FF is 02 modulo 256.
External streams
From PDF 1.2 a stream’s data can live in another file, named by F.
The data in the PDF itself is then ignored and is usually empty, and
FFilter and FDecodeParms describe the external file. It
was meant for large images and sounds kept beside a document. Few readers support
it, and a file sent on its own loses the data.