1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348: 349: 350: 351: 352: 353: 354: 355: 356: 357: 358: 359: 360: 361: 362: 363: 364: 365: 366: 367: 368: 369: 370: 371: 372: 373: 374: 375: 376: 377: 378: 379: 380: 381: 382: 383: 384: 385: 386: 387: 388: 389: 390: 391: 392: 393: 394: 395: 396: 397: 398: 399: 400: 401: 402: 403: 404: 405: 406: 407: 408: 409: 410: 411: 412: 413: 414: 415: 416: 417: 418: 419: 420: 421: 422: 423: 424: 425: 426: 427: 428: 429: 430: 431: 432: 433: 434: 435: 436: 437: 438: 439: 440: 441: 442: 443: 444: 445: 446: 447: 448: 449: 450: 451: 452: 453: 454: 455: 456: 457: 458: 459: 460: 461: 462: 463: 464: 465: 466: 467: 468: 469: 470: 471: 472: 473: 474: 475: 476: 477: 478: 479: 480: 481: 482: 483: 484: 485: 486: 487: 488: 489: 490: 491: 492: 493: 494: 495: 496: 497: 498: 499: 500: 501: 502: 503: 504: 505: 506: 507: 508: 509: 510: 511: 512: 513: 514: 515: 516: 517: 518: 519: 520: 521: 522: 523: 524: 525: 526: 527: 528: 529: 530: 531: 532: 533: 534: 535: 536: 537: 538: 539: 540: 541: 542: 543: 544: 545: 546: 547: 548: 549: 550: 551: 552: 553: 554: 555: 556: 557: 558: 559: 560: 561: 562: 563: 564: 565: 566: 567: 568: 569: 570: 571: 572: 573: 574: 575: 576: 577: 578: 579: 580: 581: 582: 583: 584: 585: 586: 587: 588: 589: 590: 591: 592: 593: 594: 595: 596: 597: 598: 599: 600: 601: 602: 603: 604: 605: 606: 607: 608: 609: 610: 611: 612: 613: 614: 615: 616: 617: 618: 619: 620: 621: 622: 623: 624: 625: 626: 627: 628: 629: 630: 631: 632: 633: 634: 635: 636: 637: 638: 639: 640: 641: 642: 643: 644: 645: 646: 647: 648: 649: 650: 651: 652: 653: 654: 655: 656: 657: 658: 659: 660: 661: 662: 663: 664: 665: 666: 667: 668: 669: 670: 671: 672: 673: 674: 675: 676: 677: 678: 679:
<?php
/**
* library for image handling using the GD library of functions
* @package core
* @subpackage graphic-handlers\lib-gd
*/
// force UTF-8 Ø
$_zp_graphics_optionhandlers[] = new lib_GD_Options(); // register option handler
/**
* Option class for lib-GD
*
*/
class lib_GD_Options {
function __construct() {
}
/**
* Standard option interface
*
* @return array
*/
function getOptionsSupported() {
if (defined('GD_FREETYPE') && GD_FREETYPE) {
return array(gettext('GD TypeFace path') => array('key' => 'GD_FreeType_Path', 'type' => OPTION_TYPE_TEXTBOX,
'desc' => gettext('Supply the full path to your TrueType fonts.')));
} else {
return array();
}
}
function canLoadMsg() {
if (extension_loaded('gd')) {
return '';
} else {
return gettext('The <strong><em>GD</em></strong> extension is not available.');
}
}
}
if (!function_exists('zp_graphicsLibInfo')) {
/**
* Zenphoto image manipulation functions using the PHP GD library
*
*/
if (extension_loaded('gd')) { // only define the functions if we have the proper versions
$_lib_GD_info = array();
$info = gd_info();
$_lib_GD_info['Library'] = 'GD';
$_lib_GD_info['Library_desc'] = sprintf(gettext('PHP GD library <em>%s</em>'), $info['GD Version']);
$_lib_GD_info['FreeType'] = $info['FreeType Support'];
define('GD_FREETYPE', (bool) $_lib_GD_info['FreeType']);
unset($_lib_GD_info['FreeType']);
define('GD_FREETYPE_SAMPLE', 'The quick brown fox jumps over the lazy dog');
define('GD_FREETYPE_SAMPLE_CHARS', strlen('GD_FREETYPE_SAMPLE'));
$_gd_freetype_fonts = array(0);
$imgtypes = imagetypes();
$gd_imgtypes['GIF'] = ($imgtypes & IMG_GIF) ? 'gif' : false;
$gd_imgtypes['JPG'] = ($imgtypes & IMG_JPG) ? 'jpg' : false;
$gd_imgtypes['JPEG'] = ($imgtypes & IMG_JPG) ? 'jpg' : false;
$gd_imgtypes['PNG'] = ($imgtypes & IMG_PNG) ? 'png' : false;
$gd_imgtypes['WBMP'] = ($imgtypes & IMG_WBMP) ? 'jpg' : false;
$gd_imgtypes['WEBP'] = ($imgtypes & IMG_WEBP) ? 'webp' : false;
//Fix that unsupported types may be listed without suffix and then confuse e.g. the "cache as" option
foreach($gd_imgtypes as $key => $value) {
if($value) {
$_lib_GD_info[$key] = $value;
}
}
unset($gd_imgtypes);
unset($imgtypes);
unset($info);
if (DEBUG_IMAGE)
debugLog("Loading " . $_lib_GD_info['Library']);
/**
* Takes an image filename and returns a GD Image using the correct function
* for the image's format (imagecreatefrom*). Supports JPEG, GIF, and PNG.
* @param string $imagefile the full path and filename of the image to load.
* @return image the loaded GD image object.
*
*/
function zp_imageGet($imgfile) {
$ext = getSuffix($imgfile);
switch ($ext) {
case 'png':
return imagecreatefrompng($imgfile);
case 'wbmp':
return imagecreatefromwbmp($imgfile);
case 'jpeg':
case 'jpg':
return imagecreatefromjpeg($imgfile);
case 'gif':
return imagecreatefromgif($imgfile);
case 'webp':
return imagecreatefromwebp($imgfile);
}
return false;
}
/**
* outputs an image resource as a given type
*
* @param resource $im
* @param string $type
* @param string $filename
* @param int $qual
*/
function zp_imageOutput($im, $type, $filename = NULL, $qual = 75) {
$qual = max(min($qual, 100), 0);
if (getOption('image_interlace')) {
imageinterlace($im, true);
}
switch ($type) {
case 'png':
$qual = max(0, 9 - round($qual / 10));
return imagepng($im, $filename, $qual);
case 'wbmp':
return imagewbmp($im, $filename);
case 'jpeg':
case 'jpg':
return imagejpeg($im, $filename, $qual);
case 'gif':
return imagegif($im, $filename);
case 'webp':
return imagewebp($im, $filename, $qual);
}
return false;
}
/**
* Creates a true color image
*
* @param int $w the width of the image
* @param int $h the height of the image
* @param bool $truecolor True to create a true color image, false for usage with palette images like gifs
* @return image
*/
function zp_createImage($w, $h, $truecolor = true) {
if ($truecolor) {
return imagecreatetruecolor($w, $h);
} else {
return imagecreate($w, $h);
}
}
/**
* Fills an image area
*
* @param image $image
* @param int $x
* @param int $y
* @param color $color
* @return bool
*/
function zp_imageFill($image, $x, $y, $color) {
return imagefill($image, $x, $y, $color);
}
/**
* Sets the transparency color
*
* @param image $image
* @param color $color
* @return bool
*/
function zp_imageColorTransparent($image, $color) {
return imagecolortransparent($image, $color);
}
/**
* copies an image canvas
*
* @param image $imgCanvas source canvas
* @param image $img destination canvas
* @param int $dest_x destination x
* @param int $dest_y destination y
* @param int $src_x source x
* @param int $src_y source y
* @param int $w width
* @param int $h height
*/
function zp_copyCanvas($imgCanvas, $img, $dest_x, $dest_y, $src_x, $src_y, $w, $h) {
return imageCopy($imgCanvas, $img, $dest_x, $dest_y, $src_x, $src_y, $w, $h);
}
/**
* resamples an image to a new copy
*
* @param resource $dst_image
* @param resource $src_image
* @param int $dst_x
* @param int $dst_y
* @param int $src_x
* @param int $src_y
* @param int $dst_w
* @param int $dst_h
* @param int $src_w
* @param int $src_h
* @return bool
*/
function zp_resampleImage($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) {
return imagecopyresampled($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);
}
/**
* Sharpens an image using an Unsharp Mask filter.
*
* Original description from the author:
*
* WARNING ! Due to a known bug in PHP 4.3.2 this script is not working well in this
* version. The sharpened images get too dark. The bug is fixed in version 4.3.3.
*
* From version 2 (July 17 2006) the script uses the imageconvolution function in
* PHP version >= 5.1, which improves the performance considerably.
*
* Unsharp masking is a traditional darkroom technique that has proven very
* suitable for digital imaging. The principle of unsharp masking is to create a
* blurred copy of the image and compare it to the underlying original. The
* difference in colour values between the two images is greatest for the pixels
* near sharp edges. When this difference is subtracted from the original image,
* the edges will be accentuated.
*
* The Amount parameter simply says how much of the effect you want. 100 is
* 'normal'. Radius is the radius of the blurring circle of the mask. 'Threshold'
* is the least difference in colour values that is allowed between the original
* and the mask. In practice this means that low-contrast areas of the picture are
* left unrendered whereas edges are treated normally. This is good for pictures of
* e.g. skin or blue skies.
*
* Any suggenstions for improvement of the algorithm, expecially regarding the
* speed and the roundoff errors in the Gaussian blur process, are welcome.
*
* Permission to license this code under the GPL was granted by the author on 2/12/2007.
*
* @param image $img the GD format image to sharpen. This is not a URL string, but
* should be the result of a GD image function.
* @param int $amount the strength of the sharpening effect. Nominal values are between 0 and 100.
* @param int $radius the pixel radius of the sharpening mask. A smaller radius sharpens smaller
* details, and a larger radius sharpens larger details.
* @param int $threshold the color difference threshold required for sharpening. A low threshold
* sharpens all edges including faint ones, while a higher threshold only sharpens more distinct edges.
* @return image the input image with the specified sharpening applied.
*/
function zp_imageUnsharpMask($img, $amount, $radius, $threshold) {
/*
Unsharp Mask for PHP - version 2.0
Unsharp mask algorithm by Torstein Hønsi 2003-06.
Please leave this notice.
*/
// $img is an image that is already created within php using
// imgcreatetruecolor. No url! $img must be a truecolor image.
// Attempt to calibrate the parameters to Photoshop:
if ($amount > 500)
$amount = 500;
$amount = $amount * 0.016;
if ($radius > 50)
$radius = 50;
$radius = $radius * 2;
if ($threshold > 255)
$threshold = 255;
$radius = abs(round($radius)); // Only integers make sense.
if ($radius == 0)
return $img;
$w = imagesx($img);
$h = imagesy($img);
$imgCanvas = imagecreatetruecolor($w, $h);
$imgCanvas2 = imagecreatetruecolor($w, $h);
imagecopy($imgCanvas, $img, 0, 0, 0, 0, $w, $h);
imagecopy($imgCanvas2, $img, 0, 0, 0, 0, $w, $h);
imageBlurGD($imgCanvas, $imgCanvas2, $radius, $w, $h);
// Calculate the difference between the blurred pixels and the original
// and set the pixels
for ($x = 0; $x < $w; $x++) { // each row
for ($y = 0; $y < $h; $y++) { // each pixel
$rgbOrig = ImageColorAt($imgCanvas2, $x, $y);
$rOrig = (($rgbOrig >> 16) & 0xFF);
$gOrig = (($rgbOrig >> 8) & 0xFF);
$bOrig = ($rgbOrig & 0xFF);
$rgbBlur = ImageColorAt($imgCanvas, $x, $y);
$rBlur = (($rgbBlur >> 16) & 0xFF);
$gBlur = (($rgbBlur >> 8) & 0xFF);
$bBlur = ($rgbBlur & 0xFF);
// When the masked pixels differ less from the original
// than the threshold specifies, they are set to their original value.
$rNew = (abs($rOrig - $rBlur) >= $threshold) ? max(0, min(255, ($amount * ($rOrig - $rBlur)) + $rOrig)) : $rOrig;
$gNew = (abs($gOrig - $gBlur) >= $threshold) ? max(0, min(255, ($amount * ($gOrig - $gBlur)) + $gOrig)) : $gOrig;
$bNew = (abs($bOrig - $bBlur) >= $threshold) ? max(0, min(255, ($amount * ($bOrig - $bBlur)) + $bOrig)) : $bOrig;
if (($rOrig != $rNew) || ($gOrig != $gNew) || ($bOrig != $bNew)) {
$pixCol = ImageColorAllocate($img, $rNew, $gNew, $bNew);
ImageSetPixel($img, $x, $y, $pixCol);
}
}
}
return $img;
}
/**
* Resize a PNG file with transparency to given dimensions
* and still retain the alpha channel information
*
* Note: You have to apply zp_resampleImage() afterwards as the function does not handle this internally
*
* @param image $src
* @param int $w
* @param int $h
* @return image
*/
function zp_imageResizeAlpha($src, $w, $h) {
if ($src) {
imagealphablending($src, false);
imagesavealpha($src, true);
$transparentindex = imagecolorallocatealpha($src, 255, 255, 255, 127);
imagefill($src, 0, 0, $transparentindex);
}
return $src;
}
/**
* Resize a GIF file with transparency to given dimensions
* and still retain the transparency information
*
* Note: You have to apply zp_resampleImage() afterwards as the function does not handle this internally
*
* @since ZenphotoCMS 1.5.2
*
* @param image $src
* @param int $w
* @param int $h
* @return image
*/
function zp_imageResizeTransparent($src, $w, $h) {
if ($src) {
$transparent = zp_colorAllocate($src, 255, 255, 255);
zp_imageColorTransparent($src, $transparent);
}
return $src;
}
/**
* Returns true if GD library is configued with image rotation suppord
*
* @return bool
*/
function zp_imageCanRotate() {
return function_exists('imagerotate');
}
/**
* Rotates an image resource according to its Orientation
* NB: requires the imagarotate function to be configured
*
* @param resource $im
* @param int $rotate
* @return resource
*/
function zp_rotateImage($im, $rotate) {
$newim_rot = imagerotate($im, $rotate, 0);
imagedestroy($im);
return $newim_rot;
}
/**
* Returns the image height and width
*
* @param string $filename
* @return array
*/
function zp_imageDims($filename) {
$imageinfo = NULL;
$rslt = getimagesize($filename, $imageinfo);
if (is_array($rslt)) {
return array('width' => $rslt[0], 'height' => $rslt[1]);
} else {
return false;
}
}
/**
* Returns the IPTC data of an image
*
* @param string $filename
* @return string
*/
function zp_imageIPTC($filename) {
$imageinfo = NULL;
$rslt = getimagesize($filename, $imageinfo);
if (is_array($rslt) && isset($imageinfo['APP13'])) {
return $imageinfo['APP13'];
} else {
return false;
}
}
/**
* Returns the width of an image resource
*
* @param resource $im
* @return int
*/
function zp_imageWidth($im) {
return imagesx($im);
}
/**
* Returns the height of an image resource
*
* @param resource $im
* @return int
*/
function zp_imageHeight($im) {
return imagesy($im);
}
/**
* Does a copy merge of two image resources
*
* @param resource $dst_im
* @param resource $src_im
* @param int $dst_x
* @param int $dst_y
* @param int $src_x
* @param int $src_y
* @param int $src_w
* @param int $src_h
* @param int $pct
* @return bool
*/
function zp_imageMerge($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct) {
return imagecopymerge($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct);
}
/**
* Creates a grayscale image
*
* @param resource $image
* @return resource
*/
function zp_imageGray($image) {
$img_height = imagesy($image);
$img_width = imagesx($image);
for ($y = 0; $y < $img_height; $y++) {
for ($x = 0; $x < $img_width; $x++) {
$gray = (ImageColorAt($image, $x, $y) >> 8) & 0xFF;
imagesetpixel($image, $x, $y, ImageColorAllocate($image, $gray, $gray, $gray));
}
}
}
/**
* destroys an image resource
*
* @param resource $im
* @return bool
*/
function zp_imageKill($im) {
return imagedestroy($im);
}
/**
* Returns an RGB color identifier
*
* @param resource $image
* @param int $red
* @param int $green
* @param int $blue
* @return int
*/
function zp_colorAllocate($image, $red, $green, $blue) {
return imagecolorallocate($image, $red, $green, $blue);
}
/**
* Rencers a string into the image
*
* @param resource $image
* @param int $font
* @param int $x
* @param int $y
* @param string $string
* @param int $color
* @return bool
*/
function zp_writeString($image, $font, $x, $y, $string, $color) {
global $_gd_freetype_fonts;
if ($font > 0) {
return imagestring($image, $font, $x, $y, $string, $color);
} else {
$font = abs($font);
$fontfile = $_gd_freetype_fonts[$font]['path'];
$size = $_gd_freetype_fonts[abs($font)]['size'];
$bbox = imagettfbbox($_gd_freetype_fonts[$font]['size'], 0, $_gd_freetype_fonts[$font]['path'], GD_FREETYPE_SAMPLE);
$w = (int) (($bbox[2] - $bbox[0]) / GD_FREETYPE_SAMPLE_CHARS);
$h = $bbox[1] - $bbox[7];
$rslt = imagettftext($image, $size, 0, $x + $w, $y + $h, $color, $fontfile, $string);
return is_array($rslt);
}
}
/**
* Creates a rectangle
*
* @param resource $image
* @param int $x1
* @param int $y1
* @param int $x2
* @param int $y2
* @param int $color
* @return bool
*/
function zp_drawRectangle($image, $x1, $y1, $x2, $y2, $color) {
return imagerectangle($image, $x1, $y1, $x2, $y2, $color);
}
/**
* Returns array of graphics library info
*
* @return array
*/
function zp_graphicsLibInfo() {
global $_lib_GD_info;
return $_lib_GD_info;
}
/**
* Returns a list of available fonts
*
* @return array
*/
function zp_getFonts() {
global $_gd_fontlist;
if (!is_array($_gd_fontlist)) {
$_gd_fontlist = array('system' => '');
$curdir = getcwd();
$basefile = SERVERPATH . '/' . USER_PLUGIN_FOLDER . 'gd_fonts/';
if (is_dir($basefile)) {
chdir($basefile);
$filelist = safe_glob('*.gdf');
foreach ($filelist as $file) {
$key = filesystemToInternal(str_replace('.gdf', '', $file));
$_gd_fontlist[$key] = $basefile . '/' . $file;
}
}
chdir($basefile = SERVERPATH . '/' . ZENFOLDER . '/gd_fonts');
$filelist = safe_glob('*.gdf');
foreach ($filelist as $file) {
$key = filesystemToInternal(preg_replace('/\.gdf/i', '', $file));
$_gd_fontlist[$key] = $basefile . '/' . $file;
}
if (GD_FREETYPE) {
$basefile = rtrim(getOption('GD_FreeType_Path') . '/');
if (is_dir($basefile)) {
chdir($basefile);
$filelist = safe_glob('*.ttf');
foreach ($filelist as $file) {
$key = filesystemToInternal($file);
$_gd_fontlist[$key] = $basefile . '/' . $file;
}
}
}
chdir($curdir);
}
return $_gd_fontlist;
}
/**
* Loads a font and returns its font id
*
* @param string $font
* @return int
*/
function zp_imageLoadFont($font = NULL, $size = 18) {
global $_gd_freetype_fonts;
if (!empty($font)) {
if (file_exists($font)) {
switch (getSuffix($font)) {
case 'gdf':
return imageloadfont($font);
case 'ttf':
$index = -count($_gd_freetype_fonts);
array_push($_gd_freetype_fonts, array('path' => $font, 'size' => $size));
return $index;
}
}
}
return 5; // default to the largest inbuilt font
}
/**
* Returns the font width in pixels
*
* @param int $font
* @return int
*/
function zp_imageFontWidth($font) {
global $_gd_freetype_fonts;
if ($font > 0) {
return imagefontwidth($font);
} else {
$font = abs($font);
$bbox = imagettfbbox($_gd_freetype_fonts[$font]['size'], 0, $_gd_freetype_fonts[$font]['path'], GD_FREETYPE_SAMPLE);
$w = (int) (($bbox[2] - $bbox[0]) / GD_FREETYPE_SAMPLE_CHARS);
return $w;
}
}
/**
* Returns the font height in pixels
*
* @param int $font
* @return int
*/
function zp_imageFontHeight($font) {
global $_gd_freetype_fonts;
if ($font > 0) {
return imagefontheight($font);
} else {
$font = abs($font);
$bbox = imagettfbbox($_gd_freetype_fonts[$font]['size'], 0, $_gd_freetype_fonts[$font]['path'], GD_FREETYPE_SAMPLE);
$h = $bbox[1] - $bbox[7];
return $h;
}
}
/**
* provides image blur support for lib-GD:zp_imageUnsharpMask
*
* @param image $imgCanvas
* @param int $radius
* @param int $w
* @param int $h
*/
function imageBlurGD($imgCanvas, $imgCanvas2, $radius, $w, $h) {
// Gaussian blur matrix:
// 1 2 1
// 2 4 2
// 1 2 1
//////////////////////////////////////////////////
for ($i = 0; $i < $radius; $i++) {
if (function_exists('imageconvolution')) { // PHP >= 5.1
$matrix = array(
array(1, 2, 1),
array(2, 4, 2),
array(1, 2, 1)
);
imageconvolution($imgCanvas, $matrix, 16, 0);
}
}
}
/**
*
* creates an image from an image stream
* @param $string
*/
function zp_imageFromString($string) {
return imagecreatefromstring($string);
}
}
}
?>