Thursday, May 22, 2008

Put watermark on images using PHP

If you are a professional or a newbie photographer you will probably want to protect your photos from being stolen and used for free. Using PHP you can create different types of watermarks on all of your images. I am going to show you a way how to dynamically put a text messages on your images. What you need is a JPG image file and a font file used for generate the watermark message. I am going to use arial font which you can also download.

Below you can find a watermarkImage() image function which takes 3 parameters ($SourceFile, $WaterMarkText, $DestinationFile) and creates an watermarked image from the source image specified. The first parameter - $SourceFile - is the full server path to the JPG image that you are going to watermark. The second one - $WaterMarkText - is the text message that you want to use for the watermark. And the last parameter - $DestinationFile - can either be blank or full server path to a new file which will be the source file with watermark text on it. What this function does is to read the source file, then create a new image object (using the imagecopyresampled() function). Then using the Arial.ttf font file and the imagettftext() function it writes the WaterMarkText onto the image. The last IF statement checks if it should save a new watermarked file or should just display it on the screen.

function watermarkImage ($SourceFile, $WaterMarkText, $DestinationFile) {
list($width, $height) = getimagesize($SourceFile);
$image_p = imagecreatetruecolor($width, $height);
$image = imagecreatefromjpeg($SourceFile);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $width, $height, $width, $height);
$black = imagecolorallocate($image_p, 0, 0, 0);
$font = 'arial.ttf';
$font_size = 10;
imagettftext($image_p, $font_size, 0, 10, 20, $black, $font, $WaterMarkText);
if ($DestinationFile<>'') {
imagejpeg ($image_p, $DestinationFile, 100);
} else {
header('Content-Type: image/jpeg');
imagejpeg($image_p, null, 100);
};
imagedestroy($image);
imagedestroy($image_p);
};
?>

You need to download the arial.ttf file and upload it on your server. Then create a new PHP file and copy and paste the above function in it. Next 4 lines are used to set the Source file, Watermark text message and Destination file. If you want to just display the watermarked image you need to leave the $DestinationFile variable empty ($DestinationFile=''; ). Also please make sure that for source file and destination file you include the full server path and the image file name. If you want to change the position of the watermark message on your images you can chage that line imagettftext($image_p, $font_size, 0, 10, 20, $black, $font, $WaterMarkText);

$SourceFile = '/home/user/www/images/image1.jpg';
$DestinationFile = '/home/user/www/images/image1-watermark.jpg';
$WaterMarkText = 'Copyright phpJabbers.com';
watermarkImage ($SourceFile, $WaterMarkText, $DestinationFile);
?>

Protecting Your Images with PHP Watermarks

As an amateur photographer, I've been looking for practical ways to display my work as well as protect them from potential copyright infringement. There are a hundred ways to superimpose a watermark on an image, but this requires a process of doing that to each of your images before you place them on your website. Being the lazy fellow that I am, I was seeking a way for this to occur on-the-fly without me having to do anything but scale my preview/thumbnail images (which I do automatically with my gallery software).

I investigated various ways to use CGI to handle this, which is an easy way to do it, but it can lead to unweidly URLs. A simple method might be to link to is such as this:

Basically, you're passing the CGI the file you want to have watermarked and the .cgi does its thing, printing the header "Content-type: image/jpeg" and then the JPEG data to standard out. I would have to come up with a way to have the CGI do this watermarking automatically. It would work, but its inelegant and makes for ugly URLs. Close, but no cigar.

Another method I came up with was using PHP to do a similar function, instead of using CGI, I would use PHP's internal image manipulation routines to generate watermarked image. Unfortunately, the URL would essentially be the same:

Then it dawned on me that because my URLs for this would be fairly consistent, why couldn't I use Apache's Mod_Rewrite module to automatically convert my normal image source tags into the php URL and mask this from the browser?

This method would get me two things:

1) The URL for the image would be normal, such as
2) Any direct requests for the image would result in a watermarked image

So if a person tried to do something like:

wget http://www.mysite.com/image/statue.jpg

They would be served up the watermarked image, despite the fact that the original statue.jpg on the server is unmodified!

The PHP script that watermarks the image

The PHP script, which I call "wm.php" that I use for watermarking was written by "thunder", but was modified with some pathing enhancements by myself. There are only a few variables needed to be changed in the script, the base directory of your HTML and the name of the watermark image you wish to use, which should be located in that base directory.

Setting up Apache and Mod_Rewrite to "mask" the PHP


Mod_rewrite can be configured in your server's httpd.conf or your local .htaccess. If you don't have access to httpd.conf, modifying your .htaccess is your only alternative.

Lets say my URL is something like this:

http://www.bigisp.com/users/johndoe/index.html

Basically, the rule is pretty straight forward:

RewriteEngine on
RewriteBase /johndoe
RewriteRule ^(watermarked.*)/(.*\.[jJ].*)$ /~liem/wm.php?p=$1&i=$2

I'm using the RewriteBase directive here because all of my documents and images are based out of the /johndoe/ directory.

Because I won't want all of the images on my site watermarked, I only put the images I want to be watermarked in the "watermarked" subdirectory. The path and filename information are passed to the wm.php script so that they're properly handled.


No comments: