LJ Archive

Work the Shell

Easy Watermarking with ImageMagick

Dave Taylor

Issue #237, January 2014

Script auteur Dave Taylor explores smart ways to use ImageMagick and Bash to copyright and watermark images in bulk.

Let's start with some homework. Go to Google (or Bing) and search for “privacy is dead, get over it”. I first heard this from Bill Joy, cofounder of Sun Microsystems, but it's attributed to a number of tech folk, and there's an element of truth to it. Put something on-line and it's in the wild, however much you'd prefer to keep it under control.

Don't believe it? Ask musicians or book authors or film-makers. Now, whether the people who would download a 350-page PDF instead of paying $14 for a print book are hurting sales, that's another question entirely, but the Internet is public and open, even the parts that we wish were not.

This means if you're a photographer or upload images you'd like to protect or control, you have a difficult task ahead of you. Yes, you can add some code to your Web pages that makes it impossible to right-click to save the image, but it's impossible to shut down theft of intellectual property completely in the on-line world.

This is why a lot of professional photographers don't post images on-line that are bigger than low-resolution thumbnails. You can imagine that wedding photographers who make their money from selling prints (not shooting the wedding) pay very close attention to this sort of thing!

Just as people have learned to accept poor video in the interest of candor and funny content thanks to YouTube, so have people also learned to accept low-res images for free rather than paying even a nominal fee for license rights and a high-res version of the photograph or other artwork.

There is another way, however, that's demonstrated by the stock photography companies on-line: watermarking.

You've no doubt seen photos with embedded copyright notices, Web site addresses or other content that mars the image but makes it considerably harder to separate it from its original source.

It turns out that our friend ImageMagick is terrific at creating these watermarks in a variety of different ways, and that's what I explore in this column. It's an issue for a lot of content producers, and I know the photos I upload constantly are being ripped off and reused on other sites without permission and without acknowledgement.

To do this, the basic idea is to create a watermark-only file and then blend that with the original image to create a new one. Fortunately, creating the new image can be done programmatically with the convert program included as part of ImageMagick.

Having said that, it's really mind-numbingly complex, so I'm going to start with a fairly uninspired but quick way to add a watermark using the label: feature. In a nutshell, you specify what text you want, where you want it on the image, the input image filename and the output image filename. Let's start with an image (Figure 1).

Figure 1. Original Image, Kids at a Party

You can get the dimensions and so forth of the image with identify, of course:

$ identify kids-party.png
kids-party.png PNG 493x360 493x360+0+0 8-bit 
 ↪DirectClass 467KB 0.000u 0:00.000

You can ignore almost all of this; it's just the size that you care about, and that's shown as 493x360.

Now, let's use composite to add a simple label:

$ composite label:'AskDaveTaylor.com' kids-party.png \
  kids-party-labelled.png

Figure 2 shows the image with the label applied.

Figure 2. Label Added, No Styling

That's rather boring, although it's effective in a rudimentary sort of way. Let's do something more interesting now, starting by positioning the text centered on the bottom but also adding space below the image for the caption:

$ convert kids-party.png -background Khaki \
 label:'AskDaveTaylor.com' \
 -gravity center -append party-khaki.png

Here I've added a background color for the new text (khaki) and tapped the complicated but darn useful gravity capability to center the text within the new append (appended) image space. Figure 3 shows the result.

Figure 3. Caption against a Khaki Background

I'm not done yet though. For the next example, let's actually have the text superimpose over the image, but with a semi-transparent background.

This is more ninja ImageMagick, so it involves a couple steps, the first of which is to identify the width of the original source image. That's easily done:

width=$(identify -format %w kids-party.png)

Run it, and you'll find out:

$ echo $width
493

Now, let's jump into the convert command again, but this time, let's specify a background color, a fill and a few other things to get the transparency to work properly:

$ convert -background '#0008' -fill white -gravity center \
  -size ${width}x30 caption:AskDaveTaylor.com \
  kids-party.png +swap -gravity south -composite \
  party-watermark.png

I did warn you that it'd be complex, right? Let's just jump to the results so you can see what happened (Figure 4).

Figure 4. Improved Semi-Transparent Label

You can experiment with different backgrounds and colors, but for now, let's work with this and jump to the second part of the task, turning this into a script that can fix a set of images in a folder. The basic structure for this script will be easy actually:

for every image file
   calculate width
   create new watermarked version
   mv original to a hidden directory
   rename watermarked version to original image name
done

Because Linux is so “dot file”-friendly, let's have the script create a “.originals” folder in the current folder so that it's a nondestructive watermark process. Here's the script:

savedir=".originals"
mkdir $savedir

if [ $? -ne 0 ] ; then
  echo "Error: failed making $savedir."
  exit 1
fi

for image in *png *jpg *gif
do
 if [ -s $image ] ; then   # non-zero file size
    width=$(identify -format %w $image)
    convert -background '#0008' -fill white -gravity center \
       -size ${width}x30 caption:AskDaveTaylor.com \
       $image +swap -gravity south -composite new-$image
     mv $image $savedir
     mv new-$image $image
    echo "watermarked $image successfully"
  fi
done

You can see that it translates pretty easily into a script, with the shuffle of taking the original images and saving them in .originals.

The output is succinct when I run it in a specific directory:

watermarked figure-01.png successfully
watermarked figure-02.png successfully
watermarked figure-03.png successfully
watermarked figure-04.png successfully

Easily done.

You definitely can go further with all the watermarking in ImageMagick, but my personal preference is to tap into the reference works that already are on-line, including this useful, albeit somewhat confusing, tutorial: www.imagemagick.org/Usage/annotating.

However you slice it, if you're going to make your images available on-line in high resolution, or if they're unique and copyrighted intellectual property, knowing how to watermark them from the command line is a darn helpful skill.

Dave Taylor has been hacking shell scripts for more than 30 years. Really. He's the author of the popular Wicked Cool Shell Scripts and can be found on Twitter as @DaveTaylor and more generally at www.DaveTaylorOnline.com.

LJ Archive