About Image Format Converter
Every image format makes a different trade-off between file size, quality and compatibility, and "just convert it" is rarely as simple as it sounds because those trade-offs don't line up neatly. PNG is lossless and supports transparency, which makes it the right choice for screenshots, logos and anything with sharp edges or text, but it compresses photographs relatively poorly compared to a format designed for them. JPEG is lossy — it throws away image detail humans are less likely to notice, controlled by a quality setting — and produces much smaller files for photographs, but it has no transparency channel at all and can introduce visible blocky artifacts at low quality. WebP is a newer format that generally beats both PNG and JPEG at their own games, offering both lossless and lossy modes with better compression than either older format at an equivalent quality, though a small number of older tools and workflows still don't accept it. BMP is essentially the odd one out: an old, deliberately simple, uncompressed format that stores every pixel's colour value directly with no compression at all, which makes it enormous compared to any of the other three, but guarantees pixel-perfect fidelity and total compatibility with very old or minimal software that can't parse a compressed format.
This tool handles the decode side by leaning entirely on the browser's own image decoder: the file is loaded into a plain `<img>` element, and whatever formats that specific browser already knows how to display natively — PNG, JPEG, WebP, GIF, BMP, and often SVG and AVIF too — are read successfully. This is deliberate: rather than trying to reimplement a JPEG or PNG decoder in JavaScript (a huge, error-prone undertaking that would inevitably lag behind and disagree with the browser's own battle-tested decoder), the tool simply asks the browser to do what it already does every time it displays any image on any webpage, then draws the fully-decoded result onto a canvas. From that canvas, three of the four output formats (PNG, JPEG, WebP) are produced using the browser's native `canvas.toBlob()` export, which every modern browser supports directly.
BMP is the exception, and it's worth being explicit about why: no browser's `canvas.toBlob()` implementation supports exporting to BMP, in any browser, on any platform — it's simply never been implemented, presumably because BMP has had essentially no web use for decades. So for BMP output specifically, this tool hand-rolls a minimal, uncompressed 24-bit BMP encoder directly in JavaScript: reading the decoded pixel data back out of the canvas with `getImageData()`, then writing the exact byte layout the BMP file format specifies — a 14-byte file header, a 40-byte info header, and the raw pixel data itself, stored bottom-up (the last row of the image is written first) in BGR byte order rather than the RGB order canvas uses internally, with each row padded to a multiple of 4 bytes. This is a fully spec-compliant, if basic, BMP writer — it just doesn't apply any compression, matching what "uncompressed 24-bit BMP" has always meant.
A few input formats are explicitly out of scope, and it's worth knowing why rather than hitting a confusing silent failure. HEIC (the format modern iPhones save photos in by default) only decodes in browsers that have added native HEIC support — this varies by browser and version and isn't something this tool controls; if your browser can't decode it, the file will show a clear error rather than a blank result. TIFF isn't decoded natively by any mainstream browser at all, so it will always fail to load here — convert it with dedicated desktop software first. And animated GIFs will convert successfully, but only their first frame: a canvas only ever "sees" one static frame of an animated image, by design, so the output is always a single still frame rather than the full animation, regardless of which output format you choose.