A custom program to watermark images using Image Magick.
15 Jul 2021 This post details my process for applying watermarks to images as fast as possible. I have a TIL post on generating the initial watermark image and then applying that watermark to a batch of images using ImageMagick.
The backstory: I had begun to create a lot of cropped images and portrait orientation photos, and I wanted the watermark size to dynamically adjust to the image size, Also, I schedule many of the photos I share on Twitter with Buffer in a batch, and Buffer’s size limit is 10 MB. So I want to automatically resize any photo that is over 10 MB to under 10 MB.
The result is a little bit of hacky C++ code that I built and then installed, so I can call it from anywhere. Since it isn’t research code, I hard-coded some items in there. Of course, adjust for your own needs! The C++ file and CMakeLists.txt is on Github, amy-tabb/custom-watermark, with my watermark trans_stamp3.png so you have something to play around with.
There is one argument, the input directory. What the program does is read through all the files in the directory, determining if the files are or are not image files. It creates a watermarked copy if the file is an image file, with water-
as the file’s prefix. This allows me to run
custom-watermark --input $PWD
in a directory with sidecar files from editing RAW files. Nothing is lost, only watermarked images created.
The image examples in this post were created using the custom-watermark
program. Original sizes were:
- deer, first image: 4985 x 3323.
- butterfly, second image: 1938 x 2908.
- hummingbird, third image: 3406 x 2272.
and resized smaller to be more web friendly.
Preliminaries:
- C++,
- C++ 17 compiler,
- Cmake project,
- need exiftool.
sudo apt install exiftool
on Ubuntu. - need Image Magick.
sudo apt install imagemagick
on Ubuntu.
C++ code: hardcoded values.
Over in the .cpp file at amy-tabb/custom-watermark, you’ll want to adjust the hardcoded values as needed. They are indicated with
hardcoded item
in the comments.
Maximum filesize
I set the maximum filesize to 10 MB.
// hardcoded item # 1
std::uintmax_t maxfilesize = 10*1000000;
Later, if the filesize of the watermarked file is greater than this maximum, the file is resized down until it is smaller than the maximum.
std::uintmax_t filesize = filesys::file_size(watermarkedPath);
// 1 MB to 1000000 bytes. so
cout << "Current size as a proportion, " << float(filesize)/float(maxfilesize) << endl;
while (filesize > maxfilesize){
...
}
Watermark directory and filename
These paths are for the watermark to apply to the input directory. You’ll want to make this an absolute path if you install.
// hardcoded item # 2
string watermark_directory = "/home/atabb/Pictures/KeepStamps";
// hardcoded item #3
string watermark_filename = "trans_stamp3.png";
Size of the watermark
I empirically (see how I made it sound researchy?) determined what size I wanted the watermark to be relative to the rest of the image. Too big, and it is obnoxious. Too small, you might as well not have include a watermark. Ehh. I think these proportions below work better on Twitter versus on the website, where these proportions might be too small. A note: all of my images have the 3:2 or 2:3 aspect ratio.
// hardcoded item #4
// landscape
if (imageheight < imagewidth){
stamp_width = round(double(imagewidth)*0.12); //(*.12)
stamp_height = round(double(stamp_width)/3.2);
} else {
// portrait
stamp_width = round(double(imagewidth)*0.22);
stamp_height = round(double(stamp_width)/3.2);
}
Where to place the watermark
I place the watermark in the lower right corner. This command puts all of the previous parameters together to get one magical command string, where, hackily, I do a system call to ImageMagick.
// hardcoded item #5, where the watermark will be placed.
command = "composite " + watermark_directory + watermark_filename + " " + filename
+ " -gravity southeast -geometry " + ToString<int>(stamp_width)
+ "x" + ToString<int>(stamp_height) + "+10+10 "
+ read_directory + "water-" + image_names[i];
system(command.c_str());
Final words
Again, the project is at Github: amy-tabb/custom-watermark, and the post with instructions to create your own watermark is here. Happy watermarking!