How to really compress JPEGs with mozjpeg

Today I learnt …

It’s quite unfair, but the JPEG image format has picked up a bad reputation. Google especially has pushed it’s own format, WebP, as an upgrade to JPEG. But with mozjpeg, Mozilla have shown that many of the assumed inadequacies of JPEG images are caused more by unoptimised encoders than the format itself. You can read more at Performance Calendar.

As a quick example, I took this 4896×3264 image and then resized and re-encoded it using libwebp, the reference JPEG encoder libjpeg, and Mozilla’s drop-in replacement for that, mozjpeg.

$ cwebp -resize 800 533 image.jpg -o image.webp
$ convert -resize 800x image.jpg TGA:- | cjpeg -outfile image-libjpeg.jpg -targa
$ convert -resize 800x image.jpg TGA:- | /opt/homebrew/opt/mozjpeg/bin/cjpeg -outfile image-mozjpeg.jpg -targa
EncoderFile size (bytes)Difference

You can see that although the libjpeg file is around 24% larger than the WebP file, the mozjpeg file gets to within 2% of the WebP file. That’s just using the defaults. If I tweak the parameters to mozjpeg a little:

$ convert -resize 800x image.jpg TGA:- | /opt/homebrew/opt/mozjpeg/bin/cjpeg -quant-table 3 -optimize -outfile image-mozjpeg-optim.jpg -targa -smooth 10
EncoderFile size (bytes)Difference
mozjpeg (tweaked)57,790-14.4%

This gives me a JPEG that’s 14.4% smaller than the WebP file. The visual differences between all four re-encoded files is barely noticeable — subjectively I think the JPEG output is sharper, but for the Web there’s really nothing in it.

Now that’s just one example of one file, of course, and I could also tweak the parameters to to the cwebp encoder too, so it’s not to say mozjpeg is always an improvement on cwebp. But it was fun to discover that WebP is neither definitively nor objectively better than JPEG.

Versions used for the comparison:

$ cwebp -version
libsharpyuv: 0.2.0
$ cjpeg -version
libjpeg-turbo version (build 20230208)
$ /opt/homebrew/opt/mozjpeg/bin/cjpeg -version
mozjpeg version 4.1.1 (build 20220815)