Finance asked for one PDF. You have a camera roll.
Seven canteen photos. One expense form. This page creates a new document with pdf-lib, embeds each PNG or JPG as its own page, and sizes that page to the image’s pixel box. pdf-lib loads from jsDelivr. Your pictures are not posted to Privy Tools. Watch the compute log for a library fetch, not an upload. Selection order is page order. There is no mind-reading sort by filename, and there is no auto-rotate from EXIF, on purpose: if GPS and orientation tags still live in the JPEG, they can ride along inside the PDF because embedJpg keeps the JPEG bytes.
Worked example: three receipts, GPS still on
Phone camera, restaurant at 13:40, GPS in the file. If you stack first, a determined reader can pull the JPEG out of the PDF and see where you ate. Run EXIF remover first, then pick the cleaned JPGs in date order. Open page 1 of the result before you mail finance. If page 3 is sideways, rotate in a photos app and restack. I will not silently honor an Orientation tag you should have stripped.
Worked example: iPhone HEIC
The embed paths are PNG and JPG. Chrome often cannot decode HEIC. Renaming .heic to .jpg does not help. Convert to JPG with the format converter (or the phone’s “Most Compatible” setting), then stack. If embed throws, read the error instead of retrying the same HEIC five times.
Worked example: an ID scan that must print
A 1200-pixel-wide photo looks sharp on a phone and soft on a laser printer. Page size follows the image, so a tiny picture becomes a tiny page, not magically A4. If the office will print, recapture with a scanner or a higher-resolution photo. Mixing a landscape receipt with a portrait Aadhaar shot is how page 2 looks like a stamp in the corner of an empty sheet. Crop before you stack if you care about that.
What this will not do
OCR. Searchable text. Desk-mess auto-crop. A shared page size with margins. Digital signatures. If you need those, you wanted a scanner app with an OCR toggle, not a stacker. HEIC, WebP, and GIF support depend on whether the browser can decode them into something pdf-lib can embed; when in doubt, flatten to JPG or PNG first.
Memory is the cap, not a polite “max 12 images” marketing number. Twelve 12-megapixel photos on a phone tab will freeze more honestly than a spinner. Use a laptop for the fat stack. Keep the original images until finance confirms the PDF opened.
If you needed pages extracted from an existing PDF, that is merge & split, not this stacker. If you needed the reverse (a PNG of page 2), that is PDF to image. Mixing those three jobs in one upload farm is how people attach the wrong artefact. After you download, open the PDF and flick through every page. A blank page usually means a decode failure on one file that the loop skipped or a zero-byte drop. Re-add that image as JPG and restack rather than mailing a mystery sheet.
Questions
Are my photos uploaded?
No. Bytes stay in this tab. pdf-lib still loads from jsDelivr so the PDF can be built; that hop is the library, not your images.
How is page order decided?
The order you select files. Confirm page 1 before you send. Filenames are not sorted for you.
Does JPEG EXIF survive inside the PDF?
It can. embedJpg keeps JPEG bytes, GPS included. Strip with the EXIF remover first if location privacy matters.
Why did my HEIC fail?
This path embeds PNG or JPG. Convert HEIC to JPG first. Do not rename the extension and hope.
Is the PDF searchable?
No. Images stay images. OCR lives in a different tool.
Will pages be A4?
No. Each page is the pixel box of that image. Tiny photos make tiny pages.