PNG to PDF

Nothing you choose here leaves your browser, and nothing is downloaded to make it work. The PDF is assembled on your own device by a page of code that is part of this site — there is no library, no server, and no upload.

A PNG cannot be carried into a PDF whole, the way a JPEG can — PDF does not read PNG’s container. So the picture is decoded by your browser and the pixels are deflated straight back in, which is the same compression PNG was using inside its own file. Nothing is thrown away; the file just gets rewrapped, and this page shows you what that cost in bytes.

…or drop files anywhere on this page.

What this conversion costs you

Every conversion loses something, and the honest version of that sentence names it. Here is what putting a PNG into a PDF keeps and what it does not.

What survives

What does not

How it works, and why nothing is downloaded

A PDF is a far simpler thing to write than it is to read. It is a header, a numbered list of objects, a table saying which byte each object starts at, and a trailer pointing at the table. That is the whole file format for a document like this one, and it is what lib-pdf.js does — about a page of code, no library, nothing fetched.

Every PDF this page writes is laid out the same way. Object 1 is the catalogue, object 2 the page tree, and then each picture takes three objects: the page, the image itself, and a one-line content stream that says where on the page to paint it. After the objects comes the cross-reference table, which is one twenty-byte line per object giving its offset from the start of the file, and after that the trailer with the offset of the table.

The per-file working below is that structure with the actual numbers in it — how many objects, which byte the table starts at, and how large the finished file is. If the arithmetic in a cross-reference table is wrong by even one byte the file is broken, although you would very likely never find out: the readers this site tested both silently repaired a deliberately corrupted table and opened the file anyway. That a PDF opens is therefore not evidence that it is correct, which is why the offsets here are recorded as the file is built rather than measured afterwards.

Why this one costs bytes and JPEG does not. PDF's image filters were fixed a long time ago and the list has never included PNG's container or WebP at all. So there is no way to carry either file in whole. The browser decodes the picture, the pixels are deflated — by CompressionStream, which is part of the browser, so still nothing is downloaded — and the result goes in as FlateDecode. That is lossless, and for a screenshot or a diagram it is also small. For a photograph it is not: deflate is not a photographic compressor, and the same picture as a JPEG would make a PDF a fraction of the size. The working below gives both numbers.

Where to go next

The same job in the other direction, and the rest of the PDF pages:

What this does not do

It makes a PDF that holds pictures. It does not make a PDF that holds text: there are no words in the output, nothing is searchable, and nothing can be selected. If you need a searchable document, this is the wrong tool and no browser-side converter is the right one.

It does not merge, split, rotate, sign, encrypt or compress an existing PDF, and it does not read one at all — it only writes. It will not enlarge a small picture to fill a large page, because that is a decision you did not ask for; a picture smaller than the space available is centred at its own size.

And it does not upload anything, so it cannot work on a file that is not on the device you are using.