Home / Media and Real Time / Image Compressor

Image Compressor in JavaScript, Free with Live Demo

Free bulk image compressor in plain JavaScript. Resize and convert photos to WebP, AVIF or JPEG in a Web Worker with OffscreenCanvas, and compare before and after.

Open live demoDownload HTML fileView code on GitHub
Image Compressor JavaScript project: shrink photos in bulk without uploading them

Runs on: OffscreenCanvas in a Worker. Every modern browser. AVIF output: Chrome and Edge. Safari encodes JPEG and PNG; its WebP output may fall back to PNG.

What is the Image Compressor?

Drop a batch of photos, pick a size and quality, and get smaller files back in seconds, with a before and after slider on each one. Nothing is uploaded.

The heavy work runs in a Web Worker so the page never freezes. Each photo becomes an ImageBitmap, is drawn at the new size on an OffscreenCanvas, and is encoded to the format you picked.

Good for

  • Shrinking photos before upload
  • Faster pages and better Core Web Vitals
  • Making WebP versions of images
  • Learning Web Workers

What this project does

How it works

  1. DecodeEach file becomes an ImageBitmap with createImageBitmap, which decodes off the main thread.
  2. Resize in a workerThe bitmap is sent to the worker, drawn at the new size on an OffscreenCanvas with high quality smoothing.
  3. EncodeconvertToBlob encodes to the chosen format and quality. The page gets back the new file and its size.

The key JavaScript

This is the heart of the project. The full file has the rest, including the screen layout and error handling.

// worker.js (created from a Blob so the page stays a single file)
self.onmessage = async ({ data: { id, bitmap, width, type, quality } }) => {
  const scale = width ? Math.min(1, width / bitmap.width) : 1;
  const canvas = new OffscreenCanvas(Math.round(bitmap.width * scale), Math.round(bitmap.height * scale));
  const ctx = canvas.getContext("2d");
  ctx.imageSmoothingQuality = "high";
  ctx.drawImage(bitmap, 0, 0, canvas.width, canvas.height);
  const blob = await canvas.convertToBlob({ type, quality });
  self.postMessage({ id, blob, w: canvas.width, h: canvas.height });
};
// page
worker.postMessage({ id, bitmap, width: 1920, type: "image/webp", quality: 0.75 }, [bitmap]);

How to use it

  1. Click Download HTML file above.
  2. Open the file in a code editor, like VS Code.
  3. Run it from a local server with npx serve . so the camera, microphone and AI features are allowed.
  4. Change the text and colors, then upload it to GitHub Pages, Netlify or your own site. It is one file with no build step.

Questions people ask

Is WebP or AVIF better?

AVIF files are usually smaller at the same quality, but encoding is slower and fewer browsers can create them. WebP is a safe default.

Does compressing lose quality?

A little, depending on the quality slider. Around 0.75 is hard to tell apart from the original for most photos.

Why use a Web Worker?

Encoding big images takes time. Doing it in a worker keeps scrolling and clicking smooth.

More Media and Real Time projects