← Blog

PNG to PDF — embedding without recompression

PNG and PDF both use deflate; the embedded image lands as a /FlateDecode XObject inside the PDF screenshot.png 8-byte signature IHDR width, height, bit depth PLTE palette (if indexed) IDAT zlib(filter+pixels) IDAT more compressed data IEND end of file PNG is "deflate of filtered rows" — same algorithm as PDF /FlateDecode lossless re-compress, set DPI, embed as a PDF Image XObject screenshot.pdf /Image XObject /Width 1920 /Height 1080 /BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter /FlateDecode pixels lossless; bytes are not the original IDAT bytes

PNG and PDF share a remarkable property: both use deflate (zlib) for lossless compression of pixel data. PDF's /FlateDecode filter is deflate. With one extra parameter — a row predictor — PDF can in principle decode PNG-encoded streams natively. The PNG you upload ends up as a /FlateDecode Image XObject inside the resulting PDF. The pixels are byte-for-byte identical to the source; the bytes inside the PDF stream may not be the same as the IDAT bytes, but the visible result is.

How PNG actually works

A PNG file is a sequence of typed chunks. The relevant ones for understanding compression:

Inside the IDAT deflate stream, pixels are organized row by row. Each row is preceded by a 1-byte filter type that selects how that row's pixels were filtered before deflate (None, Sub, Up, Average, Paeth — predictors that improve compression by using nearby pixel values to predict the current pixel).

What PDF supports

PDF's /FlateDecode filter is deflate, the same algorithm. PDF's /DecodeParms dictionary lets you specify a "PNG predictor" — exactly the same row filtering scheme used by PNG, with the same five filter types.

Specifically, /DecodeParms << /Predictor 15 /Columns 1920 /Colors 3 /BitsPerComponent 8 >> tells the decoder: "after deflate, treat the data as 8-bit RGB rows of 1920 pixels each, with a per-row PNG-style filter byte". A PDF reader implementing this correctly produces the same pixels as a PNG decoder.

What happens during conversion

  1. The PNG goes through a lossless re-compression pass — alternative filter and zlib choices are tried, and the smaller result is kept.
  2. DPI is set on the file so that the page-size math comes out right.
  3. The PNG is embedded as a /FlateDecode Image XObject on a single PDF page, with the appropriate color space derived from the source.
  4. Source EXIF metadata (CreateDate, Author, Copyright) is copied across to the PDF.

The decoded pixels in the output are identical to those a PNG viewer would extract — no quality loss. The output size is comparable to (and usually slightly smaller than) the input PNG, thanks to the lossless re-compression step.

Alternative: true pass-through tools

Specialized PDF libraries that target PNG-to-PDF specifically can pass IDAT bytes through to PDF's /FlateDecode + /Predictor 15. The output is byte-identical to the input PNG inside the PDF, occasionally a few percent smaller for highly-filtered content. If size is critical, those tools are worth a look.

Things to know about specific PNG variants

  1. Indexed PNGs with low color count. A 256-color indexed PNG carries through cleanly — PDF supports /Indexed color directly. For screenshots that could use a palette but were saved as truecolor (common from "save as PNG" dialogs), palettizing first reduces size by 50–70%. The conversion preserves whatever the input was.
  2. 16-bit PNGs. PDF supports 16-bit color in principle, but support across viewers is patchy, so the output usually settles on 8-bit.
  3. Animated PNGs (APNG). Only the first frame ends up in the PDF; the animation chunks (acTL, fcTL, fdAT) don't have a place in a static PDF page.

Alpha channel handling

PNG supports a per-pixel alpha channel. PDF supports it too via the /SMask entry on the Image XObject — a separate grayscale image used as an alpha mask.

For a PNG with alpha, PDF's data model puts the RGB channels in the main Image XObject and the alpha channel in a separate /SMask Image XObject of the same dimensions. The PDF reader composites them at render time, producing the same blended-with-page-background result as a PNG viewer.

This split costs some efficiency: deflate compresses RGB+alpha together better than RGB and alpha separately. The size penalty is typically 5–15% — but it's what PDF requires for soft transparency.

The page around the image

Like JPG, the PNG image becomes one Image XObject on a single page. PNG2PDF defaults to A4 portrait at 96 DPI and computes a DPI that fits the image. The matrix in the page content stream places the image; the underlying PNG data doesn't move.

For a 1920 × 1080 screenshot on A4 portrait, the required DPI is 1920 × 72 / 595 = 232. The image lands at 8.27 × 4.65 inches — full A4 width, with white space top and bottom. Auto-rotated landscape A4 produces a wider but still-letterboxed result.

The result is a real PDF

Standard, valid, opens in any reader, prints, and combines with other PDFs without surprise. The fact that the image data is PNG-encoded internally is a detail visible only to people writing PDF parsers.