PDF Image XObject

A PDF Image XObject is a stream object that stores a raster image for display on a PDF page. It carries the image dimensions, colour space, bits per component, and compression filter directly in its dictionary. The image is rendered on a page content stream using the Do operator, which paints the image into the current transformation matrix.

A PDF Image XObject is a stream object that stores a raster image for display on a PDF page. In the PDF object model, an XObject is any self-contained stream that can be referenced and placed multiple times in a document. The Image XObject subtype (<code>/Subtype /Image</code>) specifically stores pixel-based raster images — photographs, screenshots, scanned pages, and similar content — as opposed to <a href="https://pdftheguide.com/glossary/pdf-xobject" target="_blank" rel="noopener">Form XObjects</a> (which store reusable PDF content streams) or PostScript XObjects.

Image XObjects are the mechanism through which all raster images — whether embedded in the original document or added by <a href="https://pdftheguide.com/add-image-to-pdf" target="_blank" rel="noopener">an image editing tool</a> — exist within a PDF file. Understanding Image XObjects is essential for extracting images from PDFs, understanding file size contributors, managing <a href="https://pdftheguide.com/glossary/pdf-compression" target="_blank" rel="noopener">compression</a>, and troubleshooting display quality issues.

Image XObject stream dictionary

An Image XObject is a PDF stream with a specific set of required and optional entries in its stream dictionary:

<strong>Required entries:</strong>

<code>/Type /XObject</code> — Identifies the object type (sometimes omitted in practice but technically required).

<code>/Subtype /Image</code> — Specifies that this is an image XObject rather than a form or PostScript XObject. Required.

<code>/Width</code> — The width of the image in samples (pixels). Required.

<code>/Height</code> — The height of the image in samples (pixels). Required.

<code>/ColorSpace</code> — The <a href="https://pdftheguide.com/glossary/pdf-color-space" target="_blank" rel="noopener">colour space</a> of the image data. Common values: <code>/DeviceGray</code> (greyscale), <code>/DeviceRGB</code> (RGB), <code>/DeviceCMYK</code> (CMYK), <code>/Indexed</code> (palette), or an ICC profile-based colour space array. Required for most images; for image masks, the /ImageMask entry is used instead.

<code>/BitsPerComponent</code> — The number of bits per colour channel per pixel: 1, 2, 4, 8, or 16. For an 8-bit RGB image, each pixel is 3 bytes (8 bits × 3 channels). Required unless /ImageMask is true.

<strong>Common optional entries:</strong>

<code>/Filter</code> — One or more compression filters applied to the stream data. Determines the compression format (see below).

<code>/SMask</code> — A reference to another Image XObject that serves as a soft mask (alpha channel) for this image, enabling transparency.

<code>/Interpolate</code> — Boolean that hints whether the viewer should interpolate the image when scaling up, producing smoother upscaling (at the cost of sharpness).

<code>/ImageMask</code> — Boolean; if true, the image is a 1-bit stencil mask rather than a full image, and the /ColorSpace and /BitsPerComponent entries are omitted.

Image compression filters

The raw pixel data of an image is almost always stored compressed. The <code>/Filter</code> entry in the stream dictionary specifies the compression applied:

<strong>DCTDecode (JPEG)</strong> — Lossy compression for continuous-tone photographic images. The stream data is standard JFIF/JPEG data. DCTDecode is the most common filter for photographic images in PDFs. When you embed a JPEG into a PDF without recompression, the JPEG data is typically stored as-is with a DCTDecode filter, preserving the original JPEG quality.

<strong>FlateDecode (zlib/DEFLATE)</strong> — Lossless compression for images with large areas of flat colour, line art, or text. Used for PNG-style images where lossless compression is required. FlateDecode images take more storage than DCT for photos but preserve every pixel exactly.

<strong>JPXDecode (JPEG 2000)</strong> — A more efficient lossy (and optionally lossless) compression introduced in PDF 1.5. Provides better quality-to-size ratio than JPEG for most content types. Supported by all current viewers but less commonly used than DCT.

<strong>JBIG2Decode</strong> — Specialised compression for bilevel (1-bit) images, particularly scanned text. Provides significantly better compression than CCITTFaxDecode for scanned documents. Used by some scanning systems and PDF optimisers for black-and-white scanned pages.

<strong>CCITTFaxDecode</strong> — CCITT Group 3 or Group 4 fax compression for bilevel images. Predates JBIG2 and is less efficient, but very widely supported. Common in older scanned PDF documents.

<strong>Inline images vs. XObjects</strong> — Very small images can alternatively be stored inline in the page content stream using the <code>BI</code>/<code>ID</code>/<code>EI</code> operators. Inline images are suitable only for very small images; larger images should always be Image XObjects.

Placing images on the page: the Do operator

An Image XObject stored in the PDF is not automatically visible — it must be explicitly referenced and placed by a page's content stream. The placement mechanism uses:

<strong>Resource registration</strong> — The Image XObject must be registered in the page's resource dictionary under <code>/XObject</code> with a name key: <code>/Resources &lt;&lt; /XObject &lt;&lt; /Im0 15 0 R &gt;&gt; &gt;&gt;</code>. Here <code>/Im0</code> is the name and <code>15 0 R</code> is the indirect reference to the image XObject.

<strong>The <code>Do</code> operator</strong> — To display the image, the content stream uses the <code>Do</code> (Draw Object) operator: <code>/Im0 Do</code>. This tells the viewer to render the named XObject.

<strong>Transformation matrix</strong> — Before calling <code>Do</code>, the content stream sets the current transformation matrix (CTM) using the <code>cm</code> operator to position and scale the image. The matrix format is: <code>a b c d e f cm</code>. For a 200-point-wide, 150-point-tall image at position (100, 400): <code>200 0 0 150 100 400 cm</code>. This matrix scales the image from its unit square (1×1) to the desired dimensions and position.

<strong>The unit square convention</strong> — PDF Image XObjects are defined in a normalised 1×1 unit square, regardless of their pixel dimensions. The /Width and /Height entries define the number of samples, not the display dimensions. The transformation matrix applied via <code>cm</code> before <code>Do</code> determines the actual rendered size and position on the page. This separation allows the same image XObject to be placed at different sizes and positions throughout a document without duplicating the image data.

Frequently asked questions

How can I extract images from a PDF?

Images in a PDF are stored as Image XObjects in the file structure. To extract them: Adobe Acrobat Pro: Edit > Copy > Copy Images (for single images) or Tools > Export PDF > Image to export all images. Command-line tools: pdfimages (part of poppler-utils) extracts all image XObjects from a PDF to image files; pdfimages -list filename.pdf shows image details (format, dimensions, bits per component, colour space, size) without extraction. Python: the PyMuPDF library (import fitz) provides page.get_images() to list images and doc.extract_image(xref) to extract individual images. Note that pdfimages extracts the raw compressed streams — a DCT-compressed image is extracted as JPEG, a Flate-compressed image as PNG. The dimensions and colour space come from the XObject dictionary, not from the image data itself.

Why does an image in a PDF look blurry when zoomed in?

Blurriness when zooming is caused by the image having insufficient resolution relative to the display size. In PDF, the image is stored at a fixed pixel resolution (e.g., 100 × 75 pixels). When the page is displayed at high zoom or printed at high DPI, the viewer interpolates the image — stretching those 100 pixels to cover a larger area. If the original image was only 72 PPI (pixels per inch) at normal view size, zooming to 300% requires displaying it at effectively 24 PPI, which will be visibly blurry. For print quality, images should be at least 300 PPI at their intended print size. The /Interpolate entry in the Image XObject controls whether the viewer uses bilinear/bicubic interpolation (smoother) or nearest-neighbour (sharper but pixellated) when upscaling.

What is an image mask in a PDF?

An image mask is an Image XObject with /ImageMask true. Instead of storing colour values, it stores a 1-bit (bilevel) pattern where 1-bits are "masked" (transparent, showing what is behind) and 0-bits are "painted" (using the current fill colour from the graphics state). Image masks are used for: rendering black-and-white logos or text at the current colour without a white background; applying a stencil pattern; and creating transparent areas. Image masks differ from soft masks (/SMask): a soft mask is an 8-bit or 16-bit Image XObject where each pixel value represents an alpha (opacity) value, enabling smooth semi-transparency. Image masks provide binary (on/off) transparency; soft masks provide graduated transparency.