[{"data":1,"prerenderedAt":38},["ShallowReactive",2],{"$fSTrWXo-FnUwiM5Da_8iw4KLz_gzExBAMx6xHlXq4LMg":3},{"slug":4,"title":5,"description":6,"date":7,"tags":8,"tools":13,"draft":15,"html":16,"toc":17,"minutes":37},"putting-images-into-a-pdf","Putting Photos Into a PDF Without Re-Compressing Them","How ToolOnTap's Image to PDF tool sizes pages in points, turns pages for wide scans, keeps JPGs untouched with pdf-lib, and fixes sideways phone photos.","2026-09-24",[9,10,11,12],"pdf","images","pdf-lib","typescript",[14],"image-to-pdf",false,"\u003Cp>An expense system wants one PDF. You have eleven photos of receipts on your phone, two of them sideways, and one of a long receipt that’s taller than any page. That’s the situation I built ToolOnTap’s \u003Ca href=\"\u002Fimage-to-pdf\">Image to PDF\u003C\u002Fa> tool for. Putting a picture on a page sounds trivial, and mostly it is. The details are in page sizes, orientation, and not damaging the photos on the way in.\u003C\u002Fp>\n\u003Ch2 id=\"one-page-per-image-in-your-order\">One page per image, in your order\u003C\u002Fh2>\n\u003Cp>The tool makes one page per image, in the order of the list. Files are added in the order your device hands them over, and from there you move them by dragging, or with the up and down buttons on each row. The buttons work with a keyboard, and after each move a screen reader hears where the page went, for example “receipt-04.jpg moved to page 2 of 11”.\u003C\u002Fp>\n\u003Cp>Ordering matters more than it looks. The order a file picker hands over isn’t always the order you took the photos in, so the list shows a thumbnail and a number next to every page. You check the order before you create the PDF, instead of after.\u003C\u002Fp>\n\u003Ch2 id=\"page-sizes-are-measured-in-points\">Page sizes are measured in points\u003C\u002Fh2>\n\u003Cp>PDF measures everything in points, and a point is 1\u002F72 of an inch. The two standard paper sizes in the tool are stored in points:\u003C\u002Fp>\n\u003Cdiv class=\"table-wrap\">\u003Ctable>\u003Cthead>\n\u003Ctr>\n\u003Cth>Page size\u003C\u002Fth>\n\u003Cth>Points\u003C\u002Fth>\n\u003Cth>Paper\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>A4\u003C\u002Ftd>\n\u003Ctd>595.28 × 841.89\u003C\u002Ftd>\n\u003Ctd>210 × 297 mm\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>US Letter\u003C\u002Ftd>\n\u003Ctd>612 × 792\u003C\u002Ftd>\n\u003Ctd>8.5 × 11 in\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\u003C\u002Fdiv>\u003Cp>Letter comes out in round numbers because it’s defined in inches (8.5 × 72 = 612). A4 is defined in millimeters, so its points aren’t whole. The margins are points too: None is 0, Small is 18 (about 6 mm) and Large is 36 (about 13 mm).\u003C\u002Fp>\n\u003Cp>The third option, “Same as image”, has no fixed size. Each page is made exactly as big as its picture, plus the margin. Images are measured in pixels, so the tool needs a conversion, and it uses the CSS one: 96 pixels per inch. An 800 × 600 screenshot becomes a 600 × 450 point page, which a PDF viewer at 100% zoom shows at about the size the screenshot had on screen.\u003C\u002Fp>\n\u003Ch2 id=\"turning-the-page-for-wide-images\">Turning the page for wide images\u003C\u002Fh2>\n\u003Cp>On A4 and Letter, every image is scaled to fit inside the margins and centered on its page. Here’s the whole placement function:\u003C\u002Fp>\n\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">export\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\"> function\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> placeImage\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#b35309;--shiki-dark:#FFAB70\">image\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">:\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> Size\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#b35309;--shiki-dark:#FFAB70\">size\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">:\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> PageSize\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#b35309;--shiki-dark:#FFAB70\">margin\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">:\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> PageMargin\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">)\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">:\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> PagePlacement\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">  const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> m\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> MARGINS\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">[margin]\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">  if\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> (size \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">===\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> 'fit'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">) {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">    const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> width\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> image.width \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">*\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> PX_TO_PT\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">    const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> height\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> image.height \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">*\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> PX_TO_PT\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">    return\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { page: { width: width \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">+\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> 2\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\"> *\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> m, height: height \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">+\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> 2\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\"> *\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> m }, image: { x: m, y: m, width, height } }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">  const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> base\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> PAGE_SIZES\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">[size]\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">  const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> landscape\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> image.width \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">>\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> image.height\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">  const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> page\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> landscape \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">?\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { width: base.height, height: base.width } \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">:\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">...\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">base }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">  const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> scale\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> Math.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">min\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">((page.width \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">-\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> 2\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\"> *\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> m) \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">\u002F\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> image.width, (page.height \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">-\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> 2\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\"> *\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> m) \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">\u002F\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> image.height)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">  const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> width\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> image.width \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">*\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> scale\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">  const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> height\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> image.height \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">*\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> scale\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">  return\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { page, image: { x: (page.width \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">-\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> width) \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">\u002F\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> 2\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, y: (page.height \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">-\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> height) \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">\u002F\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> 2\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, width, height } }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>The \u003Ccode>landscape\u003C\u002Fcode> line is the decision that matters. If an image is wider than it is tall, its page turns sideways. Without that, a landscape scan of a two-page spread would be shrunk to fit the width of a tall sheet, with empty space above and below. A square image counts as portrait.\u003C\u002Fp>\n\u003Cp>The \u003Ccode>Math.min\u003C\u002Fcode> picks whichever side hits the margin first, so the image always fits without being cropped or stretched. A 3000 × 4000 phone photo on A4 with Small margins comes out about 559 × 746 points, and it touches the side margins with a little space above and below.\u003C\u002Fp>\n\u003Cp>Two honest consequences of this:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>Small images are scaled up\u003C\u002Fstrong> to fill the page, because the scale factor can be bigger than 1. A small screenshot on A4 will look soft. “Same as image” is the better choice for screenshots, and the tool page says so.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Each page decides for itself.\u003C\u002Fstrong> In a mixed set, landscape photos get landscape pages and portrait photos get portrait pages in the same PDF. PDF viewers show each page the right way up, but it surprises people the first time.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>My long receipt from the opening ends up as a narrow strip in the middle of a portrait page, because its height is what hits the margin. It’s readable, and you can zoom in, but if it’s very long, crop it into two images first.\u003C\u002Fp>\n\u003Ch2 id=\"keeping-jpgs-untouched\">Keeping JPGs untouched\u003C\u002Fh2>\n\u003Cp>The PDF itself is written by pdf-lib. It’s only imported when you click “Create PDF”, so the page loads without it.\u003C\u002Fp>\n\u003Cp>pdf-lib can embed JPG and PNG files directly. A JPG goes into the PDF byte for byte, compressed exactly as it was, so there’s no second round of JPG compression and no quality loss. That’s the path the tool takes whenever it can:\u003C\u002Fp>\n\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> embedAsIs\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> file.type \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">===\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> 'image\u002Fpng'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\"> ||\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> (file.type \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">===\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> 'image\u002Fjpeg'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\"> &#x26;&#x26;\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> jpegOrientation\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(bytes) \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#cb2431;--shiki-dark:#F97583\">===\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> 1\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">)\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>The second half of that line is about phone photos. Phones often save a photo with its pixels sideways and a small EXIF tag that says how to turn it. Browsers and gallery apps read that tag. PDF viewers don’t, because inside a PDF the image is just pixels. Embed one of those JPGs as it is, and the page shows it on its side.\u003C\u002Fp>\n\u003Cp>So before embedding a JPG, the tool reads its orientation tag. It walks the JPG’s markers from the start of the file, finds the APP1 block that starts with “Exif”, and reads tag \u003Ccode>0x0112\u003C\u002Fcode>, handling both byte orders a camera can use. If it finds no tag, or the value is 1 (upright), the JPG goes in untouched. If not, it’s drawn onto a canvas (which applies the rotation) and saved again as a JPG at 92% quality, then embedded.\u003C\u002Fp>\n\u003Cp>Other formats take the same path. WebP and GIF can’t be embedded directly by pdf-lib, so they’re re-encoded as JPG too. That canvas step has the same 16,777,216-pixel cap the other image tools use, the largest canvas iOS Safari will draw, so a very large non-JPG image is scaled down to fit under it. HEIC photos are sent to the \u003Ca href=\"\u002Fheic-to-jpg\">HEIC to JPG converter\u003C\u002Fa> first, because only Safari can decode them.\u003C\u002Fp>\n\u003Ch2 id=\"how-big-the-pdf-gets\">How big the PDF gets\u003C\u002Fh2>\n\u003Cp>Because JPGs go in as they are, the PDF ends up roughly as big as your images added together, plus a little for the page structure. Eleven 3 MB phone photos make a PDF of about 33 MB, which is too big to attach to many emails. Compress the photos first with the \u003Ca href=\"\u002Fcompress-image\">image compressor\u003C\u002Fa>, then make the PDF. The tool won’t do that silently, because it would mean changing your images without asking.\u003C\u002Fp>\n\u003Cp>Each image can be up to 50 MB, and there’s no fixed page limit. The real limit is your device’s memory, since the whole PDF is built in memory before you download it, on your own device, with nothing uploaded. A single image gives you a PDF named after it (\u003Ccode>receipt.jpg\u003C\u002Fcode> becomes \u003Ccode>receipt.pdf\u003C\u002Fcode>), and several give you \u003Ccode>images.pdf\u003C\u002Fcode>.\u003C\u002Fp>\n\u003Ch2 id=\"try-it\">Try it\u003C\u002Fh2>\n\u003Cp>\u003Ca href=\"\u002Fimage-to-pdf\">Image to PDF\u003C\u002Fa> handles receipts, signed forms and screenshots. Use A4 or US Letter for anything that will be printed, and “Same as image” for screenshots. Once you have a PDF, the \u003Ca href=\"\u002Fpdf-tools\">PDF tools\u003C\u002Fa> can merge it with others, rotate pages or put them in a new order.\u003C\u002Fp>\n",[18,22,25,28,31,34],{"id":19,"text":20,"level":21},"one-page-per-image-in-your-order","One page per image, in your order",2,{"id":23,"text":24,"level":21},"page-sizes-are-measured-in-points","Page sizes are measured in points",{"id":26,"text":27,"level":21},"turning-the-page-for-wide-images","Turning the page for wide images",{"id":29,"text":30,"level":21},"keeping-jpgs-untouched","Keeping JPGs untouched",{"id":32,"text":33,"level":21},"how-big-the-pdf-gets","How big the PDF gets",{"id":35,"text":36,"level":21},"try-it","Try it",5,1792325805351]