%PDF- %PDF-
| Direktori : /home/lightco1/www/plugins/system/magic360/magic360_classes/ |
| Current File : /home/lightco1/www/plugins/system/magic360/magic360_classes/magictoolbox.imagehelper.class.php |
<?php
/*------------------------------------------------------------------------
# plg_system_magic360 - Magic 360 for Joomla
# ------------------------------------------------------------------------
# Magic Toolbox
# Copyright 2011 MagicToolbox.com. All Rights Reserved.
# @license - http://www.opensource.org/licenses/artistic-license-2.0 Artistic License 2.0 (GPL compatible)
# Website: http://www.magictoolbox.com/magic360/modules/joomla/
# Technical Support: http://www.magictoolbox.com/contact/
/*-------------------------------------------------------------------------*/
// no direct access
defined('_JEXEC') or die('Restricted access.');
if(!defined('MagicToolboxImageHelperClassLoaded')) {
define('MagicToolboxImageHelperClassLoaded', true);
require_once('magictoolbox.params.class.php');
if(!defined('MT_DS')) {
define('MT_DS', DIRECTORY_SEPARATOR);
//define('MT_DS', '/');
}
class MagicToolboxImageHelperClass {
// link to original image file
var $src = '';
// original file extension
var $ext = '';
// destination file (without sufix and extension)
var $out = '';
// full path for webdir
var $path = '';
// web address for wesite
var $url = '';
// full destination file
var $file = '';
// path to Image Magick
var $imageMagick = false;
// options (imagick path, resize params, etc)
var $options = null;
//options hash for folder name
var $hash;
// is there critical errors?
var $errors = false;
//path to folder with cached images
var $cache = '';
var $pid = null;
/**
* @constructor
* @param string $path full path for webdir
* @param string $cache cache folder path relative to webdir
* @param object $options options (imagick path, resize params, etc)
* @param string $pid product ID
* @param string $url web address for wesite
* @return nothing
*/
function __construct($path, $cache = null, $options = null, $pid = null, $url = null) {
clearstatcache();
//prepare params
$this->path = preg_replace('/(\/|\\\\)$/is', '', $path);
if(!$cache) {
$cache = MT_DS.'magictoolbox_cache';
} else {
$cache = preg_replace('/(\/|\\\\)$/is', '', $cache);
}
if(!$options) {
$this->options = new MagicToolboxParamsClass();
$this->options->appendArray(array(
"square-images"=>array("id"=>"square-images","group"=>"Positioning and Geometry","order"=>"310","default"=>"disable","label"=>"Create square images","description"=>"The white/transparent padding will be added around the image or the image will be cropped.","type"=>"array","subType"=>"radio","values"=>array("extend","crop","disable"),"scope"=>"module"),
"imagemagick"=>array("id"=>"imagemagick","advanced"=>"1","group"=>"Miscellaneous","order"=>"550","default"=>"off","label"=>"Path to ImageMagick binaries (convert tool)","description"=>"You can set 'auto' to automatically detect ImageMagick location or 'off' to disable ImageMagick and use php GD lib instead","type"=>"text","scope"=>"module"),
"watermark"=>array("id"=>"watermark","group"=>"Watermark","order"=>"10","default"=>"","label"=>"Watermark image path","description"=>"Enter location of watermark image on your server. Leave field empty to disable watermark","type"=>"text","scope"=>"module"),
"watermark-opacity"=>array("id"=>"watermark-opacity","group"=>"Watermark","order"=>"40","default"=>"50","label"=>"Watermark image opacity (1-100)","description"=>"0 = transparent, 100 = solid color","type"=>"num","scope"=>"module"),
"watermark-max-width"=>array("id"=>"watermark-max-width","group"=>"Watermark","order"=>"20","default"=>"30%","label"=>"Maximum width of watermark image","description"=>"pixels = fixed size (e.g. 50) / percent = relative for image size (e.g. 50%)","type"=>"text","scope"=>"module"),
"watermark-max-height"=>array("id"=>"watermark-max-height","group"=>"Watermark","order"=>"21","default"=>"30%","label"=>"Maximum height of watermark image","description"=>"pixels = fixed size (e.g. 50) / percent = relative for image size (e.g. 50%)","type"=>"text","scope"=>"module"),
"watermark-position"=>array("id"=>"watermark-position","group"=>"Watermark","order"=>"50","default"=>"center","label"=>"Watermark position","description"=>"Watermark size settings will be ignored when watermark position is set to 'stretch'","type"=>"array","subType"=>"select","values"=>array("top","right","bottom","left","top-left","bottom-left","top-right","bottom-right","center","stretch"),"scope"=>"module"),
"watermark-offset-x"=>array("id"=>"watermark-offset-x","advanced"=>"1","group"=>"Watermark","order"=>"60","default"=>"0","label"=>"Watermark horizontal offset","description"=>"Offset from left and/or right image borders. Pixels = fixed size (e.g. 20) / percent = relative for image size (e.g. 20%). Offset will disable if 'watermark position' set to 'center'","type"=>"text","scope"=>"module"),
"watermark-offset-y"=>array("id"=>"watermark-offset-y","advanced"=>"1","group"=>"Watermark","order"=>"70","default"=>"0","label"=>"Watermark vertical offset","description"=>"Offset from top and/or bottom image borders. Pixels = fixed size (e.g. 20) / percent = relative for image size (e.g. 20%). Offset will disable if 'watermark position' set to 'center'","type"=>"text","scope"=>"module"),
"image-quality"=>array("id"=>"image-quality","group"=>"Miscellaneous","order"=>"560","default"=>"75","label"=>"Quality of thumbnails and watermarked images (1-100)","description"=>"1 = worst quality / 100 = best quality","type"=>"num","scope"=>"module")
));
$this->logError('MagicToolbox ImageHelper :: Invalid options (use defauls)');
} else {
$this->options = $options;
}
$this->pid = $pid;
if($url) {
$this->url = preg_replace('/\/$/is', '', $url);
}
$this->hash = $this->getOptionsHash();
$cache = $cache.MT_DS.$this->hash;
$this->cache = $this->path.$cache;
//create cache
if(!@is_dir($this->cache)) {
$this->cache = $this->path;
//recursively check/create subdirs
$cache = explode(MT_DS, $cache);
foreach($cache as $sub_dir) {
if(!strlen($sub_dir)) continue;
$this->cache .= MT_DS.$sub_dir;
if(!is_dir($this->cache) && (!@mkdir($this->cache) || !@chmod($this->cache, 0777))) {
$this->logError('MagicToolbox ImageHelper :: Can\'t create cache folder or change permission ('.$this->cache.')', true);
return;
}
}
}
// check path to Image Magick
$this->imageMagick = $this->checkImagick($this->options->getValue('imagemagick'));
}
function getOptionsHash() {
$params = array();
$wIDs = array('watermark-opacity', 'watermark-max-width', 'watermark-max-height', 'watermark-position', 'watermark-offset-x', 'watermark-offset-y');
$params[] = $this->options->getValue('square-images');
$params[] = $this->options->getValue('image-quality');
//$params[] = $this->options->getValue('use-original-file-names');
$watermark = $this->options->getValue('watermark');
if($watermark) {
$params[] = $watermark;
foreach($wIDs as $id) {
$params[] = $this->options->getValue($id);
}
}
return md5(implode('', $params));
}
/**
* create thumbnail
*
* @access public
* @param string $src relative path to original image
* @param string / array $type type of thumbnail to create ('original', 'thumb', 'selector') or sizes
* @param string $out relative path to result image
* @param string $pid product ID
* @param boolean $force force to replace existing image
*/
function create($src, $type, $pid = null, $out = null, $force = false) {
if($this->errors) {
return false;
}
if ($retina = is_string($type) && preg_match('/.*2x$/', $type)) {
$type = preg_replace('/(.*)2x$/','$1',$type);
}
$src = str_replace('/', MT_DS, $src);
$this->src = $this->path.$src;
if(!file_exists($this->src) || !is_file($this->src)) {
$this->logError('MagicToolbox ImageHelper :: Invalid image file ('.$this->src.')');
return false;
} else {
if(is_string($type)) {
if($type == 'original') {
$size = array(0, 0);
} else {
$size = array(
$this->options->getValue($type.'-max-width')*($retina?2:1),
$this->options->getValue($type.'-max-height')*($retina?2:1)
);
$type = $type.$size[0].'x'.$size[1];
}
} else {
$size = $type;
$type = $type[0].'x'.$type[1];
}
if($pid === null) $pid = $this->pid;
$this->ext = substr($src, strrpos($src, '.'));
if($out === null) {
if($pid === null) {
$out = $this->cache.MT_DS.$type;
} else {
$out = $this->cache.MT_DS.$this->getPathPrefix($pid).$pid;
if(!is_dir($out)) {
$out = $this->cache;
$path = explode(MT_DS, $this->getPathPrefix($pid).$pid);
foreach($path as $part) {
if(!strlen($part)) continue;
$out .= MT_DS.$part;
if(!is_dir($out) && (!@mkdir($out) || !@chmod($out, 0777))) {
$this->logError('MagicToolbox ImageHelper :: Can\'t create cache folder or change permission ('.$out.')', true);
return false;
}
}
}
$out = $out.MT_DS.$type;
}
if(!is_dir($out) && (!@mkdir($out) || !@chmod($out, 0777))) {
$this->logError('MagicToolbox ImageHelper :: Can\'t create cache folder or change permission ('.$out.')', true);
return false;
}
//if($this->options->checkValue('use-original-file-names', 'No')) {
// $this->out = $out.MT_DS.md5($src);
//} else {
//NOTE: added file path hash (if files have the same name)
$out = $out.MT_DS.crc32($src);
if(!is_dir($out) && (!@mkdir($out) || !@chmod($out, 0777))) {
$this->logError('MagicToolbox ImageHelper :: Can\'t create cache folder or change permission ('.$out.')', true);
return false;
}
$this->out = $out.MT_DS.substr($src, strrpos($src, MT_DS)+1, -strlen($this->ext));
//}
$this->file = $this->out.$this->ext;
} else {
$this->out = $this->path.$out;
$this->file = $this->out;
}
if($force || !file_exists($this->file) || !is_file($this->file) || (@filemtime($this->file) - @filemtime($this->src)) < 0) {
$this->resize($size[0], $size[1]);
if(file_exists($this->file) && is_file($this->file)) {
@chmod($this->file, 0755);
return $this->getLink($this->file);
}
} elseif(file_exists($this->file) && is_file($this->file)) {
return $this->getLink($this->file);
}
}
return $this->getLink($this->src);
}
/*function createDir($dir) {
//recursively check/create subdirs
$dirs = explode(MT_DS, $dir);
$_dir = '';
foreach($dirs as $sub_dir) {
if(!strlen($sub_dir)) continue;
$_dir .= MT_DS.$sub_dir;
if(!is_dir($_dir) && (!@mkdir($_dir) || !@chmod($_dir, 0777))) {
$this->logError('MagicToolbox ImageHelper :: Can\'t create cache folder or change permission ('.$_dir.')', true);
return false;
}
}
return true;
}*/
function getPathPrefix($str) {
$str = preg_replace('/[^a-z0-9_]+/i', '_', $str);
//if(preg_match('/^_+$/', $str)) {
// $str = '';
//}
//$i = 0;
//$pathPrefix = '';
//for($i = 0, $l = strlen($str); $i < 2 && $i < $l ; $i++) {
// $pathPrefix .= $str[$i].MT_DS;
//}
//return $pathPrefix;
if(strlen($str) < 2) return '';
return $str[0].MT_DS.$str[1].MT_DS;
}
function getLink($link) {
$link = $this->path ? str_replace($this->path, $this->url, $link) : ($this->url.$link);
$link = str_replace(MT_DS, '/', $link);
return $link;
}
function getTotalSize($originalW, $originalH, $maxW = 0, $maxH = 0) {
if(!$maxW && !$maxH) {
return array($originalW, $originalH);
} elseif(!$maxW) {
$maxW = ($maxH * $originalW) / $originalH;
} elseif(!$maxH) {
$maxH = ($maxW * $originalH) / $originalW;
}
$sizeDepends = $originalW/$originalH;
$placeHolderDepends = $maxW/$maxH;
if($sizeDepends > $placeHolderDepends) {
$newW = $maxW;
$newH = $originalH * ($maxW / $originalW);
} else {
$newW = $originalW * ($maxH / $originalH);
$newH = $maxH;
}
return array(round($newW), round($newH));
}
function resize($w = null, $h = null, $square = null) {
if($this->errors) return false;
$watermark = $this->options->getValue('watermark');
if($square == null) {
$square = $this->options->getValue('square-images');
}
if($square == 'disable') {
$square = false;
}
if($watermark) {
$watermark = $this->path.'/'.preg_replace('/^\/|\/$/is', '', $watermark);
if(!(file_exists($watermark) && is_file($watermark))) {
$watermark = false;
} else {
$wpos = strtolower($this->options->getValue('watermark-position'));
$wopacity = $this->options->getValue('watermark-opacity');
$woffsetx = $this->options->getValue('watermark-offset-x');
$woffsety = $this->options->getValue('watermark-offset-y');
$ww = $this->options->getValue('watermark-max-width');
$wh = $this->options->getValue('watermark-max-height');
}
} else if(!($w || $h || $square)) {
return;
}
$q = intval($this->options->getValue('image-quality'));
//if($imagick = $this->checkImagick($this->options->getValue('imagemagick'))) {
if($imagick = $this->imageMagick) {
// use imagemagick
if($imagick == 'native') {
//not support yet
//$imagick = new Imagick($this->img);
//if($h === null) {
// $imagick->thumbnailImage($depends != 'height' ? $w : 0, $depends != 'width' ? $w : 0, $depends == 'both' ? true : false);
//} else {
// $imagick->thumbnailImage($w, $h, false);
//}
//$imagick->writeImage($this->file);
// TODO implement watermark
// TODO implement square
} else {
$imagick = escapeshellarg($imagick);
$size = $this->getImageInfo($this->src, $imagick);
if(empty($size[0]) || !$size[0]) {
$this->logError('MagicToolbox ImageHelper :: Can\'t get the picture size. ('.$this->src.')', true);
return false;
}
if(!$w && !$h) {
$w = $size[0]; $h = $size[1];
} else {
if($square == 'crop') {
$s = max(($w ? $w : 0), ($h ? $h : 0));
if($size[0] < $size[1]) {
$w = $s;
$h = 0;
} else if($size[0] > $size[1]) {
$w = 0;
$h = $s;
} else {
$square = false;
$w = $h = $s;
}
}
list($w, $h) = $this->getTotalSize($size[0], $size[1], $w, $h);
}
$imagickComposite = str_replace('convert', 'composite', $imagick);
$escapedFilePath = escapeshellarg($this->file);
$coalesceOption = $this->ext == '.gif' ? ' -coalesce' : '';
exec($imagick.' '.escapeshellarg($this->src).$coalesceOption.' -quality '.$q.' -resize '.$w.'x'.$h.'! '.$escapedFilePath);
if($square == 'crop') {
if($w > $h) {
$offsetx = round(($w - $h)/2);
$offsety = 0;
$w = $h;
//exec($imagick.' '.$escapedFilePath.$coalesceOption.' -quality '.$q.' -crop '.$w.'x'.$h.'+'.$offsetx.'+'.$offsety.'! '.$escapedFilePath);
exec($imagick.' '.$escapedFilePath.$coalesceOption.' -quality '.$q.' -shave '.$offsetx.'x'.$offsety.' '.$escapedFilePath);
} else if($w < $h) {
$offsetx = 0;
$offsety = round(($h - $w)/2);
$h = $w;
//exec($imagick.' '.$escapedFilePath.$coalesceOption.' -quality '.$q.' -crop '.$w.'x'.$h.'+'.$offsetx.'+'.$offsety.'! '.$escapedFilePath);
exec($imagick.' '.$escapedFilePath.$coalesceOption.' -quality '.$q.' -shave '.$offsetx.'x'.$offsety.' '.$escapedFilePath);
}
}
if($watermark) {
$wsize = $this->getImageInfo($watermark, $imagick);
$mins = min($w, $h);
$ww = $this->getPercent($ww, $mins);
$wh = $this->getPercent($wh, $mins);
list($ww, $wh) = $this->getTotalSize($wsize[0], $wsize[1], $ww, $wh);
$woffsetx = $this->getPercent($woffsetx, $w);
$woffsety = $this->getPercent($woffsety, $h);
if($wpos == 'stretch') {
$wcmd = '-size '.$w.'x'.$h.' -depth '.$wsize[2].' NULL: -write mpr:watermarkblank +delete '
.escapeshellarg($watermark).' -quality '.$q.' -resize '.($w - 2 * $woffsetx).'x'.($h - 2 * $woffsety).'! -write mpr:watermark +delete '
.'mpr:watermarkblank -gravity Center mpr:watermark -composite -write mpr:watermark +delete ';
} else {
$wcmd = '-size '.($ww + 2 * $woffsetx).'x'.($wh + 2 * $woffsety).' -depth '.$wsize[2].' NULL: -write mpr:watermarkblank +delete '
.escapeshellarg($watermark).' -quality '.$q.' -resize '.$ww.'x'.$wh.'! -write mpr:watermark +delete '
.'mpr:watermarkblank -gravity Center mpr:watermark -composite -write mpr:watermark +delete ';
}
$escapedTmpFilePath = escapeshellarg($this->file.'.png');
exec($imagick.' '.$wcmd.' mpr:watermark -quality '.$q.' '.$escapedTmpFilePath);
switch($wpos) {
case 'stretch':
case 'center':
$wcmd = 'Center';
break;
case 'tile':
// TODO implement
// we can use -tile option here
break;
case 'top-right':
$wcmd = 'NorthEast';
break;
case 'top-left':
$wcmd = 'NorthWest';
break;
case 'bottom-right':
$wcmd = 'SouthEast';
break;
case 'bottom-left':
$wcmd = 'SouthWest';
break;
case 'top':
$wcmd = 'North';
break;
case 'bottom':
$wcmd = 'South';
break;
case 'left':
$wcmd = 'West';
break;
case 'right':
$wcmd = 'East';
break;
default: break;
}
if($this->ext != '.gif') {
//NOTE: this bad for animated GIF
exec($imagickComposite.' '.$escapedTmpFilePath.' -dissolve '.$wopacity.' -gravity '.$wcmd.' '.$escapedFilePath.' '.$escapedFilePath);
} else {
//NOTE: this good for animated GIF (but without transparency)
exec($imagick.' '.$escapedFilePath.' -coalesce -gravity '.$wcmd.' -geometry +0+0 null: '.$escapedTmpFilePath.' -layers composite -layers optimize '.$escapedFilePath);
}
@unlink($this->file.'.png');
}
if($square == 'extend') {
/*
$s = max($w, $h);
if($size[3] == 'png' || $size[3] == 'gif') {
// null for transparent images
$wrapper = 'NULL:';
} else {
// white background for opaque images
$wrapper = 'xc:white';
}
//$wrapper = 'NULL:';
//NOTE: this command causes problems with animated GIF
$cmd = ' -size '.$s.'x'.$s.' -depth '.$size[2].' '.$wrapper.' -write mpr:resultblank +delete '
.'mpr:resultblank -gravity Center '.$escapedFilePath
.' -compose src-over -composite '.$escapedFilePath;
*/
if($size[3] == 'png' || $size[3] == 'gif') {
$bordercolor = '-bordercolor none';
//$bordercolor = '-matte -bordercolor none';
} else {
$bordercolor = '-bordercolor White';
}
if($w > $h) {
$borderx = 0;
$bordery = round(($w - $h)/2);
} else/* if($w < $h)*/ {
$borderx = round(($h - $w)/2);
$bordery = 0;
}
$cmd = ' '.$escapedFilePath." {$bordercolor} -border {$borderx}x{$bordery} ".$escapedFilePath;
exec($imagick.$cmd);
}
}
} else {
// use GD library
list($data, $size) = $this->loadImage($this->src);
if(!$data) {
$this->logError('MagicToolbox ImageHelper :: Can\'t get the image data. ('.$this->src.')', true);
return false;
}
if(!$w && !$h) {
$w = $size[0]; $h = $size[1];
if($square == 'extend') {
$rw = $rh = max($w, $h);
} else if($square == 'crop') {
$rw = $rh = min($w, $h);
} else {
$rw = $w;
$rh = $h;
}
} else {
list($w, $h) = $this->getTotalSize($size[0], $size[1], $w, $h);
if($square) {
$rw = $rh = max($w, $h);
} else {
$rw = $w;
$rh = $h;
}
}
$out = $this->createImage($rw, $rh);
$fCopy = function_exists('imagecopyresampled') ? 'imagecopyresampled' : 'imagecopyresized';
if($square == 'crop') {
if($size[0] > $size[1]) {
$offsetx = round(($size[0]- $size[1])/2);
$offsety = 0;
$src_size = $size[1];
} else if($size[0] < $size[1]) {
$offsetx = 0;
$offsety = round(($size[1] - $size[0])/2);
$src_size = $size[0];
} else {
$offsetx = $offsety = 0;
$src_size = $size[0];
}
$w = $h = $rw;//= $rh
call_user_func($fCopy, $out, $data, 0, 0, $offsetx, $offsety, $rw, $rh, $src_size, $src_size);
} else {
call_user_func($fCopy, $out, $data, ($rw-$w)/2, ($rh-$h)/2, 0, 0, $w, $h, $size[0], $size[1]);
}
// include watermark
if($watermark) {
list($wdata, $wsize) = $this->loadImage($watermark);
$mins = min($w, $h);
$ww = $this->getPercent($ww, $mins);
$wh = $this->getPercent($wh, $mins);
list($ww, $wh) = $this->getTotalSize($wsize[0], $wsize[1], $ww, $wh);
$woffsetx = $this->getPercent($woffsetx, $w);
$woffsety = $this->getPercent($woffsety, $h);
if($wpos == 'stretch') {
$wdatanew = $this->createImage($w - 2 * $woffsetx, $h - 2 * $woffsety);
call_user_func($fCopy, $wdatanew, $wdata, 0, 0, 0, 0, $w - 2 * $woffsetx, $h - 2 * $woffsety, $wsize[0], $wsize[1]);
} else {
$wdatanew = $this->createImage($ww, $wh);
call_user_func($fCopy, $wdatanew, $wdata, 0, 0, 0, 0, $ww, $wh, $wsize[0], $wsize[1]);
}
//imagealphablending($wdatanew, true);
//NOTE: if both (image and watermark image) are PNG
$imagecopymerge = ($wsize[2] == 3 && $wsize[2] == $size[2]) ? 'imagecopymerge_extra' : 'imagecopymerge';
switch($wpos) {
case 'center':
//call_user_func($fCopy, $out, $wdata, ($rw-$ww)/2, ($rh-$wh)/2, 0, 0, $ww, $wh, $wsize[0], $wsize[1]);//NOTE: 'watermark-opacity' does't work in this case
//imagecopymerge($out, $wdatanew, ($rw-$ww)/2, ($rh-$wh)/2, 0, 0, $ww, $wh, $wopacity);
$this->{$imagecopymerge}($out, $wdatanew, ($rw-$ww)/2, ($rh-$wh)/2, 0, 0, $ww, $wh, $wopacity);
break;
case 'tile':
// TODO implement
break;
case 'stretch':
$this->{$imagecopymerge}($out, $wdatanew, $woffsetx+($rw-$w)/2, $woffsety+($rh-$h)/2, 0, 0, $w-2*$woffsetx, $h-2*$woffsety, $wopacity);
break;
case 'top-right':
$this->{$imagecopymerge}($out, $wdatanew, $rw-$woffsetx-$ww-($rw-$w)/2, $woffsety+($rh-$h)/2, 0, 0, $ww, $wh, $wopacity);
break;
case 'top-left':
$this->{$imagecopymerge}($out, $wdatanew, $woffsetx+($rw-$w)/2, $woffsety+($rh-$h)/2, 0, 0, $ww, $wh, $wopacity);
break;
case 'bottom-right':
$this->{$imagecopymerge}($out, $wdatanew, $rw-$woffsetx-$ww-($rw-$w)/2, $rh-$woffsety-$wh-($rh-$h)/2, 0, 0, $ww, $wh, $wopacity);
break;
case 'bottom-left':
$this->{$imagecopymerge}($out, $wdatanew, $woffsetx+($rw-$w)/2, $rh-$woffsety-$wh-($rh-$h)/2, 0, 0, $ww, $wh, $wopacity);
break;
case 'top':
$this->{$imagecopymerge}($out, $wdatanew, ($rw-$ww)/2, $woffsety+($rh-$h)/2, 0, 0, $ww, $wh, $wopacity);
break;
case 'bottom':
$this->{$imagecopymerge}($out, $wdatanew, ($rw-$ww)/2, $rh-$woffsety-$wh-($rh-$h)/2, 0, 0, $ww, $wh, $wopacity);
break;
case 'left':
$this->{$imagecopymerge}($out, $wdatanew, $woffsetx+($rw-$w)/2, ($rh-$wh)/2, 0, 0, $ww, $wh, $wopacity);
break;
case 'right':
$this->{$imagecopymerge}($out, $wdatanew, $rw-$woffsetx-$ww-($rw-$w)/2, ($rh-$wh)/2, 0, 0, $ww, $wh, $wopacity);
break;
default: break;
}
}
switch($size[2]) {
case 1: function_exists('imagegif') && imagegif($out, $this->file);
case 3: imagepng($out, $this->file); break;
case 2: imagejpeg($out, $this->file, $q); break;
}
imagedestroy($data);
imagedestroy($out);
}
}
//for merge with png alpha channel
function imagecopymerge($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct) {
// creating a cut resource
$cut = imagecreatetruecolor($src_w, $src_h);//$cut = $this->createImage($src_w, $src_h);
// copying relevant section from background to the cut resource
imagecopy($cut, $dst_im, 0, 0, $dst_x, $dst_y, $src_w, $src_h);
// copying relevant section from watermark to the cut resource
imagecopy($cut, $src_im, 0, 0, $src_x, $src_y, $src_w, $src_h);
// insert cut resource to destination image
imagecopymerge($dst_im, $cut, $dst_x, $dst_y, 0, 0, $src_w, $src_h, $pct);
}
//for merge two png images with alpha channel
function imagecopymerge_extra($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct) {
if(!$pct) return false;
$pct /= 100;
// Get image width and height
$w = imagesx($src_im);
$h = imagesy($src_im);
// Turn alpha blending off
imagealphablending($src_im, false);
// Find the most opaque pixel in the image (the one with the smallest alpha value)
$minalpha = 127;
for($x = 0; $x < $w; $x++) {
for($y = 0; $y < $h; $y++) {
$alpha = (imagecolorat($src_im, $x, $y) >> 24) & 0xFF;
if($alpha < $minalpha) {
$minalpha = $alpha;
}
}
}
// Loop through image pixels and modify alpha for each
for($x = 0; $x < $w; $x++) {
for($y = 0; $y < $h; $y++) {
// Get current alpha value (represents the TANSPARENCY!)
$colorxy = imagecolorat($src_im, $x, $y);
$alpha = ($colorxy >> 24) & 0xFF;
// Calculate new alpha
if($minalpha !== 127) {
$alpha = 127 + 127 * $pct * ($alpha - 127) / (127 - $minalpha);
} else {
$alpha += 127 * $pct;
}
// Get the color index with new alpha
$alphacolorxy = imagecolorallocatealpha($src_im, ($colorxy >> 16) & 0xFF, ($colorxy >> 8) & 0xFF, $colorxy & 0xFF, $alpha);
// Set pixel with the new color + opacity
if(!imagesetpixel($src_im, $x, $y, $alphacolorxy)) {
return false;
}
}
}
// The image copy
imagecopy($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h);
return true;
}
function getImageInfo($src, $imagick) {
$src = escapeshellarg($src);
$imagickIdentify = str_replace('convert', 'identify', $imagick);
$commands = array(
$imagick.' '.$src.' -format \'%w::%h::%[depth]::%e\' info:',
$imagick.' '.$src.' -format \'%w::%h::%z::%e\' info:',
$imagickIdentify.' -format \'%w::%h::%[depth]::%e\' '.$src,
$imagickIdentify.' -format \'%w::%h::%z::%e\' '.$src
);
$info = array();
foreach($commands as $c) {
$result = array();
exec($c, $result);
if(!empty($result)) {
$info = explode('::', $result[0]);
if(!empty($info[2])) break;
}
}
return $info;
}
function getPercent($p, $s) {
preg_match('/^([0-9]+)(%|px|Px|pX|PX)?$/is', $p, $matches);
if(isset($matches[2]) && $matches[2] == '%') {
$p = round($s*$matches[1]/100);
} else {
$p = $matches[1];
}
return $p;
}
function createImage($w, $h, $op = 127) {
$fCreate = function_exists('imagecreatetruecolor') ? 'imagecreatetruecolor' : 'imagecreate';
$out = call_user_func($fCreate, $w, $h);
if(function_exists('imageantialias')) { imageantialias($out, true); }
if(function_exists('imagealphablending')) { imagealphablending($out, false); }
if(function_exists('imagecolorallocatealpha')) {
// white transparent BG
$clr = imagecolorallocatealpha($out, 255, 255, 255, $op);
imagefill($out, 0, 0, $clr);
}
if(function_exists('imagesavealpha')) { imagesavealpha($out, true); }
if(function_exists('imagealphablending')) { imagealphablending($out, true); }
return $out;
}
function loadImage($src, $size = null) {
if($size === null) {
$size = getimagesize($src);
}
/*
1 GIF
2 JPG
3 PNG
4 SWF
5 PSD
6 BMP
7 TIFF (intel byte order)
8 TIFF (motorola byte order)
9 JPC
10 JP2
11 JPX
12 JB2
13 SWC
14 IFF
*/
switch($size[2]) {
case 1:
// unfortunately this function does not work on windows
// via the precompiled php installation :(
// it should work on all other systems however.
if(function_exists('imagecreatefromgif')) {
$data = imagecreatefromgif($src);
} else {
$data = false;
$this->logError('MagicToolbox ImageHelper :: Sorry, this server doesn\'t support <b>imagecreatefromgif()</b> function', true);
}
break;
case 2:
// php5 & gd2 bug. see issue #0024583 for details
@ini_set('gd.jpeg_ignore_warning', 1);
$data = imagecreatefromjpeg($src);
break;
case 3: $data = imagecreatefrompng($src); break;
// GD doesn't support other formats
default:
$data = false;
$this->logError('MagicToolbox ImageHelper :: Unsupported image type ('.$size[2].')', true);
}
return array($data, $size);
}
function isFileExists($f, $check = false) {
if(@file_exists($f) && (!$check || $check && @is_file($f))) {
return true;
} elseif(@exec('ls -l '.escapeshellarg($f).' | grep '.escapeshellarg($f))) {
return true;
} else {
return false;
}
}
function checkImagick($imagick) {
if((strtolower($imagick) != 'off') && !preg_match('/\bexec\b/is', ini_get('disable_functions'))) {
if(empty($imagick) || strtolower($imagick) == 'auto') {
$imagick = false;
// auto detect
if($this->isFileExists('/usr/bin/convert')) {
// found UNIX imagick tools in /usr/bin
$imagick = '/usr/bin/convert';
} else if($this->isFileExists('/usr/local/bin/convert')) {
// found UNIX imagick tools in /usr/local/bin
$imagick = '/usr/local/bin/convert';
} else {
$output = array();
@exec('compgen -ac', $output);
if(in_array('convert', $output) && in_array('identify', $output)) {
// UNIX imagick command line tools is available
$imagick = 'convert';
}
}
} else {
if(!preg_match('/convert$/s', $imagick)) {
if(!preg_match('/\/$/s', $imagick)) {
$imagick .= '/';
}
$imagick .= 'convert';
}
if(!$this->isFileExists($imagick)) {
$imagick = false;
}
}
} else {
$imagick = false;
}
if($imagick) {
// we should also check does we can run imagick bin file
@exec(escapeshellarg($imagick).' logo: /tmp/logo.png', $ret, $exitCode);
if($exitCode > 0) {
// got error, disable imagick
$imagick = false;
}
}
// check imagick version (for some reason, resize option dosn't working in imagick 5.x)
if($imagick) {
@exec(escapeshellarg($imagick).' --version', $ret);
foreach($ret as $line) {
if(preg_match('/version:/is', $line)) {
$v = preg_replace('/^.*?\s((?:[0-9]+\.){2}[0-9]+)(\-\d+)?\s.*$/is', '$1', $line);
if(version_compare($v, '6.0.0', '<')) {
$imagick = false;
}
break;
}
}
}
// temporary disabled
/*if(!$imagick && (in_array('Imagick', get_declared_classes()) || in_array('imagick', get_declared_classes()))) {
$imagick = 'native';
}*/
return $imagick;
}
function logError($message, $critical = false) {
if($this->options->checkValue('imagehelper-errors', 'Yes')) {
error_log($message);
}
if($critical) {
$this->errors = true;
}
//for debugging purposes
global $_GET;
if(isset($_GET['magic']) && $_GET['magic']) {
die($message);
}
}
}
}