Optimizing your images can feel like black magic sometimes. The safest JPG compression is lossless meaning no quality loss (guide), lossy compression has far superior space savings. This guide will show you how to batch optimize JPG images using lossy compression with jpeg-recompress from jpeg-archive on Linux.
In this guide I am batch optimizing 37000 images on an Ubuntu 16.04 Linux VPS from Vultr.
Back up your images first before attempting any optimizations!
If you want to get a batch of test images you can find some here Test images here.
Potential Savings Demo
I chose this sunset image, the original image was 6.3 MB.
Optimized it is 1 MB, ~ 20% of its original size!
I performed this lossy compression with jpeg-compress
jpeg-recompress --quality medium --method smallfry --min 40 hires.jpg hires.jpg
jpeg-recompress does some test compressions and analyses to see if the quality difference is noticeable before choosing an appropriate size.
Overall 5073
kilobytes were saved 🙂
Metadata size is 20kb
smallfry at q=67 (40 - 95): 95.344597
smallfry at q=81 (68 - 95): 99.582062
smallfry at q=88 (82 - 95): 103.033356
smallfry at q=84 (82 - 87): 100.918098
smallfry at q=86 (85 - 87): 101.932304
Final optimized smallfry at q=87: 100.375671
New size is 21% of original (saved 5073 kb)
Let’s get started.
Checking Initial Size
Check the initial size of your image folder
du -sh foldername
For example, before optimization the folder was 18 GB
18G uploads
Optimize JPG Lossy Linux with jpeg-recompress
Install mozjpeg dependencies first
sudo apt-get update
sudo apt-get install build-essential autoconf pkg-config nasm libtool git gettext libjpeg-dev -y
Build mozjpeg, the latest tar.gz can be found here which you can replace below in the wget
line.
cd /tmp
wget https://github.com/mozilla/mozjpeg/releases/download/v3.1/mozjpeg-3.1-release-source.tar.gz -O mozjpeg.tar.gz
tar -xf mozjpeg.tar.gz
cd mozjpeg
autoreconf -fiv
./configure --with-jpeg8 --prefix=/usr
make
sudo make install
Install jpeg-recompress with these commands, make sure you have the bzip2
package.
sudo apt-get install bzip2
cd /tmp
wget https://github.com/danielgtaylor/jpeg-archive/releases/download/2.1.1/jpeg-archive-2.1.1-linux.tar.bz2 -O jpeg-archive.tar.bz2
tar -xf jpeg-archive.tar.bz2
sudo cp jpeg-recompress /usr/bin/jpeg-recompress
sudo chmod 755 /usr/bin/jpeg-recompress
Now the required dependencies are installed we can start automating the lossy compression of tons of jpeg files.
Using jpeg-archive to Lossy Compress JPEGs
First we are going to run some tests on the images to verify the quality is OK, then batch optimize.
The basic command for lossy jpeg compression specifies a --quality
, other qualities exist like high
and veryhigh
jpeg-recompress --quality medium --method ssim image.jpg output.jpg
Output
Metadata size is 0kb
smallfry at q=77 (60 - 95): 98.259766
smallfry at q=86 (78 - 95): 103.205048
smallfry at q=81 (78 - 85): 99.176430
smallfry at q=83 (82 - 85): 100.903015
smallfry at q=84 (84 - 85): 101.598312
Final optimized smallfry at q=85: 99.523018
New size is 71% of original (saved 78 kb)
You can also specify the minimum quality allowed with --min
and jpeg-compress will do comparisons to ensure the best compression ratio without losing quality.
This means if you set --min
to 40 jpeg-recompress will only save the image at that quality level after testing other quality levels and analyzing the results.
I had good results with the smallfry
method so I am using that here.
jpeg-recompress --quality high --method smallfry --min 60 image.jpg image.jpg
Compressing an image to 12% of its original size without noticeable quality loss is pretty awesome.
Metadata size is 56kb
smallfry at q=77 (60 - 95): 102.386467
smallfry at q=68 (60 - 76): 101.549133
smallfry at q=72 (69 - 76): 101.127449
smallfry at q=74 (73 - 76): 101.716339
smallfry at q=75 (75 - 76): 101.718018
Final optimized smallfry at q=76: 100.795944
New size is 12% of original (saved 2228 kb)
If you want to be extra accurate but slower you can add the --accurate
flag
jpeg-recompress --quality high --accurate --method smallfry --min 60 image.jpg image.jpg
If you having thousands of images, it’s a good idea to use screen to run the optimizations.
Screen will ensure the batch command keeps on running even if your SSH session is terminated.
sudo apt-get install screen
Create a new screen session
screen
To batch optimize all of your JPGs to lossy versions in a specific folder use the command below.
The find command does recursive searching so all subfolders with images will be processed.
Make sure to adjust the quality
and min
flags based on your previous compression trials
find /var/www/wp-bullet.com/wp-content/uploads -type f -iname '*.jpg' -exec jpeg-recompress --quality medium --min 60 --method smallfry \{} \{} \;
Detach the screen with Ctrl+A and pressing D (detach).
You can use the top
command and look for jpegoptim processes once in a while.
Reattach the screen like so
screen -r
Now you can strip EXIF data as well for additional savings.
Stripping EXIF Data with exiftool
Exiftool is written in perl and will strip metadata out of your images
sudo apt install exiftool
Removing exif data from a single image is done with the command below
By default a backup is created with the extension jpg_original
If you just want to overwrite the images, use the -overwrite_image
flag
exiftool -overwrite_original -all= image.jpg
This command will remove all of the EXIF data from all JPGs and replace the originals
find /var/www/wp-bullet.com/wp-content/uploads -type f -iname "*.jpg" -exec exiftool -overwrite_original -all= \{} \;
Now it is time to check how much space was saved.
Check Space Savings
Recheck your image folder size
du -sh foldername
Hope the savings were significant
11G uploads
That is almost a 50% savings without a noticeable quality loss of the JPEG images.
Sources
Mozjpeg
Remove exif Metadata
Remove exif without Recompressing JPEG
Reuse found file name in bash
How does jpeg-recompress compare to jpegoptim? The latter does compress and strip exif data.
jpeg-recompress should be more aggressive and get better results
Thank you
Hi Pea, are you still getting this error? I used this recently and didn’t so just want to make sure!
Thanks man! awesome tutorial. I lost a lot of weigh!