How to shrink and optimize images?

5.7k Views Asked by At

I'm currently using jpegoptim on CentOS 6. It lets you set a quality and file size benchmark. However, it doesn't let you resize the images.

I have 5000 images of all file sizes and dimensions that I want to shrink to a max width and max file size.

For example, I'd like to get all images down to a maximum width of 500 pixels and 50 KB.

How can I shrink and optimize all of these images?

1

There are 1 best solutions below

1
On

You can do this with ImageMagick, but it is hard to say explicitly which way to do it as it depends on whether all the files are in the same directory and also whether you have or can use, GNU Parallel.

Generally, you can reduce the size of a single image to a specific width of 500 like this:

# Resize image to 500 pixels wide
convert input.jpg -resize 500x result.jpg

where input.jpg and result.jpg are permitted to be the same file. If you wanted to do the height, you would use:

# Resize image to 500 pixels high
convert input.jpg -resize x500 result.jpg

since dimensions are specified as width x height.

If you only want to reduce files that are larger than 500 pixels, and not do any up-resing (increasing resolution), you add > to the dimension:

# Resize images wider than 500 pixels down to 500 pixels wide
convert image.jpg -resize '500x>' image.jpg

If you want to reduce the file size of the result, you must use a -define to guide the JPEG encoder as follows:

# Resize image to no more than 500px wide and keep output file size below 50kB
convert image.jpg -resize '500x>' -define jpeg:extent=50KB result.jpg

So, now you need to put a loop around all your files:

#!/bin/bash
shopt -s nullglob
shopt -s nocaseglob

for f in *.jpg; do
    convert "$f" -resize '500x>' -define jpeg:extent=50KB "$f"
done

If you like thrashing all your CPU cores, do that using GNU Parallel to get the job done faster.

Note that if you have a file that is smaller than 500px wide, ImageMagick will not process it so if it is smaller than 500 pixels wide and also larger than 50kB, it will not get reduced in terms of filesize. To catch that unlikely edge case, you may need to run another find afterwards to find any files over 50kB and then run them through convert but without the -resize, something like this:

find . -type f -iname "*.jpg" -size -51200c -exec convert {} -define jpeg:extent=50KB {} \;