Most "free online" image compressors upload your photo to a server, process it there and send it back. That works, but it means a copy of your file sits on someone else's machine, and the site pays for bandwidth and CPU, which usually ends in a daily limit or a watermark.
I wanted a toolkit where none of that happens. The result is Compressly: an image compressor, resizer, converter, background remover, upscaler and a set of PDF and Word tools. All of it runs in the browser tab.
This post explains how a few of the parts work.
Compressing to an exact file size
A lot of people don't care about "quality 80". They care about a limit: a job application that accepts photos under 100 KB, or an exam form that wants 50 KB.
The Canvas API can encode JPEG and WebP at a given quality, but it can't aim for a size. So Compressly runs a binary search over the quality value:
async function encodeToTarget(canvas, mime, target) {
let lo = 0.1, hi = 0.92, best = null;
const first = await encode(canvas, mime, hi);
if (first.size <= target) return first; // already fits at high quality
for (let i = 0; i < 7 && hi - lo > 0.015; i++) {
const q = (lo + hi) / 2;
const blob = await encode(canvas, mime, q);
if (blob.size <= target) { best = blob; lo = q; } // fits: try higher quality
else hi = q; // too big: go lower
}
return best; // highest quality that fits
}
If even the lowest quality is too big, it reduces the pixel dimensions, using the ratio between the target and the current size to estimate the next scale, and searches again. The UI always says whether the target was reached, instead of rounding the number down.
Two details made this fast enough to feel instant:
- Encoding runs in a Web Worker with
OffscreenCanvas.convertToBlob(), so a 7-pass search doesn't freeze the page. - The resized canvas is cached, so moving the quality slider only re-encodes and doesn't resample again.
Smaller PNGs without losing transparency
The browser's PNG encoder is always lossless, so a screenshot saved as PNG stays large. Tools like TinyPNG get their savings by reducing the image to a palette of up to 256 colours.
Compressly does the same thing in the worker: median-cut quantisation refined with a couple of k-means passes, optional Floyd–Steinberg dithering, and then it writes the indexed PNG itself (IHDR, PLTE, tRNS, IDAT) with CompressionStream('deflate') for the compression. Quality 96 or above skips the palette and keeps the PNG lossless.
AI background removal without a server
The background remover runs a segmentation model in the browser with Transformers.js. I chose ormbg because it is Apache-2.0 licensed; some popular background-removal models don't allow commercial use.
const T = await import('https://cdn.jsdelivr.net/npm/@huggingface/transformers@4.3.0');
T.env.backends.onnx.wasm.proxy = true; // run inference in a worker
const segment = await T.pipeline('background-removal', 'onnx-community/ormbg-ONNX', { dtype: 'q8' });
const [result] = await segment([T.RawImage.fromCanvas(canvas)]);
The quantised model is about 45 MB. It downloads the first time someone opens the tool and is cached after that. A photo takes around 10 seconds on a normal laptop CPU. For logos and signatures on a flat colour there's also a non-AI mode that removes the colour directly, including the inside of letters.
PDF and Word without libraries
The PDF tools write PDF 1.4 by hand: the standard 14 fonts with real font metrics for Latin text, JPEG images embedded as they are, and Flate-compressed content streams. Text in scripts the standard fonts can't show, such as Bangla, is drawn by the browser and embedded as a lossless image, so it always looks right.
.docx files are ZIP archives of XML, so Word to PDF unzips them with DecompressionStream, reads word/document.xml with DOMParser and lays out the paragraphs, lists and tables. The Text to PDF editor goes the other way and exports both PDF and a real .docx.
What I'd like feedback on
- Target size: is the "highest quality that fits" result good enough, or should it trade some resolution for quality sooner?
- Background removal: are 10 seconds and a one-time 45 MB download acceptable for you, or would you rather have a smaller, faster model with rougher edges?
You can try everything here, with no account: compresslyonline.blogspot.com
Thanks for reading!
Top comments (0)