Watermarking images with ImageMagick and BASH

Watermarking images with ImageMagick and BASH

Created:30 Oct 2017 21:11:08 , in  Host development

In this article I give a command line script for watermarking JPEG and PNG files with ImageMagick. Primary reason for me to write the script was the need of watermarking a large number of my own graphics files before posting them online as well as watermarking JPEGs and PNGs for various websites quick and effectively.

Prerequisites

My script is called swww_watermark.sh and is written in BASH command language. It is designed for GNU Debian but should also work on other Unix-like operating systems. Under the bonnet it uses ImageMagick. ImageMagick is an open-source graphics editing suite available for both MS Windows and Unix-like operating systems. Make sure the suite is installed and patched properly (see a note on security below) on your system before running the script.

Watermarking BASH script



#!/usr/bin/env bash

# Script: swww_watermark.sh 
# Description: watermark JPEG and PNG images in a directory
# Author : Sylwester Wojnowski
# WWW : wojnowski.net.pl 

PICS_DIR='pics/' # default directory for images to watermark
PICS_EXT='jpg' # default extension of files to watermark
WMARK_PIC='watermark.jpg' # default watermarking image
GRAVITY='NorthWest' # NorthWest, North, NorthEast, West, Center, East, SouthWest, South, SouthEast
GRAVITY_OPTS=(NorthWest North NorthEast West Center East SouthWest South SouthEast)
GEOMETRY_X=0 # ImageMagick geometry x coordinate value
GEOMETRY_Y=0 # ImageMagick geometry y coordinate value

#errors 
ERROR_COMPOSITE_NOT_INST="ImageMagick composite command not available. Install ImageMagick and try again."
ERROR_NON_EXIST_DIR='ERROR: Given Image directory does not exist.'
ERROR_INCORRECT_EXT='ERROR: Unsupported image extension. This script support watermarking jpg and png files.'
ERROR_INCORRECT_X='ERROR: X co-ordinate for geometry option should be an integer.'
ERROR_GEOMETRY_Y='ERROR: Y co-ordinate for geometry option should be an integer.'
ERROR_GRAVITY_SETTING="ERROR: Gravity settings are: $GRAVITY_OPTS_STR"
ERROR_NON_EXIST_WATERMARK_FILE='ERROR: Watermark file does not exist'

# === private === 
GRAVITY_OPTS_STR=$(IFS=,; echo "${GRAVITY_OPTS[*]}")

help(){
SCRIPTNAME=$(basename "$0")
read -r -d '' HP <<EOH
*** $SCRIPTNAME - watermark images in a directory using ImageMagick composite command.

* Synopsis: $SCRIPTNAME [-d directory] [-p extension] [ -g setting ] [ -x co-ordinate ] [ -y co-ordinate ] [ -w filename ] [ -h ] \n
      -d directory - directory with images to watermark, defaults to pics/
      -e extension - extension of image files to watermark, options are jpg,jpeg,png, defaults to jpg
      -g option - imagemagick gravity option, available options are:
         $GRAVITY_OPTS_STR ,defaults to NorthWest
      -x co-ordinate - geometry x co-ordinate, non-negative integer, defaults to 0
      -y co-ordinate - geometry y co-ordinate, non-negative integer, defaults to 0
      -w file - file to use for watermarking images
      -w file - file to use for watermarking images from directory given using -d option, defaults to watermark.jpg
      -h - help message
EOH
printf "\n%s\n" "$HP";
}

bail(){ echo "$1" >&2; help; exit 1; }
prereqs(){ [[ -z $(which composite) ]] && { bail "$ERROR_COMPOSITE_NOT_INST"; };}

validate_input(){
  local OPTIND name
  while getopts "d:e:g:w:x:y:h" name; do
    case "$name" in
      d) # overwrite pics directory
        PICS_DIR="$OPTARG"   
        ;;
      e) # overwrite file extension 
        e_reg='^jpe?g|png$';
        [[ $OPTARG =~ $e_reg ]] && {
          PICS_EXT="$OPTARG"   
        } || { bail "$ERROR_INCORRECT_EXT"; }
        ;;      
      g) # overwrite gravity option
        gr_set=0
        for i in "${!GRAVITY_OPTS[@]}"; do
          [ "$OPTARG" == "${GRAVITY_OPTS[i]}" ] && {
            GRAVITY="$OPTARG"
            gr_set=1
            break;
          }
        done
        (( $gr_set == 0 )) && { bail "$ERROR_GRAVITY_SETTING"; }  
        ;;     
      x) #overwrite geometry x co-ordinate 
        x_reg='^0$|^-?[1-9][0-9]{0,3}$';  
        [[ $OPTARG =~ $x_reg ]] && {
          GEOMETRY_X="$OPTARG"
        } || { bail "$ERROR_INCORRECT_X"; }
        ;; 
      y) #overwrite geometry y co-ordinate
        y_reg='^0$|^-?[1-9][0-9]{0,3}$'; 
        [[ $OPTARG =~ $y_reg ]] && {
          GEOMETRY_Y="$OPTARG"
        } || { bail "$ERROR_INCORRECT_Y"; }
        ;;  
      w) # overwrite watermarking image name
         WMARK_PIC="$OPTARG" 
       ;;
      h|?)
       help; exit 1
       ;;
    esac
  done
  
  [ ! -d "$PICS_DIR" ] && { bail "$ERROR_NON_EXIST_DIR"; }
  [ ! -f "$WMARK_PIC" ] && { bail "$ERROR_NON_EXIST_WATERMARK_FILE"; }
}

watermark(){
  while read -r -d ''; do
    composite -gravity "$GRAVITY" \
     -geometry "+$GEOMETRY_X+$GEOMETRY_Y" "$WMARK_PIC" "$REPLY" "$REPLY"
  done < <(find "$PICS_DIR" -name "*.$PICS_EXT" -print0)  
}

prereqs
validate_input "$@"
watermark

Configuration options

swww_watermark.sh has some configuration options. Among other things, they allow to specify a directory the script should look for images to watermark, a watermark file to use, type of files to watermark, or position of the watermark on the original image.

All the configuration options (each with a short description) are available after typing:


./swww_watermark.sh -h 

in your terminal window.

Use examples

Below are a couple of examples how the script can be used to watermark images.

As the first example, lets watermark all JPEG files in directory pics/ ( which lies in the same directory as swww_watermark.sh), with watermark file called watermark.jpg.


./swww_watermark.sh

Watermarking all PNG files in directory ~/images with watermark /tmp/watermark.png can be done as follows:


./swww_watermark.sh -d ~images/ -e png -w watermark.png

By default, the watermark for each processed image will be placed in top-left corner of the image. Other locations for it can be given by specifying gravity (-g) and geometry(-x,-y) options (These options are described more thoroughly here).


./swww_watermark.sh -g Center

will watermark all JPEG images in pics/ by placing watermark.jpg in their centre.


./swww_watermark.sh -g Center -x 20 -y 40

will place watermark.jpg 20 pixels to the right from the centre and 40 pixels to bottom from the centre of the image being watermarked.

Both, x and y options can also accept negative values, in such a case a shift will take place to the left and top by the number of pixels specified respectively.

A note on security

In year 2016 a number of vulnerabilities have been discovered in the code ImageMagick graphics suite relies upon. Details on the issues and how to mitigate it can be found here and here. You should make sure your installation of ImageMagick is properly patched and configured before trying to manipulate images from distrusted sources, like user downloads, with its commands.

Final thoughts

Watermarking images is a frequent requirement these days. Quite a few high-level programming languages rely upon ImageMagick bindings to perform the task. BASH, a command language, does not depend on any extra code like that. Instead, it enjoys a sort of more direct access to the wealth of commands ImageMagick suite ( and many other CLI programs ) provide. I like this direct link, it simplifies considerably writing scripts like the one presented in this article.

I hope the article has been an interesting read, and the code in it will prove useful to you.

This post was updated on 31 Oct 2017 00:00:40

Tags:  BASH ,  image ,  ImageMagick 


Author, Copyright and citation

Author

Sylwester Wojnowski

Author of the above article, Sylwester Wojnowski, is sWWW admin and owner.He enjoys doing Maths and studying algorithms, writing code in scripting and command languages, Thrash Metal music and playing electric guitar.

Copyrights

©Copyright, 2017 Sylwester Wojnowski. This article may not be reproduced or published as a whole or in parts without permission from the author. If you share it, please give author credit and do not remove embedded links.

Computer code, if present in the article, is excluded from the above and licensed under GPLv3.

Citation

Cite this article as:

Wojnowski, Sylwester. "Watermarking images with ImageMagick and BASH." From sWWW - Code For The Web . https://wojnowski.net.pl//main/index/watermarking-images-with-imagemagick-and-bash