Losslessly Compress JPG Images via Linux Command Line

Although JPG images already utilize lossy compression to reduce file size, this compression is rarely optimized. jpegoptim is a Linux command line utility that can optimize JPG photos, yielding a smaller file size and zero quality loss. The resulting image data is bit-for-bit the exact same as the original, but the files can enjoy a significant reduction in size.

There are a lot of programs and websites that claim to reduce image file size for you, but be careful. Most of these tools will indeed reduce the size of your images, but they work by recompressing the photo, resulting in a marginal (and sometimes quite noticeable) loss of quality. You may not always notice the dip in quality, but it’s there.

The jpegoptim tool works differently. Instead of recompressing an image, it optimizes the Huffman coding that’s used to compress the image data.

Some of your JPG files may already be optimized, but it’s a rare occurrence. Most devices (cell phones, cameras) will not compress your images optimally, because it takes extra time (more CPU power). The device will instead opt for faster compression, which makes your files a little bit bigger than they need to be. This fast compression frees up your device more quickly, allowing you to continue snapping photos.

In this guide, we’ll show you how to install the jpegoptim tool on Linux, and go over some example commands to help you learn how to use it on your own pictures.

Is jpegoptim Really Lossless?

Our photos are valuable, and we wouldn’t want them to lose quality that we can never get back. To verify that jpegoptim isn’t touching the photo data itself, we tried optimizing a photo and then used graphicsmagick to compare it to the original.

$ cp canyon.JPG canyon-optim.JPG
$ jpegoptim canyon-optim.JPG
canyon-optim.JPG 7552x3818 24bit N Exif ICC  [OK] 10961114 --> 10219177 bytes (6.77%), optimized.
$ gm compare -metric mse canyon.JPG canyon-optim.JPG
Image Difference (MeanSquaredError):
           Normalized    Absolute
          ============  ==========
     Red: 0.0000000000        0.0
   Green: 0.0000000000        0.0
    Blue: 0.0000000000        0.0
   Total: 0.0000000000        0.0
$ du -h canyon*
9.8M    canyon-optim.JPG
11M     canyon.JPG

As you can see, our JPG image was compressed 1.2MB (6.77%), and the optimized image is identical to the original. Even the photo’s metadata is left intact.

Install jpegoptim on Linux

Install the jpegoptim tool with your system’s package manager by using the appropriate command below.

Ubuntu, Debian, and Linux Mint:

$ sudo apt install jpegoptim

Fedora, AlmaLinux, CentOS, and RHEL:

$ sudo dnf install jpegoptim

Arch Linux and Manjaro:

$ sudo pacman -S jpegoptim

jpegoptim Command Examples

Now that it’s installed, check out some of the command examples below to learn how to use it.

1. To optimize an image in-place, simply pass the name of the JPG file to jpegoptim. Of course, you can also use wildcards or specify multiple files in your command, which works well if you have a whole directory of images to optimize.

$ jpegoptim image.jpg
image.jpg 4032x3024 24bit N Exif ICC  [OK] 3742826 --> 3705792 bytes (0.99%), optimized.

2. If you don’t want jpegoptim to overwrite the original files, use the -d option and specify a directory where you’d like the optimized files to be saved to.

$ jpegoptim *.jpg -d /home/linuxnightly/optimized

3. To reduce size even further, you can pass the --strip-exif option, which will clear Exif metadata from the file, like the date it was taken, with what device, GPS location, etc. Be careful, because sometimes this information is nice to have. But if you’re sharing the picture online, Exif data can be a privacy concern anyway.

$ jpegoptim image.jpg --strip-exif

4. The -t (totals) option will give us a summary of the optimization when jpegoptim is finished running. This is nice when running the command on a bunch of files. Here’s an example where I run jpegoptim on the last 150 photos I’ve taken with my iPhone.

$ jpegoptim *.JPG -t
Average compression (150 files): 6.17% (89681k)

That’s almost 90 MB savings across 150 files!

5. To execute jpegoptim on all images recursively, we can use the find command. The following command will optimize all *.jpg (and *.JPG) files in your current directory, as well as all of those in any subdirectories.

$ find . -type f \( -iname "*.jpg" \) -exec jpegoptim {} \;

6. If you have a ton of JPG files, it’s possible to speed up the find command shown above by using xargs and multiple CPU cores. Take the following example where we pass 10 JPG files to jpegoptim simultaneously, and utilize 4 CPU cores via xargs.

$ find . -type f \( -iname "*.jpg" \) -print0 | xargs -0 -n 10 -P 4 jpegoptim

7. One last thing to note. If you have an image that’s already been optimally compressed (again, it’s rare), jpegoptim will just skip it. You may see something like the output below when that happens.

image.JPG 4032x3024 24bit N Exif ICC JFIF  [OK] 3915810 --> 3915810 bytes (0.00%), skipped.

That should be all you need to know to get the most out of jpegoptim. There’s quite a bit of documentation in the man page if you want to read up on some of its other options.

$ man jpegoptim

You may also be interested in how to use optipng, a similar command line tool that can optimize PNG files.

Leave a Comment

Your email address will not be published. Required fields are marked *