Shrinking images in batch

I regularly have to reduce the size of digital images. To automatize this, I created a little Bash script, which also considers the orientation (landscape/portrait) of the image:

#!/bin/bash

# This script shrinks all JPEG images in the given input folder and
# stores them in the output folder.
# 
# The maximum length (in pixels) of the longest edge can be set by
# the variable 'maxSize'.
#
# Author: Roland Kluge

maxSize="1000"
originaleImages="input"
smallImages="output"

IFS=$'\n'
for image in $(find $originaleImages -regex .*[jJ][pP][eE]?[gG])
do
  filename=$(basename $image)
  noExtension=${filename%.*}
  newPath="$smallImages/${noExtension}e.jpg"
  
  if [ $(identify -ping -format '%W/%H>1' $image | bc -l) -eq 1 ]; then
    echo "$image is landscape"
    newSize="${maxSize}x"
   else
    echo "$image is portrait"
    newSize="x${maxSize}"
   fi
  convert $image -strip -resize $newSize jpg:$newPath
done

The actual conversion is done with convert, which is part of the ImageMagick suite (for installation instructions, see here).

The option -strip removes all EXIF metadata during conversion and the prefix jpg: ensures that the correct file format is used for the new file.

Edit (2014-11-17): Fix loop condition to cope with file names that contain whitespaces and also to also match JPEG, jpeg,… Thanks, Paul Pell!

2 comments

  1. Hi,

    thanks for your posts, I learned nice tricks =)

    You are using a bad ™ for loop: if you have whitespaces in filenames, it won’t work! Say you have “f 1.txt” in a dir, the for loop will execute twice ;)

    You could use: for i in input/*[jJ][pP][gG]; do if [ -f “$i” ]; then DO_STUFF; fi; done

    Or, if you need find (recursion), you can do it using a function:
    function do_stuff { echo “Arg1: “; }
    export -f do_stuff # to be able to refer to it from find
    find baz -exec bash -c ‘do_stuff “‘{}'”‘ ; # we need to use double quotes (“) in the -c argument, exactly to avoid the whitespace problem

Leave a Reply