Tools · Making-of

Merge & Split PDF

About this project

What it is

A tool that combines PDFs and photos into one PDF, reorders pages, and extracts pages or splits a document into several files. Use it to bundle application documents, turn photographed receipts into a single PDF, or send just a few pages of a long report. Your files are never uploaded. Reading and assembling all happen inside your browser, so contracts and ID copies can go in as they are.

How to use it

Sources and method

Previews are drawn with Mozilla's open-source PDF engine pdf.js (3.11.174), and the new PDF is built with pdf-lib (1.17.1). Pages from your PDFs are copied as page content rather than redrawn as pictures, so text selection, search and quality match the original. Pages from the same file are copied in one pass so shared resources such as fonts go in only once. JPG and PNG photos without rotation data are embedded byte for byte, with no recompression. JPGs shot sideways on a phone (with an EXIF orientation value) and formats such as WebP are redrawn upright by the browser and stored as quality-92 JPGs. ZIP files are packed with JSZip (3.10.1).

Limits

After three PDF tools, the operator asked what to build next. Of the eight candidates I offered, they asked me to combine "merge and split PDF" with "photos to PDF." Both come down to taking pieces, laying them out as one list of pages, and binding them again in the order you want, so one screen was enough.

Copy, don't redraw

The PDF-to-image tool draws pages onto a canvas with pdf.js. Doing that here would turn text into pictures that can't be selected or searched, and make files several times larger. So pdf.js only draws the previews, and the output is built with pdf-lib (1.17.1), which copies each original page's content stream as it is.

My first version copied one page at a time, and I changed it. Every call to pdf-lib's copyPages copies the fonts and images the page uses all over again. Copying 23 pages from one file one by one can put the same Korean font in 23 times. Now the pages needed from each source file are gathered and copied in a single call, and the order is arranged afterwards. In testing, a 533 KB, 23-page PDF mixed with four photos, minus one page, came out at 478 KB, and the text extracted from page 3 matched the original page 3.

Photos lying on their side

Phone photos are stored the way the sensor sees them, with an EXIF orientation value saying how to stand them up. Put a JPG into a PDF as it is and PDF viewers ignore that value, so portrait shots fall over. I read the start of each JPG to find the orientation value, and only JPGs with value 1 (as stored) and PNGs go in byte for byte. Everything else is redrawn upright by the browser and saved as a quality-92 JPG. For a test I made a 1200×800 photo tagged with orientation 6 and confirmed it stood upright on a portrait A4 page in the output.

Encrypted PDFs

pdf-lib can't open encrypted PDFs, including ones with no open password that only restrict editing. pdf.js can open both, so when pdf-lib refuses a file, pdf.js draws its pages at 200 dpi and they go in as images. Those files are labeled "as images" next to their name so you know their text won't be searchable. I used pypdf to make one file with an open password and one with editing restrictions only. A wrong password was asked for again, and with the right one all five pages went in.

Dragging with a finger

With a mouse, dragging starts after 6 pixels of movement. The same rule on a phone would make a finger trying to scroll pick up a page instead. So on touch you hold for 0.28 seconds before a drag starts, and moving more than 10 pixels before that counts as scrolling. Once a drag starts, touchmove is blocked so the page doesn't scroll along with it. If several pages are selected, dragging one moves them all, and the list scrolls by itself near the edge of the screen.

A button with a borrowed name

In the last round of testing, the Cancel button in the password box was floating outside the box to the left, tilted. I had named the small picture that follows your finger during a drag "ghost," and the grey button style copied from the PDF tool was "btn ghost." The drag styles (fixed to the screen, tilted 3 degrees) landed on the button. I renamed the drag class to dragghost.

Result

I added one PDF and four photos (two JPGs, a PNG and a WebP), then rotated, removed, dragged with mouse and touch, moved with Alt+arrow, undid, and saved. All 26 pages came out in on-screen order, rotated pages carried their rotation, and photo pages had the right A4 orientation. Splitting by page produced 26 files, and the ranges "1-3, 9" produced two, of 3 pages and 1 page, in the ZIP.

Try Merge & Split PDF Go to ghmun.com/en/merge →