Skip to content

Instantly share code, notes, and snippets.

@ArnauAregall
Last active December 13, 2015 20:39
Show Gist options
  • Save ArnauAregall/4971917 to your computer and use it in GitHub Desktop.
Save ArnauAregall/4971917 to your computer and use it in GitHub Desktop.
PHP Watermarker Class Adapted for Yii Framework
<?php
/**
* This is a driver for the watermarks creating
*
* LICENSE:
* The PHP License, version 3.0
*
* Copyright (c) 1997-2005 The PHP Group
*
* This source file is subject to version 3.0 of the PHP license,
* that is bundled with this package in the file LICENSE, and is
* available through the world-wide-web at the following url:
* http://www.php.net/license/3_0.txt.
* If you did not receive a copy of the PHP license and are unable to
* obtain it through the world-wide-web, please send a note to
* [email protected] so we can mail you a copy immediately.
*
* Class based on http://code.google.com/p/php-funs/
*
* @license http://www.php.net/license/3_0.txt
* The PHP License, version 3.0
*/
class Watermarker
{
/**
* Horizontal align constants
*/
const ALIGN_LEFT = -1;
const ALIGN_CENTER = 0;
const ALIGN_RIGHT = +1;
/**
* Vertical align constants
*/
const ALIGN_TOP = -1;
const ALIGN_MIDDLE = 0;
const ALIGN_BOTTOM = +1;
/**
* Display rendered image (send it to browser or to file).
* This method is a common implementation to render and output an image.
* The method calls the render() method automatically and outputs the
* image to the browser or to the file.
*
* @param mixed $input Destination image, a filename or an image string data or a GD image resource
* @param array $options Watermark options
* <pre>
* watermark string Watermark image filename
* halign int Horizontal align; one of Watermark::ALIGN_* constants
* valign int Vertical align; one of Watermark::ALIGN_* constants
* hshift int Horizontal shift
* vshift int Vertical shift
* type int One of IMAGETYPE_* constants supported by class
* jpeg-quality int JPEG quality level
* </pre>
*
* @return boolean TRUE on success or FALSE on failure.
* @access public
*/
public static function output ($input, $output = null, $options = null)
{
// Set default options
static $defOptions = array(
'watermark' => '',
'halign' => self::ALIGN_CENTER,
'valign' => self::ALIGN_MIDDLE,
'hshift' => 0,
'vshift' => 0,
'type' => IMAGETYPE_JPEG,
'jpeg-quality' => 90,
);
foreach ($defOptions as $k => $v) {
if ( ! isset($options[$k]) ) {
$options[$k] = $v;
}
}
// Load source file and render image
$renderImage = self::_render($input, $options);
if ( ! $renderImage ) {
throw new CHttpException(400,'Error rendering image');
return false;
}
// Before output to browsers send appropriate headers
if ( empty($output) ) {
$content_type = image_type_to_mime_type($options['type']);
if ( ! headers_sent() ) {
header('Content-Type: ' . $content_type);
} else {
throw new CHttpException(400,'Headers have already been sent. Could not display image.');
return false;
}
}
// Define outputing function
switch ($options['type'])
{
case IMAGETYPE_GIF:
$result = empty($output) ? imagegif($renderImage) : imagegif($renderImage, $output);
break;
case IMAGETYPE_PNG:
$result = empty($output) ? imagepng($renderImage) : imagepng($renderImage, $output);
break;
case IMAGETYPE_JPEG:
$result = empty($output) ? imagejpeg($renderImage, '', $options['jpeg-quality']) : imagejpeg($renderImage, $output, $options['jpeg-quality']);
break;
default:
throw new CHttpException(400,'Image type ' . $content_type . ' not supported by PHP');
return false;
}
// Output image (to browser or to file)
if ( ! $result ) {
throw new CHttpException(400,'Error output image');
return false;
}
// Free a memory from the target image
imagedestroy($renderImage);
return true;
}
/**
* Draw watermark to resource.
*
* @param mixed $input Destination image, a filename or an image string data or a GD image resource
* @param array $options Watermark options
*
* @return boolean TRUE on success or FALSE on failure.
* @access public
* @see Watermark::output()
*/
private static function _render ($input, $options)
{
$sourceImage = self::_imageCreate($input);
if ( ! is_resource($sourceImage) ) {
throw new CHttpException(400,'Invalid image resource');
return false;
}
$watermark = self::_imageCreate($options['watermark']);
if ( ! is_resource($watermark) ) {
throw new CHttpException(400,'Invalid watermark resource');
return false;
}
$image_width = imagesx($sourceImage);
$image_height = imagesy($sourceImage);
$watermark_width = imagesx($watermark);
$watermark_height = imagesy($watermark);
$X = self::_coord($options['halign'], $image_width, $watermark_width) + $options['hshift'];
$Y = self::_coord($options['valign'], $image_height, $watermark_height) + $options['vshift'];
imagecopy($sourceImage, $watermark, $X, $Y, 0, 0, $watermark_width, $watermark_height);
imagedestroy($watermark);
return $sourceImage;
}
/**
* Create a GD image resource from given input.
*
* This method tried to detect what the input, if it is a file the
* createImageFromFile will be called, otherwise createImageFromString().
*
* @param mixed $input The input for creating an image resource. The value
* may a string of filename, string of image data or
* GD image resource.
*
* @return resource An GD image resource on success or false
* @access public
* @static
* @see Watermark::imageCreateFromFile(), Watermark::imageCreateFromString()
*/
private static function _imageCreate ($input)
{
if ( is_file($input) ) {
return self::_imageCreateFromFile($input);
} else if ( is_string($input) ) {
return self::_imageCreateFromString($input);
} else {
return $input;
}
}
/**
* Create a GD image resource from file (JPEG, PNG support).
*
* @param string $filename The image filename.
*
* @return mixed GD image resource on success, FALSE on failure.
* @access private
* @static
*/
private static function _imageCreateFromFile ($filename)
{
if ( ! is_file($filename) || ! is_readable($filename) ) {
throw new CHttpException(400,'Unable to open file "' . $filename . '"');
return false;
}
// determine image format
list( , , $type) = getimagesize($filename);
switch ($type)
{
case IMAGETYPE_GIF:
return imagecreatefromgif($filename);
break;
case IMAGETYPE_JPEG:
return imagecreatefromjpeg($filename);
break;
case IMAGETYPE_PNG:
return imagecreatefrompng($filename);
break;
}
throw new CHttpException(400,'Unsupport image type');
return false;
}
/**
* Create a GD image resource from a string data.
*
* @param string $string The string image data.
*
* @return mixed GD image resource on success, FALSE on failure.
* @access private
* @static
*/
private static function _imageCreateFromString ($string)
{
if ( ! is_string($string) || empty($string) ) {
throw new CHttpException(400,'Invalid image value in string');
return false;
}
return imagecreatefromstring($string);
}
/**
* Calculate watermark X or Y coordinate based on align and dimensions
*
* @param int $align One of Watermark::ALIGN_* constants
* @param int $image_dimension The string image data.
* @param int $watermark_dimension The string image data.
*
* @return int Coordinate
* @access private
* @static
*/
private static function _coord ($align, $image_dimension, $watermark_dimension)
{
if ( $align < self::ALIGN_CENTER ) {
$result = 0;
} elseif ( $align > self::ALIGN_CENTER ) {
$result = $image_dimension - $watermark_dimension;
} else {
$result = ($image_dimension - $watermark_dimension) >> 1;
}
return $result;
}
}
@ArnauAregall
Copy link
Author

Example of usage:

$watermark_options  = array(
                        'watermark'     => IMAGE_PATH."stamp.png",
                        'halign'        => Watermarker::ALIGN_RIGHT,
                        'valign'        => Watermarker::ALIGN_BOTTOM,
                        'hshift'        => -10,
                        'vshift'        => -10,
                        'type'          => IMAGETYPE_JPEG,          // Save result in JPEG to minimize file size
                        'jpeg-quality'  => 90,
                );
                // Save watermarked image to file
                Watermarker::output($finalImageName, $finalImageName, $watermark_options);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment