A PDF image is a rectangle of samples: rows of pixels, each with one value a colour
component. It is either an image XObject, a stream that pages can draw by name and
share, or an inline image written inside a content stream. Either way it fills the
unit square of user space, so the content stream scales it with cm
first. In PDF 1.0 to 1.4 the data is compressed with the general filters or with the
image filters CCITT fax, JBIG2 (1.4) and DCT (JPEG).
Image XObjects
| Key | Since | Meaning |
|---|---|---|
Type | 1.0 | XObject, optional |
Subtype | 1.0 | Required: Image |
Width, Height | 1.0 | Required: the size in samples |
ColorSpace | 1.0 | Required except for image masks: the colour space of the samples; not Pattern |
BitsPerComponent | 1.0 | Required except for image masks: 1, 2, 4 or 8 (16 from PDF 1.5 only) |
Intent | 1.1 | The rendering intent for this image |
ImageMask | 1.0 | true: the image is a stencil mask; default false |
Mask | 1.3 | An explicit mask image, or a colour-key array |
Decode | 1.0 | How sample values map to colour components: see Decode arrays |
Interpolate | 1.0 | true asks for smoothing when the image is scaled up; default false |
Alternates | 1.3 | Other versions of the image, such as one for printing at high resolution |
SMask | 1.4 | A soft-mask image that gives the image an alpha channel |
Name | 1.0 | The name in the resources; required in PDF 1.0, optional later |
StructParent | 1.3 | Its place in the logical structure |
ID | 1.3 | Web Capture: the digital identifier of the image’s source |
OPI | 1.2 | Open Prepress Interface: a high-resolution version kept elsewhere |
Metadata | 1.4 | XMP metadata for the image |
10 0 obj
<< /Type /XObject /Subtype /Image /Width 640 /Height 480
/ColorSpace /DeviceRGB /BitsPerComponent 8
/Filter /DCTDecode /Length 48211 >>
stream
…JPEG data, FF D8 to FF D9…
endstream
endobj
The page draws it at 320 × 240 units, its top left corner at (72, 500):
q 320 0 0 240 72 260 cm /Im1 Do Q
Sample data
After the filters are undone, the data is the rows from top to bottom, each row
left to right. Each sample has one value a component in the colour space (one for
grey and Indexed, three for RGB, four for CMYK), each value
BitsPerComponent bits, packed with no gaps, high bit first. Each row
starts on a byte boundary, so a row is
ceil(Width × components × BitsPerComponent ÷ 8) bytes. A 3-pixel row of
1-bit grey is one byte, its last 5 bits unused.
Image space maps the first sample of the first row to the top left corner of the unit square, (0, 1) in user space: the image is stored top to bottom but user space runs bottom to top.
Decode arrays
Decode holds a pair of numbers for each component, [Dmin
Dmax], and a sample value from 0 to 2bits − 1 is mapped linearly to
the range between them. The defaults:
| Colour space | Default Decode |
|---|---|
| DeviceGray, CalGray, Separation | [0 1] |
| DeviceRGB, CalRGB | [0 1 0 1 0 1] |
| DeviceCMYK | [0 1 0 1 0 1 0 1] |
| Lab | [0 100 amin amax bmin bmax], from its Range |
| ICCBased | the stream’s Range, by default [0 1] for each component |
| Indexed | [0 N], where N = 2bits − 1, so the value is the index |
| DeviceN | [0 1] for each colourant |
| Image masks | [0 1] |
[1 0] inverts a grey image, and [1 0 1 0 1 0 1 0] is
often seen on CMYK JPEGs written inverted.
Masks
A mask decides which parts of an image are painted. PDF 1.0 to 1.4 have four kinds.
Stencil masks (1.0)
An image with /ImageMask true has 1-bit samples and no colour
space. It is not drawn in colours of its own: it paints the current fill colour
where samples are 0 and leaves the page alone where they are 1. Decode
[1 0] swaps the two. Type 3 bitmap glyphs and scanned line art use it.
Explicit masks (1.3)
Mask names a separate stencil-mask image, possibly at a different
resolution, that covers the same unit square. Where the mask is 1, the image is
not painted.
Colour-key masks (1.3)
Mask is an array of a minimum and maximum for each component, such
as [0 10 240 255 0 10] for an RGB image. Pixels whose every
component falls inside its range are not painted, which makes a colour such as
bright green transparent. The values are sample values, before
Decode.
Soft masks (1.4)
SMask names a greyscale image XObject, the alpha channel: 0 is fully
transparent, 1 fully opaque, values between partly. The soft-mask image has
ColorSpace /DeviceGray and may be at its own resolution. It can have
a Matte array, the colour that was pre-blended into the image’s
pixels, which the reader removes before blending. SMask overrides
Mask and the soft mask in the graphics state, for this image.
Inline images
A small image can be written in the content stream between BI,
ID and EI. Its keys and some values have short forms:
| Short | Full key |
|---|---|
BPC | BitsPerComponent |
CS | ColorSpace |
D | Decode |
DP | DecodeParms |
F | Filter |
H | Height |
IM | ImageMask |
I | Interpolate |
W | Width |
| Short | Value |
|---|---|
G, RGB, CMYK, I | DeviceGray, DeviceRGB, DeviceCMYK, Indexed |
AHx, A85, LZW, Fl, RL, CCF, DCT | the filters ASCIIHexDecode, ASCII85Decode, LZWDecode, FlateDecode, RunLengthDecode, CCITTFaxDecode, DCTDecode |
The colour space may also be a name in the ColorSpace resources, or,
for Indexed, an array with the lookup table written as a string. After
ID comes exactly one white-space byte, then the data, then
EI. Full key names are allowed too. A content stream can hold no
references to other objects, so anything that needs one, such as a soft mask or a
JBIG2Globals stream, needs an image XObject instead. Inline images
should be small: Adobe recommended 4 KB at most.
Image filters
| Filter | Since | For |
|---|---|---|
DCTDecode | 1.0 | JPEG photographs, 8 bits a component, grey, RGB or CMYK |
CCITTFaxDecode | 1.0 | Scanned black-and-white pages, 1 bit a sample |
JBIG2Decode | 1.4 | Scanned black-and-white pages, smaller than CCITT |
FlateDecode with a predictor | 1.2 | Lossless images of any kind; the same data as a PNG’s, without the PNG chunks |
LZWDecode, RunLengthDecode | 1.0 | Lossless images in older files |
A JPEG in a PDF can be saved out as a .jpg file as it is. A Flate
image needs its rows, colour space and bit depth written into a new image file.