Urgent.News

What's breaking now, across thousands of outlets.

Tech

Writing a real PNG compressor in vanilla JavaScript (no WASM, no libraries)

Every online image converter I tried had the same shape: drag your file in, it uploads to a server somewhere, you get a download link back. That's fine for a meme. It's less fine for a scan of your passport, and it's the most common thing people convert. So I wanted to know how far a browser could get on its own. Quite far, as it turns out — but not without a few traps that cost me an evening…

Every online image converter requires users to upload files to a server before providing a download link. This approach works for simple tasks like sharing memes but fails when dealing with sensitive documents, such as passport scans. It is the most common type of file conversion people perform. To explore how far a browser can go without relying on external servers, the author decided to create a real PNG compressor using vanilla JavaScript—without WebAssembly (WASM) or libraries.

Browsers can decode and encode various image formats, including PNG, JPEG, WebP, GIF, BMP, AVIF, SVG, and ICO. However, the only three formats they can encode are PNG, JPEG, and WebP. If you need to create or manipulate other formats like BMP or ICO, you must write the code to handle them byte by byte.

The first trap the author encountered was with the `canvas.toBlob()` method. This method accepts a MIME type as an argument, and when given an unsupported format, it doesn't throw an error or return null. Instead, it silently generates a PNG with a successful callback. For instance, creating a PNG from an AVIF image using `canvas.toBlob()` would result in a file named `.avif`, which is actually a PNG.

This deceptive behavior can lead users to believe their conversions are working correctly, but the files are actually in the wrong format. To avoid this issue, the author recommends checking the MIME type returned by `toBlob()` against the one requested.

The second trap involves the compression of PNG images. When converting a PNG to a blob using `canvas.toBlob()` with the 'image/png' MIME type, the resulting file is often larger than the original. PNG supports a lossless compression algorithm, but the `toBlob` function doesn't offer a quality setting. To truly compress a PNG, you must manually implement the compression process, which involves creating an optimized color palette and storing pixel data as indices rather than full color values.

This approach requires a deeper understanding of the PNG file format and can lead to significant file size reductions.

Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.

Read the original at dev.to →

More in Tech

More from Thursday 17 September →