close

DEV Community

Devanshu Biswas
Devanshu Biswas

Posted on

I Built an Image Compressor That Runs 100% in the Browser

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);
});
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)