More Fussing With Images

With Safari finally recently landing support for WebP and Chrome and Firefox picking up AVIF, web developers are actually starting to use them in ordinary projects.

A major problem, however, remains: no magic formula exists for determining the best compression settings to use when generating them. Every source image is different, and results will vary.

At present, most developers either pick a "good enough" average value to apply to all conversions — like cweb -jpeg_like — or let the computer pick what it judges to be "similar enough", but of course, such strategies result in winners and losers. Some files will be larger than necessary, while others might look noticeably worse than the original.

Of course, one can generate a WebP at, say, a quality of 70, eyeball the result, and do it again at 65, etc., but that is incredibly time-consuming, error prone, and utterly impractical at scale.

Is there a better way?

Refraction Testing

Inspired by the A/B lens test you get every time you go in for a vision tune-up, we designed Refract to generate WebP and AVIF copies at varying qualities automatically, stopping after each point to ask whether or not the candidate looks good.

To determine the ideal quality setting, Refract implements a moving range, choosing the midpoint at each step. Each "Yes" answer lowers the range's ceiling, while each "No" answer raises the floor. Either way, the number of qualities to test is continuously halved, allowing it to find the smallest possible acceptable image in just 5-10 steps instead of 100.

(PNG-to-WebP conversion also tries lossless compression, but does not need to ask for feedback; it'll just run with it unless a smaller, lossy version is discovered.)

Refract eliminates the command-line tedium by handling all encoding internally and ensures the resulting images do not exceed the disk size of the source.

# Make WebP and AVIF copies of one image.
refract /path/to/image.jpg

# Do several images in one go.
refract /path/to/image.jpg /path/to/more/images

# Skip the WebP bit.
refract --no-webp /path/to/image.jpg

# Skip the AVIF bit.
refract --no-avif /path/to/image.jpg

Caveats

While Refract makes hand-tuning individual WebP and AVIF image conversions easier, the process still takes time. WebP encoding is pretty zippy, but AVIF encoding can be a bit sluggish. As such, you probably don't want to go wild and tackle more than a few dozen images at once. You'll need to break and stretch your legs occasionally!

File names for the new formats are generated automatically by chucking ".webp" or ".avif" onto the end of the source path, e.g. /path/to/image.jpg.avif. If you don't like the double extension you can always rename the files after, but this does help avoid collisions.

And as we mentioned in our Fussing With Images post, sometimes WebP or AVIF or both will fail to achieve any byte savings over the original source graphics. In such cases, Refract will simply not make one.

Grab It!

Pre-built .deb packages are listed with each release for easy installation on Debian/Ubuntu systems.

Alternatively, you can grab the Rust source from the repo and manually build it with Cargo on other 64-bit Unix platforms.

We hope Refract saves you some time!

Josh Stoik
4 April 2021
Previous Faster Path Canonicalization in Rust