I recently discussed mod_ext_filter, a loadable module used with Apache. It allows you to easily process your content through an external program before it’s passed onto the user’s web browser. I mentioned using mod_ext_filter as a way to automatically add watermarks to images on a website. After receiving a bit of interest in how to do this, I decided to write a step-by-step HOWTO.
Before you start
First determine whether dynamically adding watermarks using mod_ext_filter is really the best option for your project. If you have a fixed set of images that never change, it would probably make more sense to add the watermark using a photo editing program before you upload them to the site. This would eliminate the overhead of having to run the filter everytime someone requests the image. If you’re interested in marking images that are being uploaded to the site by users via a web interface, using an image manipulation library within your scripting environment would be more efficient. (For PHP and most other languages, the obvious choice is GD). Having said that, some cases that using mod_ext_filter would be appropriate would be:
- Users directly upload images via FTP, but the images are accessed via HTTP (Apache)
- A webcam or IP security camera regularly uploads images to the server and people view the images via a website.
- Non-technical people upload images via a CMS that need to be automatically watermarked, and you have no way/desire to modify the CMS.
With that in mind, the only two technical requirements for this project is having root access on your Apache server and having “composite.” Unlike mod_rewrite, mod_ext_filter cannot be run from within an .htaccess file. Composite is a small utility that is part of the ImageMagick graphics manipulation suite. Most distros ship with this installed, but if yours doesn’t and it isn’t available via your favorite package manager, you can always download and compile the source.
Manipulating the images
Composite simply overlays one image ontop of another, allowing the transparency to be adjusted. You could get fancy and create a dynamically-generated watermark from scratch by using the other binaries in the ImageMagick suite. However, for this project I’m just going to use something I put together in Photoshop in 30 seconds.
The ultra-fancy watermark is simply a GIF on a transparent background:
And our obligatory kitten picture (It’s Maynard, of course! All together now….awwww):
Having both these images on the webserver, we could now easily use composite like so:
/usr/bin/composite -gravity SouthEast -watermark 20.0 watermark.gif maynard.jpg watermarked.jpg
Which gives us the watermark in the lower-right corner at 20% opacity:
Looks good, but we actually want to do is add the watermark to the image in real-time, when it’s sent to the web browser. For that, we need to use some mod_ext_filter voodoo.
Using composite with mod_ext_filter
Now that I’ve figured out how I want the watermark to look, I need to create a new directory to store the images that will be automatically watermarked. Since I normally store images in an “/images” directory off the root, we’ll just keep things simple and create a new subdirectory off of “/images” named “/watermarked”. Into this directory I’ll upload all the files that I want the watermark automatically applied.
Keep in mind that the image files themselves on the server aren’t affected since Apache applies the watermark on-the-fly when the user’s browser requests the image. Depending on what you’re trying to accomplish, this can be good or bad. It increases the server load and, depending on how much traffic you get, may add a noticable delay. However this is also a very flexible solution that doesn’t modify any of the original images. A good compromise would be to implement some type of caching system and/or write a custom module in C using the Apache API, but that’s a bit beyond the scope of this project.
Next I’ll modify Apache’s config file, http.conf, to define the filter:
<IfModule mod_ext_filter.c> ExtFilterDefine watermark mode=output intype=image/jpeg cmd="/usr/bin/composite -gravity SouthEast -watermark 20.0 /var/www/html/mysite/images/watermarked/watermark.gif - -" </IfModule>
(Make sure that the “ExtFilterDefine” directive is all on one line in the config file, else Apache will bomb when you try to restart it.) You’ll notice that the this is pretty much the same command that I used eariler when I was testing the watermark. The only differences are that I’m using an absolute filename for my watermark image and that my input and output filenames have been replaced with two dashes (”- -”). The dashes are the key to this whole trick. They tell composite to use STDIN for the input file, and STDOUT for output. The “intype” is also important. It specifies which MIME type Apache will use with this filter. Trying to stuff a “text/html” document through composite isn’t likely to work all that well.
Next, we need to tell Apache the location of the files that we want to be processed by the filter. The most common way to do this is with a Location container:
<Location /images/watermarked> SetOutputFilter watermark </Location>
This simply directs Apache to run any files located in “/images/watermarked” through the “watermark” filter that was defined earlier. The filter will then check to ensure that the MIME type matches, processes the requested JPEG through composite, and output the result to the browser. That’s about all there is to it… restart Apache and you should be good to go!
If you found this tip useful, please add a comment below. It would be interesting to know how people are using this idea. Thanks!
P.S. Make sure that your installation of Apache is configured to load mod_ext_filter.c. Elsewise the filter will silently fail and probably drive you nuts for an hour or two. The line “LoadModule ext_filter_module modules/mod_ext_filter.so” needs to be present somewhere near the top of http.conf.