Skip to content

Instantly share code, notes, and snippets.

@awtprod
Created February 16, 2013 02:21
Show Gist options
  • Save awtprod/4965189 to your computer and use it in GitHub Desktop.
Save awtprod/4965189 to your computer and use it in GitHub Desktop.
/**
* Place watermark on image
*
* Options:
* - 'input' Input file (path or gd resource)
* - 'output' Output path. If not specified, gd resource is returned
* - 'watermark' Watermark file (path or gd resource)
* - 'quality' Output image quality (JPG only). Value from 0 to 100
* - 'compression' Output image compression (PNG only). Value from 0 to 9
* - 'chmod' What permissions should be applied to destination image
* - 'scale' If true, watermark will be scaled fullsize ('position' and 'repeat' won't be taken into account)
* - 'strech' If true and scale also set to true, strech watermark to cover whole image
* - 'repeat' Should watermark be repeated? This is ignored if 'scale' is set to true or 'position' is custom (array)
* - 'position' Watermark position. Possible values: 'top-left', 'top-right', 'bottom-right', 'bottom-left', 'center' or array(x, y)
* - 'opacity' Watermark image's opacity (0-100). Default = 100
* - 'afterCallbacks' Functions to be executed after this one
*
* @param array $options An array of options.
* @return mixed boolean or GD resource if output was set to null
*/
function watermark(Model $model, $srcFile, $path, $options = array()) {
$srcFile = $path . $model->data[$model->alias][$field];
$options = array_merge(array(
'afterCallbacks' => null,
'scale' => false,
'strech' => false,
'repeat' => false,
'watermark' => 'watermark.png',
'output' => '{ROOT}webroot{DS}files{DS}{model}{DS}{field}{DS}',
'input' => $srcFile,
'position' => 'center',
'compression' => 9,
'quality' => 100,
'chmod' => null,
'opacity' => 100
), $options);
// if output path (directories) doesn't exist, try to make whole path
if (!$this->createPath($options['output'])) {
return false;
}
$img = $this->openImage($options['input']);
unset($options['input']);
if (empty($img)) {
return false;
}
$src_wm = $this->openImage($options['watermark']);
unset($options['watermark']);
if (empty($src_wm)) {
return false;
}
// image size
$img_im_w = imagesx($img);
$img_im_h = imagesy($img);
// watermark size
$img_wm_w = imagesx($src_wm);
$img_wm_h = imagesy($src_wm);
if ($options['scale']) {
if ($options['strech']) {
$r = imagecopyresampled($img, $src_wm, 0, 0, 0, 0, $img_im_w, $img_im_h, $img_wm_w, $img_wm_h);
} else {
$x = 0;
$y = 0;
$w = $img_im_w;
$h = $img_im_h;
if (($img_im_w / $img_im_h) > ($img_wm_w / $img_wm_h)) {
$ratio = $img_im_h / $img_wm_h;
$w = $ratio * $img_wm_w;
$x = round(($img_im_w - $w) / 2);
} else {
$ratio = $img_im_w / $img_wm_w;
$h = $ratio * $img_wm_h;
$y = round(($img_im_h - $h) / 2);
}
$r = imagecopyresampled($img, $src_wm, $x, $y, 0, 0, $w, $h, $img_wm_w, $img_wm_h);
}
} else if ($options['repeat']) {
if (is_array($options['position'])) {
$options['position'] = 5;
}
switch ($options['position']) {
case 'top-left':
for ($y=0; $y<$img_im_h; $y+=$img_wm_h) {
for ($x=0; $x<$img_im_w; $x+=$img_wm_w) {
$r = $this->imagecopymerge_alpha($img, $src_wm, $x, $y, 0, 0, $img_wm_w, $img_wm_h, $options['opacity']);
}
}
break;
case 'top-right':
for ($y=0; $y<$img_im_h; $y+=$img_wm_h) {
for ($x=$img_im_w; $x>-$img_wm_w; $x-=$img_wm_w) {
$r = $this->imagecopymerge_alpha($img, $src_wm, $x, $y, 0, 0, $img_wm_w, $img_wm_h, $options['opacity']);
}
}
break;
case 'bottom-right':
for ($y=$img_im_h; $y>-$img_wm_h; $y-=$img_wm_h) {
for ($x=$img_im_w; $x>-$img_wm_w; $x-=$img_wm_w) {
$r = $this->imagecopymerge_alpha($img, $src_wm, $x, $y, 0, 0, $img_wm_w, $img_wm_h, $options['opacity']);
}
}
break;
case 'bottom-left':
for ($y=$img_im_h; $y>-$img_wm_h; $y-=$img_wm_h) {
for ($x=0; $x<$img_im_w; $x+=$img_wm_w) {
$r = $this->imagecopymerge_alpha($img, $src_wm, $x, $y, 0, 0, $img_wm_w, $img_wm_h, $options['opacity']);
}
}
break;
case 'center':
default:
$pos_x = -(($img_im_w%$img_wm_w)/2);
$pos_y = -(($img_im_h%$img_wm_h)/2);
for ($y=$pos_y; $y<$img_im_h; $y+=$img_wm_h) {
for ($x=$pos_x; $x<$img_im_w; $x+=$img_wm_w) {
$r = $this->imagecopymerge_alpha($img, $src_wm, $x, $y, 0, 0, $img_wm_w, $img_wm_h, $options['opacity']);
}
}
break;
}
} else {
// custom location
if (is_array($options['position'])) {
list($pos_x, $pos_y) = $options['position'];
} else {
// predefined location
switch ($options['position']) {
case 'top-left':
$pos_x = 0;
$pos_y = 0;
break;
case 'top-right':
$pos_x = $img_im_w - $img_wm_w;
$pos_y = 0;
break;
case 'bottom-right':
$pos_x = $img_im_w - $img_wm_w;
$pos_y = $img_im_h - $img_wm_h;
break;
case 'bottom-left':
$pos_x = 0;
$pos_y = $img_im_h - $img_wm_h;
break;
case 'center':
default:
$pos_x = round(($img_im_w - $img_wm_w) / 2);
$pos_y = round(($img_im_h - $img_wm_h) / 2);
break;
}
}
$r = $this->imagecopymerge_alpha($img, $src_wm, $pos_x, $pos_y, 0, 0, $img_wm_w, $img_wm_h, $options['opacity']);
}
if (!$r) {
return false;
}
if (!$this->afterCallbacks($img, $options['afterCallbacks'])) {
return false;
}
return $this->saveImage($img, $options);
}
/**
* Get file extension
*
* @param string $filename Filename
* @return string
*/
function getExtension($filename) {
if (!is_string($filename)) {
return '';
}
$pos = strrpos($filename, '.');
if ($pos === false) {
return '';
}
return strtolower(substr($filename, $pos + 1));
}
/**
* Open image as gd resource
*
* @param string $input Input (path) image
* @return mixed
*/
function openImage($input) {
if (is_resource($input)) {
if (get_resource_type($input) == 'gd') {
return $input;
}
} else {
switch ($this->getImageType($input)) {
case 'jpg':
return imagecreatefromjpeg($input);
break;
case 'png':
return imagecreatefrompng($input);
break;
case 'gif':
return imagecreatefromgif($input);
break;
}
}
return false;
}
/**
* Get image type from file
*
* @param string $input Input (path) image
* @param string $extension (optional) Extension (type)
* @param boolean $extension If true, check by extension
* @return string
*/
function getImageType($input, $extension = false) {
if ($extension) {
switch ($this->getExtension($input)) {
case 'jpg':
return 'jpg';
break;
case 'png':
return 'png';
break;
case 'gif':
return 'gif';
break;
}
} else if (is_string($input) && is_file($input)) {
$info = getimagesize($input);
switch ($info['mime']) {
case 'image/pjpeg':
case 'image/jpeg':
case 'image/jpg':
return 'jpg';
break;
case 'image/x-png':
case 'image/png':
return 'png';
break;
case 'image/gif':
return 'gif';
break;
}
}
return '';
}
/**
* Save image gd resource as image
*
* Image type is determined by $output extension so it must be present.
*
* Options:
* - 'compression' Output image's compression. Currently only PNG (value 0-9) supports this
* - 'quality' Output image's quality. Currently only JPG (value 0-100) supports this
* - 'output' Output path. If not specified, image resource is returned
*
* @param mixed $im Image resource
* @param string $output Output path
* @param mixed $options An array of additional options
* @return boolean
*/
function saveImage(&$im, $options = array()) {
foreach (array('compression', 'quality', 'chmod') as $v) {
if (is_null($options[$v])) {
unset($options[$v]);
}
}
$options = array_merge(array(
'compression' => 9,
'quality' => 100,
'output' => null
), $options);
switch ($this->getImageType($options['output'], true)) {
case 'jpg':
if (ImageJPEG($im, $options['output'], $options['quality'])) {
if (!empty($options['chmod'])) {
chmod($options['output'], $options['chmod']);
}
return true;
}
break;
case 'png':
if (ImagePNG($im, $options['output'], $options['compression'])) {
if (!empty($options['chmod'])) {
chmod($options['output'], $options['chmod']);
}
return true;
}
break;
case 'gif':
if (ImageGIF($im, $options['output'])) {
if (!empty($options['chmod'])) {
chmod($options['output'], $options['chmod']);
}
return true;
}
break;
case '':
return $im;
break;
}
unset($im);
return false;
}
/**
* Try to create specified path
*
* If specified path is empty, return true
*
* @param string $output_path
* @param mixed $chmod Each folder's permissions
* @return boolean
*/
function createPath($output_path, $chmod = 0777) {
if (empty($output_path)) {
return true;
}
$arr_output_path = explode(DIRECTORY_SEPARATOR, $output_path);
unset($arr_output_path[count($arr_output_path)-1]);
$dir_path = implode($arr_output_path, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
if (!file_exists($dir_path)) {
if (!mkdir($dir_path, $chmod, true)) {
return false;
}
}
return true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment