The following code sample demonstrates the use
of GD library to watermark images on the fly. The method demonstrated
here to watermark an uploaded image is to overlay the original image
with another image, preferably a transparent PNG image.
Watermark Your Images
The following code sample demonstrates the use of GD library to
watermark images on the fly. The method demonstrated here to watermark
an uploaded image is to overlay the original image with another image,
preferably a transparent PNG image.
PHP provides a rich set of functions to create and alter images on
the fly. These functions require the GD library, which is bundled with
PHP since version 4.3.
The Complete Example
The working code sample consists of the following items:
- HTML form that posts an image to the PHP script
- The PHP Script
- The Watermark Image
HTML Form
The HTML form needs a file upload element: <input type="file">. You must also specify the correct encoding type: enctype="multipart/form-data" for the form.
<form action="watermark-image.php" method="post" enctype="multipart/form-data">
Select a file to upload for processing<br>
<input type="file" name="File1"><br>
<input type="submit" value="Submit File">
</form>
The PHP Script
The following code handles the file upload and performs the image processing.
<?php
//--------------------------------
// CREATE WATERMARK FUNCTION
//--------------------------------
define( 'WATERMARK_OVERLAY_IMAGE', 'watermark.png' );
define( 'WATERMARK_OVERLAY_OPACITY', 50 );
define( 'WATERMARK_OUTPUT_QUALITY', 90 );
function create_watermark( $source_file_path, $output_file_path )
{
list( $source_width, $source_height, $source_type ) = getimagesize( $source_file_path );
if ( $source_type === NULL )
{
return false;
}
switch ( $source_type )
{
case IMAGETYPE_GIF:
$source_gd_image = imagecreatefromgif( $source_file_path );
break;
case IMAGETYPE_JPEG:
$source_gd_image = imagecreatefromjpeg( $source_file_path );
break;
case IMAGETYPE_PNG:
$source_gd_image = imagecreatefrompng( $source_file_path );
break;
default:
return false;
}
$overlay_gd_image = imagecreatefrompng( WATERMARK_OVERLAY_IMAGE );
$overlay_width = imagesx( $overlay_gd_image );
$overlay_height = imagesy( $overlay_gd_image );
imagecopymerge(
$source_gd_image,
$overlay_gd_image,
$source_width - $overlay_width,
$source_height - $overlay_height,
0,
0,
$overlay_width,
$overlay_height,
WATERMARK_OVERLAY_OPACITY
);
imagejpeg( $source_gd_image, $output_file_path, WATERMARK_OUTPUT_QUALITY );
imagedestroy( $source_gd_image );
imagedestroy( $overlay_gd_image );
}
//--------------------------------
// FILE PROCESSING FUNCTION
//--------------------------------
define( 'UPLOADED_IMAGE_DESTINATION', 'originals/' );
define( 'PROCESSED_IMAGE_DESTINATION', 'images/' );
function process_image_upload( $Field )
{
$temp_file_path = $_FILES[ $Field ][ 'tmp_name' ];
$temp_file_name = $_FILES[ $Field ][ 'name' ];
list( , , $temp_type ) = getimagesize( $temp_file_path );
if ( $temp_type === NULL )
{
return false;
}
switch ( $temp_type )
{
case IMAGETYPE_GIF:
break;
case IMAGETYPE_JPEG:
break;
case IMAGETYPE_PNG:
break;
default:
return false;
}
$uploaded_file_path = UPLOADED_IMAGE_DESTINATION . $temp_file_name;
$processed_file_path = PROCESSED_IMAGE_DESTINATION . preg_replace( '/\\.[^\\.]+$/', '.jpg', $temp_file_name );
move_uploaded_file( $temp_file_path, $uploaded_file_path );
$result = create_watermark( $uploaded_file_path, $processed_file_path );
if ( $result === false )
{
return false;
}
else
{
return array( $uploaded_file_path, $processed_file_path );
}
}
//--------------------------------
// END OF FUNCTIONS
//--------------------------------
$result = process_image_upload( 'File1' );
if ( $result === false )
{
echo '<br>An error occurred during file processing.';
}
else
{
echo '<br>Original image saved as <a href="' . $result[ 0 ] . '" target="_blank">' . $result[ 0 ] . '</a>';
echo '<br>Watermarked image saved as <a href="' . $result[ 1 ] . '" target="_blank">' . $result[ 1 ] . '</a>';
}
?>
The Watermark Image
The watermark image should be in one of the following recommended formats:
- PNG-8 (recommended)
Colors: 256 or less
Transparency: On/Off
- GIF
Colors: 256 or less
Transparency: On/Off
- JPEG
Colors: True color
Transparency: n/a
The imagecopymerge function does not properly handle the PNG-24 images; it is therefore not recommend.
If you are using Adobe Photoshop to create watermark images, it is
recommended that you use "Save for Web" command with the following
settings:
- File Format: PNG-8, non-interlaced
- Color Reduction: Selective, 256 colors
- Dithering: Diffusion, 88%
- Transparency: On, Matte: None
- Transparency Dither: Diffusion Transparency Dither, 100%
How it Works
The function relies on the imagecopymerge
function available in GD library. This function copies a rectangular
region from one image onto the other. The important thing is that this
function allows you to specify the opacity of the image that is
rendered on the destination image.
Example Output
Example 1: Original Image
Example 1: Watermarked image showing four different combinations of alignment and opacity
Example 2: Original Image
Example 2: Watermarked image showing four different combinations of alignment and opacity
Variations of the Function
The example above will place the watermark image on the lower-right
corner of the original image with 50% opacity. To experiment with other
alignment options, you can modify the line containing imagecopymerge as follows:
<?php
//--------------------------------
// ALIGN TOP, LEFT
//--------------------------------
imagecopymerge(
$source_gd_image,
$overlay_gd_image,
0,
0,
0,
0,
$overlay_width,
$overlay_height,
WATERMARK_OVERLAY_OPACITY
);
//--------------------------------
// ALIGN TOP, RIGHT
//--------------------------------
imagecopymerge(
$source_gd_image,
$overlay_gd_image,
$source_width - $overlay_width,
0,
0,
0,
$overlay_width,
$overlay_height,
WATERMARK_OVERLAY_OPACITY
);
//--------------------------------
// ALIGN BOTTOM, RIGHT
//--------------------------------
imagecopymerge(
$source_gd_image,
$overlay_gd_image,
$source_width - $overlay_width,
$source_height - $overlay_height,
0,
0,
$overlay_width,
$overlay_height,
WATERMARK_OVERLAY_OPACITY
);
//--------------------------------
// ALIGN BOTTOM, LEFT
//--------------------------------
imagecopymerge(
$source_gd_image,
$overlay_gd_image,
0,
$source_height - $overlay_height,
0,
0,
$overlay_width,
$overlay_height,
WATERMARK_OVERLAY_OPACITY
);
?>
Limitations of the Script
- The example currently supports GIF, JPEG and PNG file handling. Additional image type support can be added rather easily.
- The example does not generate unique file names and therefore overwrites existing uploaded or thumbnail images.
- The example does not show any error messages. All "return false" need to be replaced by appropriate error handling.
- 256 color watermark images with transparency often have visible artifacts around the edges after rendering.
- 24-bit PNG watermark images are not rendered properly.
- Additional
watermark alignment options are not discussed. I am leaving that as an
exercise. FYI, it is as simple as dividing a few numbers by 2.
|