PDF XObject
A reusable graphics resource in a PDF — images, Form XObjects (sub-content-streams), and PostScript XObjects — stored once in the PDF and referenced by the Do operator wherever needed on any page.
An XObject (External Object) is a self-contained PDF resource that can be drawn on a page using a single `Do` operator. XObjects are defined once and referenced wherever needed — on any page, any number of times — without duplicating the underlying data.
There are three types of XObjects in the PDF specification: Image XObjects (raster images), Form XObjects (reusable sub-content-streams), and PostScript XObjects (deprecated legacy constructs). Image and Form XObjects are the types you encounter in every real PDF.
Understanding XObjects is essential for anyone working with PDF internals — they are the mechanism behind image embedding, watermarks, headers and footers that repeat across pages, and the efficient storage of any content that appears more than once in a document.
Image XObjects: how images are stored in PDFs
Every image in a PDF is stored as an Image XObject — a stream of pixel data with a dictionary specifying width, height, colour space, bits per component, and compression filter.
A typical Image XObject dictionary looks like: ``` << /Type /XObject /Subtype /Image /Width 800 /Height 600 /ColorSpace /DeviceRGB /BitsPerComponent 8 /Filter /DCTDecode % JPEG compression >> stream … JPEG bytes … endstream ```
The image is stored in the page's resource dictionary under `/XObject`, then drawn on the page content stream with the `Do` operator: ``` q % save graphics state 200 0 0 150 100 400 cm % transform: width=200, height=150, at (100, 400) /Im1 Do % draw image named Im1 Q % restore graphics state ```
**Image compression in PDFs:** - `/DCTDecode` — JPEG. Lossy. Best for photographs. - `/FlateDecode` — Deflate/zlib. Lossless. Best for graphics, diagrams, screenshots. - `/CCITTFaxDecode` — CCITT Fax Group 3/4. Used for black-and-white scanned documents. - `/JBIG2Decode` — JBIG2. Very efficient for bi-level (black/white) images like scanned text. - `/JPXDecode` — JPEG 2000. Supported in PDF 1.5+; better than JPEG for medical imaging.
Each image in a PDF is stored exactly once in the XObject resource dictionary, regardless of how many times it appears on how many pages. This is why a PDF with a repeated logo does not multiply in file size each time the logo appears.
Form XObjects: reusable content sub-streams
A Form XObject (named for "form" in the typesetting sense of a prepared plate — not an interactive form) is a complete, self-contained content stream stored as a PDF resource. It has its own resource dictionary, its own coordinate system (defined by a /Matrix), and a /BBox (bounding box) that describes its dimensions.
Form XObjects are used for any content that repeats across pages: - Page headers and footers - Watermarks ("DRAFT", "CONFIDENTIAL") - Company logos - Background page templates - Repeated graphical elements in reports
When the `Do` operator references a Form XObject, the PDF viewer evaluates the XObject's content stream at the current position, clipped to the /BBox, transformed by the /Matrix. This is equivalent to "stamping" the XObject content onto the page.
**Practical uses:** - A 100-page report with a page header only stores the header content once as a Form XObject; each page's content stream just contains `/Hdr Do` — a single operator. - A watermark is a Form XObject with semi-transparent text; the `gs` (graphics state) operator sets the opacity before `Do` draws it. - Background page templates in generated PDFs (invoices, certificates) use Form XObjects so the template is stored once regardless of how many document instances are generated.
Form XObjects are also the mechanism behind <a href="https://pdftheguide.com/glossary/pdf-signature-field" target="_blank" rel="noopener">PDF signature field</a> appearances — the visual rendering of a signature (logo, name, timestamp) is stored as a Form XObject in the signature field's /AP (Appearance) dictionary.
Soft masks and transparency: XObjects with alpha
Image XObjects can have an associated soft mask — a separate grayscale image that defines per-pixel opacity for the image. This allows images with smooth transparency gradients (like a logo with a drop shadow or a person cut out from a background) to be rendered correctly in PDF.
The soft mask is specified in the image dictionary's `/SMask` key, pointing to another Image XObject containing the alpha channel data: ``` << /Type /XObject /Subtype /Image /Width 200 /Height 200 /ColorSpace /DeviceRGB /BitsPerComponent 8 /Filter /FlateDecode /SMask 15 0 R % reference to alpha channel image >> ```
The soft mask image has `/ColorSpace /DeviceGray` and contains 8-bit opacity values (0 = fully transparent, 255 = fully opaque).
This mechanism is how tools like <a href="https://www.adobe.com/products/illustrator.html" target="_blank" rel="noopener">Adobe Illustrator</a>, <a href="https://www.figma.com/" target="_blank" rel="noopener">Figma</a>, and <a href="https://www.canva.com/" target="_blank" rel="noopener">Canva</a> embed PNG images with alpha transparency into PDF exports. PNG's alpha channel is extracted and stored as the SMask; the RGB channels become the main image. The result is identical to PNG's transparency but in PDF's own format.
Note: <a href="https://pdftheguide.com/glossary/pdf-a" target="_blank" rel="noopener">PDF/A-1</a> prohibits soft masks because they require the transparency model. PDF/A-2 and PDF/A-3 permit them.
XObjects and PDF file size
XObjects directly affect PDF file size through their role in resource sharing. When PDF generating software handles XObjects correctly, repeated content is stored only once. When it does not, each instance stores the content independently, causing file size bloat.
**Common file size issues related to XObjects:**
1. **Duplicate image XObjects** — Some PDF generators create a new Image XObject for each occurrence of the same image rather than referencing a shared one. A 100-page report with the same logo on every page might store the logo 100 times. Use a PDF optimisation tool (<a href="https://qpdf.sourceforge.io/" target="_blank" rel="noopener">QPDF</a> with `--object-streams=generate` or Acrobat Pro's PDF Optimizer) to detect and deduplicate shared resources.
2. **Unoptimised image compression** — Images in XObjects use whatever compression was applied when the PDF was created. An Image XObject using uncompressed `/FlateDecode` for a photograph is much larger than the same photo with `/DCTDecode` (JPEG). PDF compression tools resample and recompress images in XObjects.
3. **Embedded thumbnail XObjects** — Many PDFs include thumbnail image XObjects for each page (stored in the page dictionary's `/Thumb` entry). These add file size without benefit for modern viewers which generate thumbnails on-the-fly. Removing them with QPDF or Acrobat Pro's Reduced File Size function can save significant space.
For a detailed analysis of a PDF's XObject resources, use a PDF inspection tool like <a href="https://github.com/itext/rups" target="_blank" rel="noopener">RUPS</a> or the Python command `pikepdf.open("file.pdf"); list(pdf.pages[0].Resources.XObject.keys())` to see what XObjects each page references.
Frequently asked questions
What is a PDF XObject?
An XObject is a reusable PDF resource that can be drawn on any page using the Do operator. Image XObjects store raster images (photos, diagrams, logos). Form XObjects store reusable sub-content-streams (headers, footers, watermarks, backgrounds). Both types are stored once in the PDF and referenced wherever needed, allowing the same content to appear on multiple pages without duplicating the data.
Why does my PDF have the same image stored multiple times?
Some PDF generators — particularly those that process pages independently without a shared resource pool — create a new Image XObject for each page, even when the same image appears on every page. To detect this, open the PDF in a tool like RUPS and check whether /XObject resources with the same image data are duplicated across pages. Fix it by running the PDF through QPDF's optimiser or Acrobat Pro's PDF Optimizer, which merge identical objects.
Can I extract images from a PDF XObject?
Yes — Image XObjects are essentially the raw image data (JPEG, PNG, JBIG2, etc.) wrapped in a PDF stream. Tools like pdfimages (Poppler) extract all Image XObjects from a PDF: `pdfimages -all input.pdf output-prefix`. Python's PyMuPDF library provides `page.get_images()` to list images and `doc.extract_image(xref)` to extract them. The extracted images are in their original compression format (JPEG, PNG, etc.).
What is the difference between an Image XObject and an inline image?
Both store raster image data in a PDF, but differently. An Image XObject is stored in the page's resource dictionary and referenced by name — it can be shared across pages and referenced multiple times. An inline image is embedded directly in the page content stream using BI/ID/EI operators — it cannot be shared and should only be used for very small images (under 4 KB is the guideline). For anything larger, Image XObjects are always preferred for their sharing and compression benefits.