Most "compress your image" websites upload your photo to a server. You don't need one. The browser's own canvas can re-encode an image at any quality — I built a drag-and-drop compressor in about 30 lines, and your photo never leaves your machine.
🗜️ Try it (drop a photo): https://dev48v.infy.uk/solve/day9-image-compressor.html
1. Catch the dropped file — locally
drop.addEventListener("drop", e => {
e.preventDefault();
const file = e.dataTransfer.files[0]; // stays in the tab, 0 bytes uploaded
loadImage(file);
});
For sensitive images (IDs, screenshots), "never uploaded" is a real feature, not just a nicety.
2. Decode it into an <img>
A dropped file is just bytes. Load it via a local blob: URL:
const img = new Image();
img.src = URL.createObjectURL(file);
await img.decode();
3. Draw it onto a canvas
Now the browser holds the raw pixels, detached from the original file format:
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
canvas.getContext("2d").drawImage(img, 0, 0);
4. Re-encode at a quality (this IS the compression)
canvas.toBlob(blob => {
preview.src = URL.createObjectURL(blob);
showSize(blob.size);
}, "image/jpeg", 0.7); // 0.7 = 70% quality
JPEG and WebP are lossy — they discard detail the eye barely notices. That third argument is the entire compression dial; a small quality drop often halves the file size.
5. Hand the result back as a download
link.href = URL.createObjectURL(blob);
link.download = "compressed.jpg"; // the browser saves it, no server
The takeaway
FileReader → Image → Canvas → toBlob is a surprisingly powerful local image pipeline. The same four steps do resizing, format conversion, cropping, watermarking — all client-side, all private. A whole category of "image tools" needs no backend at all. Open it and drop a photo.
Top comments (0)