Pad images to fit 4 by 6 photo paper bash script using imagemagick

Alec Jacobson

August 16, 2009

weblog/

I was a little dismayed that I couldn't use my previously mentioned applescript to pad images with colors other than black. A shrewd observer will also notice that the Image Events suite resamples when it pads resulting in some annoying re-anti-aliasing. I wrote the following bash script to the same task as the applescript from the command line:
#!/bin/bash

USAGE="Usage: $0 [--replace] [--padcolor=color] ratio imagefile(s)
  ratio              is a float equal to long dimension / short dimension to pad 
                     to fit a 4\"x6\" card, divide 6 by 4 giving ratio = 1.5
  --replace or -f    option to overwrite original images with padded versions,
                     default is to preppend 'pad-[ratio]-' to each naee
  --padcolor= or -c= option to change pad color from default black. Takes a
                     color can be any Imagemagick color or hex color:
                     (See http://www.imagemagick.org/script/color.php)
"
if [ "$#" == "0" ]; then
  echo "$USAGE"
  exit 1
fi

replace=false
if [ "$1" == "--replace" -o "$1" == "-f" ]
then
  echo "Overwriting existing image files..."
  replace=true
  shift
fi

padcolor="black"
if [ `echo "$1" | grep "^\(--padcolor\)\|\(-c\)="` ]
then
  padcolor=`echo "$1" | sed "s/^.*=//"`
  shift
  echo "Using $padcolor as pad color..."
fi

ratio=`echo "$1" | grep "^[0-9]*\.\?[0-9]\+$\|^[0-9]\+\.$"`
if [ "$ratio" == "" ]
then
  echo "$USAGE"
  exit 2
fi
shift
while (( "$#" )); do
  image="$1"
  dir=`dirname "$image"`
  base=`basename "$image"`
  if ! $replace 
  then
    base="pad-$ratio-$base"
  fi
  if wh=`identify -format "%w %h" "$image" 2>/dev/null`
  then
    width=${wh%% *}
    height=${wh#* }
    if [ $height -gt $width ]
    then
      # vertical
      long=`echo "$height/$width > $ratio" | bc -l`
      if [ $long -eq "1" ] 
      then
        # taller than ratio
        newwidth=`echo "$height/$ratio" | bc -l`
        newwidth=`echo "($newwidth+0.5)/1" | bc`
        newheight="$height"
      else
        # shorter than ratio
        newwidth="$width"
        newheight=`echo "$width*$ratio" | bc -l`
        newheight=`echo "($newheight+0.5)/1" | bc`
      fi
    else
      # horizontal
      long=`echo "$width/$height > $ratio" | bc -l`
      if [ $long -eq "1" ] 
      then
        # wider than ratio
        newwidth="$width"
        newheight=`echo "$width/$ratio" | bc -l`
        newheight=`echo "($newheight+0.5)/1" | bc`
      else
        # skinnier than ratio
        newwidth=`echo "$height*$ratio" | bc -l`
        newwidth=`echo "($newwidth+0.5)/1" | bc`
        newheight="$height"
      fi
    fi
    printf "Padding into $base..."
    convert -size "$newwidth"x"$newheight" xc:"$padcolor" .padcanvas.miff
    composite -gravity center "$image" .padcanvas.miff "$dir"/"$base"
    rm .padcanvas.miff
    echo "DONE"
  else
    echo "$image is not a proper image...skipping."
  fi
  shift
done
I have not completely bullet proofed the above but it should get the job done. Here’s the same before and after shots to show what this script does:
OriginalPadded with blackPadded with transparent pixels
Long horizontal before Long horizontal after Long horizontal after
Short horizontal before Short horizontal after Short horizontal after
Long vertical after Long vertical after Long vertical after
Short vertical before Short vertical after Short vertical after
Look closely at the last column, the images are padded with transparent pixels! Could be useful for web posting.