{"slug": "building-a-browser-only-image-compressor-what-we-actually-measured", "title": "Building a Browser-Only Image Compressor: What We Actually Measured", "summary": "A developer built a browser-only image compressor that runs WebAssembly encoders and Canvas pixel work entirely inside the tab, so files never leave the user's machine. Benchmarks across five representative inputs showed gains depend heavily on the chosen route: palette quantization cut a 1920x1080 UI screenshot by 70.3% while lossless saved only 2.2%, and a small transparent icon actually grew when routed to WebP. The writeup notes large images are limited by device memory and that batching remains the weak point without a server-side API.", "body_md": "Building a Browser-Only Image Compressor: What We Actually Measured\n\nMost \"online image compressor\" pages upload your file, compress it on a server, and hand back a download link. That works, but it costs you two things: your file leaves your machine, and the result depends on someone else's queue depth.\n\nWe wanted the opposite: the pixels never leave the browser. Here is what that looks like in practice, and what the measurements actually say.\n\nWhy \"local\" is an architecture decision, not a promise\n\nA privacy claim is only as good as its architecture. If a page uploads your image, \"we delete it in 24 hours\" is policy. If a page never uploads, there is nothing to delete.\n\nThe verification is trivial: open the page, disconnect the network, drop an image in, and see whether a result comes out. If it does, the work happened in the tab.\n\nWhat runs inside the tab\n\nEncoding is handled by WebAssembly builds of established encoders, and pixel work runs on Canvas:\n\nNo model inference, no cloud GPU, no heuristics learned from data. Same input, same parameters, same output, every time.\n\nThe measurement table\n\nFive representative inputs, all processed with the same build:\n\nInput | Original | Lossless | Quantized | WebP\n\nTransparent PNG icon 800x600 | 5.3 KB | 4.3 KB (-18.6%) | 3.3 KB (-37.6%) | 6.1 KB (larger)\n\nCamera JPEG 2000x1500 q95 | 1.54 MB | - | q75: 374 KB (-76.2%) | -\n\nUI screenshot 1920x1080 | 9.6 KB | 9.3 KB (-2.2%) | 2.8 KB (-70.3%) | -\n\nFull-color PNG 1600x1200 | 473.7 KB | 375.5 KB (-20.7%) | 55.8 KB (-88.2%) | 16.1 KB (-96.6%)\n\nGIF 400x400, 12 frames | 21.8 KB | - | 92.4 KB (larger) | 61.8 KB (larger)\n\nThree conclusions worth keeping\n\nThe gain depends on the route, not the tool. A transparent 5 KB icon can get *bigger* if you route it to WebP, because the container overhead eats the savings. The same icon quantized saves 37%.\n\nScreenshots belong on the quantized route. Lossless optimization on a 1920x1080 UI capture saves 2%; palette quantization saves 70% with no visible difference at 100% zoom.\n\nFormat flexibility is worth more than encoder tuning. Allowing WebP on full-color art took the result from 55.8 KB to 16.1 KB. Users who insist on \"keep PNG\" cut their own ceiling in half.\n\nWhere it breaks\n\nLarge images are limited by the device, not the code. A 4000x3000 photo takes 3-5 seconds on a low-end phone and under a second on a desktop. Peak memory is roughly concurrency × decoded bitmap × 2, so a four-way batch on 48 MB bitmaps can approach 400 MB and trigger GC churn.\n\nBatching is the real weak point. Without a server there is no API, so bulk work means dragging files by hand. If you need an unattended pipeline, use command-line tools (oxipng, jpegoptim, ImageMagick) or a service with an endpoint. Browser-local is for a handful of files at a time.\n\nWhat we'd optimize next\n\nDownscale before encoding. Worker pools with OffscreenCanvas. Concurrency at half the physical core count. And a three-stage progress indicator (decode, encode, package) — because past about twenty files the bottleneck stops being CPU and becomes feedback.\n\nMeasurements above come from our own runs on the same algorithm family, and are meant as an upper-bound reference for what each route can achieve in a browser — not a guarantee for every input. If you want to check them, open the tool, disconnect, and run your own images.\n\nThe broader point is simple: for a specific, bounded class of tasks, the browser is now a legitimate compute target. The constraint is not whether it can run — it is whether you are willing to design for the device you do not control.", "url": "https://wpnews.pro/news/building-a-browser-only-image-compressor-what-we-actually-measured", "canonical_source": "https://dev.to/wu_ruihua_bbdb65cdbde7b48/building-a-browser-only-image-compressor-what-we-actually-measured-1l26", "published_at": "2026-11-15 12:44:22+00:00", "updated_at": "2026-11-15 12:49:18.064744+00:00", "lang": "en", "topics": ["developer-tools", "ai-tools"], "entities": ["WebAssembly", "Canvas", "WebP", "oxipng", "jpegoptim", "ImageMagick", "OffscreenCanvas"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/building-a-browser-only-image-compressor-what-we-actually-measured", "markdown": "https://wpnews.pro/news/building-a-browser-only-image-compressor-what-we-actually-measured.md", "text": "https://wpnews.pro/news/building-a-browser-only-image-compressor-what-we-actually-measured.txt", "jsonld": "https://wpnews.pro/news/building-a-browser-only-image-compressor-what-we-actually-measured.jsonld"}}