Share/Bookmark

Featured Posts

SharePoint Ticker Web Part from Existing Data Ever wanted to create a ticker in SharePoint without having to buy the $99 add-on from Microsoft, well here's the code: Simply create a new Web Part using the 'Content Editor' and open the 'Source Editor...'...

Read more

Sony E3 Prediction 2010 With E3 upon us in the coming weeks, and Sony keeping tight lipped about their schedule I think it's time we started predicting the outcome, the announcements and surprises with educated and industry sector...

Read more

Sony E3 Prediction 2010 With E3 upon us in the coming weeks, and Sony keeping tight lipped about their schedule I think it's time we started predicting the outcome, the announcements and surprises with educated and industry sector...

Read more

Whats next for Nintendo? Today I noticed that Nintendo have had falling profits for 2010 and predict even less sales for next year. The Wii 2 hasn`t been officially announced and from what I can see is not really on the radar....

Read more

7 Great Free Android Apps The Android mobile operating system is both fast, reliable and can do everything that the Apple OS can and a little more (all for normally a fraction of the price.) plus it supports Flash and soon Flash...

Read more

Add a Watermark to Images on the Fly

Posted by matthew | Posted in Tutorial | Posted on 27-11-2009

Tags: ,

2

Adding a watermark to an image is quite easy with PHP and has many applications, such as branding or copy protection. So after the jump see just how easy it is, and let us know your thoughts.

First of make a page called “watermark.php” and paste the following code into it:

<?php
class watermark{
# given two images, return a blended watermarked image
function create_watermark( $main_img_obj, $watermark_img_obj, $alpha_level = 100 ) {
$alpha_level = 100; # convert 0-100 (%) alpha to decimal
# calculate our images dimensions
$main_img_obj_w = imagesx( $main_img_obj );
$main_img_obj_h = imagesy( $main_img_obj );
$watermark_img_obj_w = imagesx( $watermark_img_obj );
$watermark_img_obj_h = imagesy( $watermark_img_obj );
# determine center position coordinates
$main_img_obj_min_x = floor( ( $main_img_obj_w / 2 ) - ( $watermark_img_obj_w / 2 ) );
$main_img_obj_max_x = ceil( ( $main_img_obj_w / 2 ) + ( $watermark_img_obj_w / 2 ) );
$main_img_obj_min_y = floor( ( $main_img_obj_h / 2 ) - ( $watermark_img_obj_h / 2 ) );
$main_img_obj_max_y = ceil( ( $main_img_obj_h / 2 ) + ( $watermark_img_obj_h / 2 ) );
# create new image to hold merged changes
$return_img = imagecreatetruecolor( $main_img_obj_w, $main_img_obj_h );
# walk through main image
for( $y = 0; $y < $main_img_obj_h; $y++ ) {
for( $x = 0; $x < $main_img_obj_w; $x++ ) {
$return_color = NULL;
# determine the correct pixel location within our watermark
$watermark_x = $x - $main_img_obj_min_x;
$watermark_y = $y - $main_img_obj_min_y;
# fetch color information for both of our images
$main_rgb = imagecolorsforindex( $main_img_obj, imagecolorat( $main_img_obj, $x, $y ) );
# if our watermark has a non-transparent value at this pixel intersection
# and we're still within the bounds of the watermark image
if ($watermark_x >= 0 && $watermark_x < $watermark_img_obj_w &&
$watermark_y >= 0 && $watermark_y < $watermark_img_obj_h ) {
$watermark_rbg = imagecolorsforindex( $watermark_img_obj, imagecolorat( $watermark_img_obj, $watermark_x, $watermark_y ) );
# using image alpha, and user specified alpha, calculate average
$watermark_alpha = round( ( ( 127 - $watermark_rbg['alpha'] ) / 127 ), 2 );
$watermark_alpha = $watermark_alpha * $alpha_level;
# calculate the color 'average' between the two - taking into account the specified alpha level
$avg_red = $this->_get_ave_color( $main_rgb['red'],$watermark_rbg['red'],$watermark_alpha );
$avg_green = $this->_get_ave_color( $main_rgb['green'],$watermark_rbg['green'],$watermark_alpha );
$avg_blue = $this->_get_ave_color( $main_rgb['blue'],$watermark_rbg['blue'],$watermark_alpha );

# calculate a color index value using the average RGB values we've determined
$return_color = $this->_get_image_color( $return_img, $avg_red, $avg_green, $avg_blue );
# if we're not dealing with an average color here, then let's just copy over the main color
} else {
$return_color = imagecolorat( $main_img_obj, $x, $y );
} # END if watermark
# draw the appropriate color onto the return image
imagesetpixel( $return_img, $x, $y, $return_color );
} # END for each X pixel
} # END for each Y pixel
# return the resulting, watermarked image for display
return $return_img;
} # END create_watermark()
# average two colors given an alpha
function _get_ave_color( $color_a, $color_b, $alpha_level ) {
return round( ( ( $color_a * ( 1 - $alpha_level ) ) + ( $color_b * $alpha_level ) ) );
} # END _get_ave_color()
# return closest pallette-color match for RGB values
function _get_image_color($im, $r, $g, $b) {
$c=imagecolorexact($im, $r, $g, $b);
if ($c!=-1) return $c;
$c=imagecolorallocate($im, $r, $g, $b);
if ($c!=-1) return $c;
return imagecolorclosest($im, $r, $g, $b);
} # EBD _get_image_color()
} # END watermark API
?>
<?php

class watermark{

# given two images, return a blended watermarked image

function create_watermark( $main_img_obj, $watermark_img_obj, $alpha_level = 100 ) {

$alpha_level /= 100; # convert 0-100 (%) alpha to decimal

# calculate our images dimensions

$main_img_obj_w = imagesx( $main_img_obj );

$main_img_obj_h = imagesy( $main_img_obj );

$watermark_img_obj_w = imagesx( $watermark_img_obj );

$watermark_img_obj_h = imagesy( $watermark_img_obj );

# determine center position coordinates

$main_img_obj_min_x = floor( ( $main_img_obj_w / 2 ) - ( $watermark_img_obj_w / 2 ) );

$main_img_obj_max_x = ceil( ( $main_img_obj_w / 2 ) + ( $watermark_img_obj_w / 2 ) );

$main_img_obj_min_y = floor( ( $main_img_obj_h / 2 ) - ( $watermark_img_obj_h / 2 ) );

$main_img_obj_max_y = ceil( ( $main_img_obj_h / 2 ) + ( $watermark_img_obj_h / 2 ) );

# create new image to hold merged changes

$return_img = imagecreatetruecolor( $main_img_obj_w, $main_img_obj_h );

# walk through main image

for( $y = 0; $y < $main_img_obj_h; $y++ ) {

for( $x = 0; $x < $main_img_obj_w; $x++ ) {

$return_color = NULL;

# determine the correct pixel location within our watermark

$watermark_x = $x - $main_img_obj_min_x;

$watermark_y = $y - $main_img_obj_min_y;

# fetch color information for both of our images

$main_rgb = imagecolorsforindex( $main_img_obj, imagecolorat( $main_img_obj, $x, $y ) );

# if our watermark has a non-transparent value at this pixel intersection

# and we're still within the bounds of the watermark image

if ($watermark_x >= 0 && $watermark_x < $watermark_img_obj_w &&

$watermark_y >= 0 && $watermark_y < $watermark_img_obj_h ) {

$watermark_rbg = imagecolorsforindex( $watermark_img_obj, imagecolorat( $watermark_img_obj, $watermark_x, $watermark_y ) );

# using image alpha, and user specified alpha, calculate average

$watermark_alpha = round( ( ( 127 - $watermark_rbg['alpha'] ) / 127 ), 2 );

$watermark_alpha = $watermark_alpha * $alpha_level;

# calculate the color 'average' between the two - taking into account the specified alpha level

$avg_red = $this->_get_ave_color( $main_rgb['red'],$watermark_rbg['red'], $watermark_alpha );

$avg_green = $this->_get_ave_color( $main_rgb['green'],$watermark_rbg['green'],$watermark_alpha );

$avg_blue = $this->_get_ave_color( $main_rgb['blue'],$watermark_rbg['blue'],$watermark_alpha );

# calculate a color index value using the average RGB values we've determined

$return_color = $this->_get_image_color( $return_img, $avg_red, $avg_green, $avg_blue );

# if we're not dealing with an average color here, then let's just copy over the main color

} else {

$return_color = imagecolorat( $main_img_obj, $x, $y );

} # END if watermark

# draw the appropriate color onto the return image

imagesetpixel( $return_img, $x, $y, $return_color );

} # END for each X pixel

} # END for each Y pixel

# return the resulting, watermarked image for display

return $return_img;

} # END create_watermark()

# average two colors given an alpha

function _get_ave_color( $color_a, $color_b, $alpha_level ) {

return round( ( ( $color_a * ( 1 - $alpha_level ) ) + ( $color_b * $alpha_level ) ) );

} # END _get_ave_color()

# return closest pallette-color match for RGB values

function _get_image_color($im, $r, $g, $b) {

$c=imagecolorexact($im, $r, $g, $b);

if ($c!=-1) return $c;

$c=imagecolorallocate($im, $r, $g, $b);

if ($c!=-1) return $c;

return imagecolorclosest($im, $r, $g, $b);

} # EBD _get_image_color()

} # END watermark API

?>

This is the watermark function, however you don’t need to include it on your page, so hold your horses dear cardboard coder, next create a file called “image.php” and paste this code in:

<?php

# include our watermarking class

include 'watermark.php';

$watermark = new watermark();

# create image objects using our user-specified images

# NOTE: we're just going to assume we're dealing with a JPG and a PNG here - for example purposes

$main_img_obj = imagecreatefromjpeg('images/menus/'.$_GET['main']);

$watermark_img_obj = imagecreatefrompng('watermark.png');

# create our watermarked image - set 66% alpha transparency for our watermark

$return_img_obj = $watermark->create_watermark( $main_img_obj, $watermark_img_obj, 20 );

# display our watermarked image - first telling the browser that it's a JPEG,

# and that it should be displayed inline

header( 'Content-Type: image/jpeg' );

header( 'Content-Disposition: inline; filename=' . $_GET['src'] );

imagejpeg( $_GET['main'], '', 100 );

?>

Next upload the image you want to use as a watermark, it must be a PNG file and it must be 72 DPI. To add a watermark to any image just include images in your HTML like so:

<img src="/image.php?main=images/items/00000001.jpg&watermark=watermark.png">

Replace the main variable with the actual location of your image and the watermark variable with the location of your watermark, and that’s it!

This is also useful as when users right click and choose save as on an image, all they will get is a PHP file.

Please remember however doing this is CPU intensive so you need a decent server, so you may want to build a function that creates the images once and stores them somewhere ;-)

Comments (2)

Awesome job with the code formatting.

Thanks, we like everything to be colour coded makes it easier to read.

Write a comment