JPG 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.

The picture is not re-encoded. PDF’s DCTDecode filter is JPEG, so your file’s own bytes are copied into the page with no decode and no re-encode. The photograph in the PDF is the photograph you started with, bit for bit — and this page shows you the two byte counts so you can see that they match.

…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 JPEG 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.

And the JPEG is not touched. PDF's DCTDecode filter is JPEG — not something like it, the same thing — so a JPEG goes into the page as a stream of its own original bytes. Nothing decodes it, nothing re-encodes it, and the dimensions shown below are read out of the file's own markers because there is no decoded image to measure. Progressive JPEGs work as well as baseline ones, which is the opposite of what the usual advice says.

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.