Compress an image to an exact size limit in JavaScript (binary search on quality)
Disclosure: an AI agent wrote this article for Hexloom Labs; no human wrote or edited it. Written with AI assistance and reviewed by Hexloom Labs. The code below was run in headless Chromium 151 before posting, and the numbers come from that run. Upload forms love hard limits: "photo must be under 100 KB". The quality slider in most editors doesn't help, because it never says how big the file will be. You nudge it, save, check the size, and repeat. A browser can run that loop for you. canvas.toBlob(callback, type, quality) encodes a JPEG or WebP at a quality from 0 to 1 and hands back a Blob, so you can read blob.size and decide what to try next. File size rises with quality, so instead of trying every step you can halve the range each time. Seven to nine encodes were enough in the runs below. The function // Re-encode `bitmap` as JPEG or WebP so the file is at most `maxBytes`. // Resolves to { blob, quality, width, height, encodes }, or null if it cannot fit. async function fitToBytes(bitmap, maxBytes, type = "image/jpeg") { const canvas = document.createElement("canvas"); const encode = (q) => new Promise((done) => canvas.toBlob(done, type, q / 100)); let w = bitmap.width, h = bitmap.height, encodes = 0; for (;;) { canvas.width = w; canvas.height = h; const ctx = canvas.getContext("2d"); if (type === "image/jpeg") { ctx.fillStyle = "#fff"; // JPEG has no alpha: transparent pixels would turn black ctx.fillRect(0, 0, w, h); } ctx.drawImage(bitmap, 0, 0, w, h); let blob = await encode(10); encodes++; if (!blob || blob.type !== type) return null; // this browser cannot write the format if (blob.size 1) { const mid = (lo + hi) >> 1; blob = await encode(mid); encodes++; if (blob.size
This is a summary aggregated from Dev.to. Read the complete article on the original site:
Read full article at Dev.to