Batch Watermark Images in Linux

I previously wrote up a post showing how to watermark images in Linux with ImageMagick. Without too much work you can write a script to do batch processing of your images. This way you can watermark a whole directory of images at once.

I’ve written two versions of this script. The first one I’ll show overwrites all of the images in a directory with the watermarked images. This should be done with some degree of caution as there is no way to undo the changes unless you have the files backed up. Save the following script in your ~/bin/ directory and name it wm-ow.

#!/bin/bash

###########################################
# NAME:		wn-ow
# AUTHOR:	Linerd (https://tuxtweaks.com), Copyright 2009
# LICENSE:	Creative Commons Attribution - Share Alike 3.0 http://creativecommons.org/licenses/by-sa/3.0/
#		You are free to use and/or modify this script. If you choose to distribute this script, with or
#		without changes, you must attribute credit to the author listed above.
# REQUIRES:	ImageMagick, coreutils
# VERSION:	1.0
# DESCRIPTION:	A script to add a watermark and overwrite all images in a directory.
#
# This script will watermark all of the images in a directory. Warning! This will overwrite the files.
###########################################

# Initialize variables
WM=$HOME/Documents/Watermark.png  # This is the path to your watermark image
SCALE=50                          # This sets the scale % of your watermark image

# Warning
echo -e "This will overwrite all of the images in this directory."\\n"Are you shure want to continue? {Y/n}"
read REPLY

if
	[ "$REPLY" != "n" ] && [ "$REPLY" != "N" ]
then
	file -i * | grep image | awk -F':' '{ print $1 }' | while read IMAGE
		do
			echo Watermarking $IMAGE
			composite -dissolve 40% -gravity center -quality 100 \( $WM -resize $SCALE% \) "$IMAGE" "$IMAGE"
		done
else
	echo exiting
	exit 0
fi

exit 0

Make sure to make the file executable with:

chmod +x ~/bin/wm-ow

The second version of this script will not overwrite your images. It will create a new file with _wm inserted into the file name. This is the version you should use if you’re not sure about what settings to use in the script. Save the following in ~/bin/ as wm-new.

#!/bin/bash

###########################################
# NAME:		wm-new
# AUTHOR:	Linerd (https://tuxtweaks.com), Copyright 2009
# LICENSE:	Creative Commons Attribution - Share Alike 3.0 http://creativecommons.org/licenses/by-sa/3.0/
#		You are free to use and/or modify this script. If you choose to distribute this script, with or
#		without changes, you must attribute credit to the author listed above.
# REQUIRES:	ImageMagick, coreutils
# VERSION:	1.0
# DESCRIPTION:	A script to add a watermark to all images in a directory.
#		Original images will be retained and new watermarked images will be created.
#
###########################################

# Initialize variables
WM=$HOME/Documents/Watermark.png  # This is the path to your watermark image
SCALE=50                          # This sets the scale % of your watermark image

# Find all image files in current directory and watermark.
file -i * | grep image | awk -F':' '{ print $1 }' | while read IMAGE
	do
		echo Watermarking $IMAGE
		NAME=`echo $IMAGE | cut -f1 -d.`
		EXT=`echo $IMAGE | cut -f2 -d.`
		composite -dissolve 40% -gravity center -quality 100 \( $WM -resize $SCALE% \) "$IMAGE" "${NAME}_wm.${EXT}"
	done
exit 0

Make sure to make it executable with:

chmod +x ~/bin/wm-new

NOTE: In both of the above scripts line 17 defines the location of the file that you want to use as a watermark. Line 18 defines the scale of the watermark in terms of percent.

I’m thinking that these two could be combined into one. I could present an option for the user and use a case statement to choose which routine to run.

17 thoughts on “Batch Watermark Images in Linux

  1. Martin

    does’nt work for me. regardless of which path I use for the watermark graphic, I get an error when running the script that it cant open my watermark.png , no file or directory. i have my file in home/myname/Pictures/watermark.png and this is the path I have entered in the script.

    Reply
  2. Pingback: » Batch watermarking images in Linux

    1. Linerd Post author

      basename requires you to provide the extension you want to strip, so you can’t make it generic for all image types. Perhaps a loop could be written to figure out the correct extension, but it seems like it would be more work than my current code.

      On the other hand, my script assumes that the only ‘.’ in the file name is between the name and the extension, so it’s not perfect either.

      Reply
  3. Pingback: How to make Batch watermark to images in Linux

  4. Surfrock66

    I’m having some issues; i’m completely new to Bash scripts. I’m getting an error:

    shell-init: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory

    Any thoughts?

    Reply
    1. Linerd Post author

      Surfrock66 – did you perhaps have several terminals open to different directories and delete the working directory of one of the other terminals? You might get this message if you try to run the script from a directory that no longer exists. A google search on the error suggests some possible causes.

      I don’t think the error has anything to do with the program itself.

      Reply
  5. Kim Briggs

    “@ Kim – Interesting. I haven’t gotten into perl yet, so I don’t quite follow everything that’s going on. I’m guessing that chomp is a perl specific command?”

    chomp gets rid of the “new line” character that is included when you hit the “Enter/Return” button after submitting data. In this case, the year. The “convert” command is a ImageMagick command (man imagemagick for details).

    Reply
  6. Pingback: Destillat KW34-2009 | duetsch.info - GNU/Linux, Open Source, Softwareentwicklung, Selbstmanagement, Vim ...

  7. Jose_X

    I would change the first script to run only after Y/y. This way if the person types “stop” or “help” or “no” or “” etc, they won’t have to worry.

    BTW, you can avoid being there to type “y” by doing: yes | thescript

    Reply
    1. Linerd Post author

      @ Duane – Nice script. It looks like it could be done a little more efficiently. I like the ls | grep -ic jpg part. That’s a neat trick to count the files. I like your watermark image too. I’ll have to try making one like that in GIMP.

      The composite command should work fine if you just overwrite the file:
      composite -gravity SouthEast $watermark "$i" "$i"
      Then you can skip the rm command to clean up.

      @ Kim – Interesting. I haven’t gotten into perl yet, so I don’t quite follow everything that’s going on. I’m guessing that chomp is a perl specific command?

      @ both – I guess what sets my script apart is the handling of multiple image file types. There’s a lot going on in file -i * | grep image | awk -F':' '{ print $1 }' | while read IMAGE.
      file -i * – lists the files and shows file MIME type.
      grep image – filters the list for image files
      awk -F':' '{ print $1 }' – cuts the file name from the list item (everything before the “:” )
      while read IMAGE – takes the file name output from awk and stores it in $IMAGE

      I tested on a directory with .gif, .jpg, .png, .tiff files. File names with spaces work.

      Reply
  8. Pingback: fsdaily.com

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.