Image Watermarks in Batch

A common need among those who engage in large scale image processing is to assign a watermark of some description to their images. Further, so I have been told, it is preferable to have multiple watermarks that have slightly different kerning depending on whether the image is portrait or landscape. Thus there are two functions to this script, one for separating the mass of images into a directory into whether they are portrait or landscape, and a second to apply the appropriate watermark. The script is therefore structured as follows and witness the neatness and advantages of structured coding, even in shell scripts. I learned a lot from first-year Pascal programming.

#!/bin/bash
separate() { # Separate original files in portrait and landscape directories
# content here
}

apply() { # Apply correct watermark to each directory
# content here
}

main() {
    separate
    apply
}

main
exit

The first function simple compares the width to the length of the image to make its determination. It assumes that the images are correctly orientated in the first place. Directories are created for the two types of files, and the script parses over each file in the directory and determines whether they are portraits or landscapes using the identify utility from ImageMagick and copies (you want to keep the originals) into an appropriate directory. The content of the separate function therefore ends up like this:

separate() { # Separate original files in portrait and landscape directories
mkdir portraits; mkdir landscapes
for item in ./*.jpg
do
  orient=$(identify -format '%[fx:(h>w)]' "$item")
  if [ $orient -eq 1 ] ;
  then
      cp "$item" ./portraits
  else
      cp "$item" ./landscapes
  fi
done
}

The second function goes into each directory and applies the watermark by making use of ImageMagick's composite function, looping over each file in the directory. The file in the directories are overwritten (the $item is input and output) but remember the originals have not been altered. The size of the watermark varies according to the size of the image and each are located in the "southeast" corner of the file. The function assumes a watermark 20 pixels by 20 pixels offset from the bottom left corner and a watermark of 0.1 of the height of the image. These can be changed as desired.

apply() { # Apply correct watermark to each directory
cd portraits
for item in ./*.jpg; do convert "$item" ../watermarkp.png +distort affine "0,0 0,0 %[w],%[h] %[fx:t?v.w*(u.h/v.h*0.1):s.w],%[fx:t?v.h*(u.h/v.h*0.1):s.h]" -shave 1 -gravity southeast -geometry +20+20 -composite "$item" ; done
cd ../landscapes
for item in ./*.jpg; do convert "$item" ../watermarkl.png +distort affine "0,0 0,0 %[w],%[h] %[fx:t?v.w*(u.h/v.h*0.1):s.w],%[fx:t?v.h*(u.h/v.h*0.1):s.h]" -shave 1 -gravity southeast -geometry +20+20 -composite "$item" ; done
}

This file can also be combined with existing scripts for Batch Image Processing. In particular, jpegtran/exiftran, suggested by Michael Deegan, for EXIF rotation flags.

For what it's worth this script took around an hour to put together (mostly research, about 5 minutes coding, and 10 minutes testing and debugging). I suspect it will save readers who use it a great deal of time.