Using mozjpeg to Create Efficient JPEGs ✩ Mozilla Hacks – the Web developer blog

The mozjpeg project recently released version 2.1. It aims to improve the efficiency of JPEG encoding over existing encoders while maintaining compatibility with the vast majority of existing decoders.

I’d like to explain how you can use this software to reduce the size of your JPEGs. Specifically, I’m going to go over usage of mozjpeg’s cjpeg command line utility.

Building mozjpeg

There are no official mozjpeg binaries available, so you’ll have to build the project from source. Do this by downloading the source code for the latest release and following the instructions in the file BUILDING.txt.

Building on Linux and OS X is quite easy. Things are a little more complicated on Windows, but it’s still relatively easy. The mozjpeg project is considering providing binary releases in the future.

When you build mozjpeg you’ll produce a command line tool called cjpeg. This is the encoding program that comes with mozjpeg. The decoder is called djpeg.

Input Image Formats

The cjpeg tool is capable of handling the following input file types: targa, bmp, ppm, and jpg.

The ability to take JPEG files as input is a new feature in mozjpeg which doesn’t yet exists in the cjpeg tools provided by other projects. It was added to make re-compression workflows easier. Instead of converting JPEGs to BMP or something else and then re-encoding them, you can just pass the JPEG directly to the cjpeg encoder.

If you want to create a JPEG from a file type not supported by cjpeg, take a look at the ImageMagick tools. They include a command-line utility called convert that can convert back and forth from many types of images.

Basic Usage of the cjpeg Command Line Tool

Most people who use mozjpeg’s cjpeg use it in its simplest form:

$ cjpeg -quality 80 foo.bmp > bar.jpg

This will create a JPEG called “foo.jpg” from the “foo.bmp” input file at quality level 80. cjpeg directly emits the contents of the resulting JPEG file, so if you want to write it to disk, which you probably do, you’ll need to pipe the results to a file with ‘>‘.

Selecting a Quality Level

Quality can range from 0 at the low end to 100 at the high end. Most people will want to pick quality a value somewhere between 60 and 90. You’ll want to use the lowest value that still produces and image at a quality you’re happy with, because lower values will produce images with smaller file sizes.

The following image shows an original image as well as the same image encoded at five different quality levels with mozjpeg’s cjpeg. Click on it to enlarge.

JPEG Quality Comparison

Here are the image files one-by-one:

(Image courtesy of Soulmatesphotography, via Wikimedia, Creative Commons Attribution-Share Alike 3.0 Unported License)

Do some experimenting here. Lots of people don’t, and they miss out on significant reductions in file size. Their thinking is often something along the lines of “80 seems like a good compromise, and I hear that’s what most people do, so I’ll do that.” If you can’t tell the difference between an image at quality 77 vs 80, and you’re using 80, you’re missing out on significant file size savings at no cost to you in terms of quality.

Progressive vs. Baseline JPEGs

The mozjpeg version of cjpeg produces progressive JPEGs by default because their file sizes tend to be about 4% smaller than baseline JPEGs. Progressive JPEGs can appear at full size but blurry at first, and then progress to full resolution as the image downloads. Baseline JPEGs simply load from top to bottom.

Baseline:
jpeg-baseline

Progressive:
jpeg-progressive
(Image courtesy of Soulmatesphotography, via Wikimedia, Creative Commons Attribution-Share Alike 3.0 Unported License)

If you want to produce a baseline JPEG, you can do so like this:

$ cjpeg -baseline -quality 80 foo.bmp > bar.jpg

Targeting Metrics

A cool feature of mozjpeg’s cjpeg is that you can optimize for any of four specific quality metrics: PSNR, PSNR-HVS-M, SSIM, and MS-SSIM. These metrics are algorithms that calculate the quality of an image compared to the original. More scientifically, this is often referred to as a distortion rate.

These algorithms differ in how they define quality, so optimizing for one metric can hurt performance on another. See the July 2014 lossy compressed images study from Mozilla for many example of what this looks like.

mozjpeg tunes for PSNR-HVS-M by default, because tuning for this does pretty well on all metrics.

If you or your organization have decided that you trust a particular metric more than the others, you can tell mozjpeg’s cjpeg tool about your preference and it will tune for that metric.

Conclusion

Hopefully at this point you know enough to confidently start making use of mozjpeg to optimize your JPEGs. If you run into any issues, please report them on mozjpeg’s github issue tracker.