How JPG to PDF Conversion Works in Your Browser
A PDF is not a single blob of bytes but a structured collection of objects — a catalog, a page tree, content streams, and image dictionaries — linked by cross-reference tables. Building one by hand is fiddly, which is why this page loads pdf-lib, a pure-JavaScript PDF toolkit that runs entirely in the browser. When you drop a file, the converter calls PDFDocument.create() to open an empty in-memory document, reads your image through file.arrayBuffer(), and registers it with doc.embedJpg().
Embedding is deliberately lossless: pdf-lib reads the JPEG's DCT-coded stream and stores it in the PDF as an image XObject without decoding and re-encoding the pixels. The image's declared width and height in pixels become the page's dimensions in PDF points — the format's default unit of 1/72 inch — so a 1200×800 image yields a 1200×800-point page with no scaling or margins. A single drawImage() call places the XObject at full size on that page, and doc.save() serializes the object graph: indirect object numbers, the page tree, and the cross-reference table, all compressed where the spec allows.
The serialized bytes are wrapped in a Blob with the application/pdf MIME type, turned into an object URL, and handed to the download button. Because the entire object graph lives in browser memory, the source image is never buffered on disk or transmitted anywhere — the only thing that travels is the finished PDF, from your RAM to your downloads folder. The output is a standards-compliant PDF 1.7 document that opens in Acrobat, Preview, and every in-browser PDF viewer, and because the embedded stream was never re-encoded, the image inside it is byte-for-byte the image you started with.