PageRenderTime 103ms CodeModel.GetById 22ms app.highlight 46ms RepoModel.GetById 23ms app.codeStats 0ms

/lib/phpthumb/phpthumb.filters.php

https://bitbucket.org/blackidanandteam/blacktheme
PHP | 1546 lines | 1182 code | 235 blank | 129 comment | 241 complexity | 900f2354095ab41bfde680d305f4f382 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2//////////////////////////////////////////////////////////////
   3///  phpThumb() by James Heinrich <info@silisoftware.com>   //
   4//        available at http://phpthumb.sourceforge.net     ///
   5//////////////////////////////////////////////////////////////
   6///                                                         //
   7// phpthumb.filters.php - image processing filter functions //
   8//                                                         ///
   9//////////////////////////////////////////////////////////////
  10
  11class phpthumb_filters {
  12
  13	var $phpThumbObject = null;
  14
  15	function phpthumb_filters() {
  16		return true;
  17	}
  18
  19	function ApplyMask(&$gdimg_mask, &$gdimg_image) {
  20		if (phpthumb_functions::gd_version() < 2) {
  21			$this->DebugMessage('Skipping ApplyMask() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
  22			return false;
  23		}
  24		if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.2', '>=')) {
  25
  26			$this->DebugMessage('Using alpha ApplyMask() technique', __FILE__, __LINE__);
  27			if ($gdimg_mask_resized = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg_image), ImageSY($gdimg_image))) {
  28
  29				ImageCopyResampled($gdimg_mask_resized, $gdimg_mask, 0, 0, 0, 0, ImageSX($gdimg_image), ImageSY($gdimg_image), ImageSX($gdimg_mask), ImageSY($gdimg_mask));
  30				if ($gdimg_mask_blendtemp = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg_image), ImageSY($gdimg_image))) {
  31
  32					$color_background = ImageColorAllocate($gdimg_mask_blendtemp, 0, 0, 0);
  33					ImageFilledRectangle($gdimg_mask_blendtemp, 0, 0, ImageSX($gdimg_mask_blendtemp), ImageSY($gdimg_mask_blendtemp), $color_background);
  34					ImageAlphaBlending($gdimg_mask_blendtemp, false);
  35					ImageSaveAlpha($gdimg_mask_blendtemp, true);
  36					for ($x = 0; $x < ImageSX($gdimg_image); $x++) {
  37						for ($y = 0; $y < ImageSY($gdimg_image); $y++) {
  38							//$RealPixel = phpthumb_functions::GetPixelColor($gdimg_mask_blendtemp, $x, $y);
  39							$RealPixel = phpthumb_functions::GetPixelColor($gdimg_image, $x, $y);
  40							$MaskPixel = phpthumb_functions::GrayscalePixel(phpthumb_functions::GetPixelColor($gdimg_mask_resized, $x, $y));
  41							$MaskAlpha = 127 - (floor($MaskPixel['red'] / 2) * (1 - ($RealPixel['alpha'] / 127)));
  42							$newcolor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_mask_blendtemp, $RealPixel['red'], $RealPixel['green'], $RealPixel['blue'], $MaskAlpha);
  43							ImageSetPixel($gdimg_mask_blendtemp, $x, $y, $newcolor);
  44						}
  45					}
  46					ImageAlphaBlending($gdimg_image, false);
  47					ImageSaveAlpha($gdimg_image, true);
  48					ImageCopy($gdimg_image, $gdimg_mask_blendtemp, 0, 0, 0, 0, ImageSX($gdimg_mask_blendtemp), ImageSY($gdimg_mask_blendtemp));
  49					ImageDestroy($gdimg_mask_blendtemp);
  50
  51				} else {
  52					$this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__);
  53				}
  54				ImageDestroy($gdimg_mask_resized);
  55
  56			} else {
  57				$this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__);
  58			}
  59
  60		} else {
  61			// alpha merging requires PHP v4.3.2+
  62			$this->DebugMessage('Skipping ApplyMask() technique because PHP is v"'.phpversion().'"', __FILE__, __LINE__);
  63		}
  64		return true;
  65	}
  66
  67
  68    function Bevel(&$gdimg, $width, $hexcolor1, $hexcolor2) {
  69        $width     = ($width     ? $width     : 5);
  70        $hexcolor1 = ($hexcolor1 ? $hexcolor1 : 'FFFFFF');
  71        $hexcolor2 = ($hexcolor2 ? $hexcolor2 : '000000');
  72
  73        ImageAlphaBlending($gdimg, true);
  74        for ($i = 0; $i < $width; $i++) {
  75            $alpha = round(($i / $width) * 127);
  76            $color1 = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor1, false, $alpha);
  77            $color2 = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor2, false, $alpha);
  78
  79            ImageLine($gdimg,                   $i,                   $i + 1,                   $i, ImageSY($gdimg) - $i - 1, $color1); // left
  80            ImageLine($gdimg,                   $i,                   $i    , ImageSX($gdimg) - $i,                   $i    , $color1); // top
  81            ImageLine($gdimg, ImageSX($gdimg) - $i, ImageSY($gdimg) - $i - 1, ImageSX($gdimg) - $i,                   $i + 1, $color2); // right
  82            ImageLine($gdimg, ImageSX($gdimg) - $i, ImageSY($gdimg) - $i    ,                   $i, ImageSY($gdimg) - $i    , $color2); // bottom
  83        }
  84        return true;
  85    }
  86
  87
  88	function Blur(&$gdimg, $radius=0.5) {
  89		// Taken from Torstein H�nsi's phpUnsharpMask (see phpthumb.unsharp.php)
  90
  91		$radius = round(max(0, min($radius, 50)) * 2);
  92		if (!$radius) {
  93			return false;
  94		}
  95
  96		$w = ImageSX($gdimg);
  97		$h = ImageSY($gdimg);
  98		if ($imgBlur = ImageCreateTrueColor($w, $h)) {
  99			// Gaussian blur matrix:
 100			//	1	2	1
 101			//	2	4	2
 102			//	1	2	1
 103
 104			// Move copies of the image around one pixel at the time and merge them with weight
 105			// according to the matrix. The same matrix is simply repeated for higher radii.
 106			for ($i = 0; $i < $radius; $i++)	{
 107				ImageCopy     ($imgBlur, $gdimg, 0, 0, 1, 1, $w - 1, $h - 1);            // up left
 108				ImageCopyMerge($imgBlur, $gdimg, 1, 1, 0, 0, $w,     $h,     50.00000);  // down right
 109				ImageCopyMerge($imgBlur, $gdimg, 0, 1, 1, 0, $w - 1, $h,     33.33333);  // down left
 110				ImageCopyMerge($imgBlur, $gdimg, 1, 0, 0, 1, $w,     $h - 1, 25.00000);  // up right
 111				ImageCopyMerge($imgBlur, $gdimg, 0, 0, 1, 0, $w - 1, $h,     33.33333);  // left
 112				ImageCopyMerge($imgBlur, $gdimg, 1, 0, 0, 0, $w,     $h,     25.00000);  // right
 113				ImageCopyMerge($imgBlur, $gdimg, 0, 0, 0, 1, $w,     $h - 1, 20.00000);  // up
 114				ImageCopyMerge($imgBlur, $gdimg, 0, 1, 0, 0, $w,     $h,     16.666667); // down
 115				ImageCopyMerge($imgBlur, $gdimg, 0, 0, 0, 0, $w,     $h,     50.000000); // center
 116				ImageCopy     ($gdimg, $imgBlur, 0, 0, 0, 0, $w,     $h);
 117			}
 118			return true;
 119		}
 120		return false;
 121	}
 122
 123
 124	function BlurGaussian(&$gdimg) {
 125		if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) {
 126			if (ImageFilter($gdimg, IMG_FILTER_GAUSSIAN_BLUR)) {
 127				return true;
 128			}
 129			$this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_GAUSSIAN_BLUR)', __FILE__, __LINE__);
 130			// fall through and try it the hard way
 131		}
 132		$this->DebugMessage('FAILED: phpthumb_filters::BlurGaussian($gdimg) [using phpthumb_filters::Blur() instead]', __FILE__, __LINE__);
 133		return phpthumb_filters::Blur($gdimg, 0.5);
 134	}
 135
 136
 137	function BlurSelective(&$gdimg) {
 138		if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) {
 139			if (ImageFilter($gdimg, IMG_FILTER_SELECTIVE_BLUR)) {
 140				return true;
 141			}
 142			$this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_SELECTIVE_BLUR)', __FILE__, __LINE__);
 143			// fall through and try it the hard way
 144		}
 145		// currently not implemented "the hard way"
 146		$this->DebugMessage('FAILED: phpthumb_filters::BlurSelective($gdimg) [function not implemented]', __FILE__, __LINE__);
 147		return false;
 148	}
 149
 150
 151	function Brightness(&$gdimg, $amount=0) {
 152		if ($amount == 0) {
 153			return true;
 154		}
 155		$amount = max(-255, min(255, $amount));
 156
 157		if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) {
 158			if (ImageFilter($gdimg, IMG_FILTER_BRIGHTNESS, $amount)) {
 159				return true;
 160			}
 161			$this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_BRIGHTNESS, '.$amount.')', __FILE__, __LINE__);
 162			// fall through and try it the hard way
 163		}
 164
 165		$scaling = (255 - abs($amount)) / 255;
 166		$baseamount = (($amount > 0) ? $amount : 0);
 167		for ($x = 0; $x < ImageSX($gdimg); $x++) {
 168			for ($y = 0; $y < ImageSY($gdimg); $y++) {
 169				$OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y);
 170				foreach ($OriginalPixel as $key => $value) {
 171					$NewPixel[$key] = round($baseamount + ($OriginalPixel[$key] * $scaling));
 172				}
 173				$newColor = ImageColorAllocate($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue']);
 174				ImageSetPixel($gdimg, $x, $y, $newColor);
 175			}
 176		}
 177		return true;
 178	}
 179
 180
 181	function Contrast(&$gdimg, $amount=0) {
 182		if ($amount == 0) {
 183			return true;
 184		}
 185		$amount = max(-255, min(255, $amount));
 186
 187		if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) {
 188			// ImageFilter(IMG_FILTER_CONTRAST) has range +100 to -100 (positive numbers make it darker!)
 189			$amount = ($amount / 255) * -100;
 190			if (ImageFilter($gdimg, IMG_FILTER_CONTRAST, $amount)) {
 191				return true;
 192			}
 193			$this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_CONTRAST, '.$amount.')', __FILE__, __LINE__);
 194			// fall through and try it the hard way
 195		}
 196
 197		if ($amount > 0) {
 198			$scaling = 1 + ($amount / 255);
 199		} else {
 200			$scaling = (255 - abs($amount)) / 255;
 201		}
 202		for ($x = 0; $x < ImageSX($gdimg); $x++) {
 203			for ($y = 0; $y < ImageSY($gdimg); $y++) {
 204				$OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y);
 205				foreach ($OriginalPixel as $key => $value) {
 206					$NewPixel[$key] = min(255, max(0, round($OriginalPixel[$key] * $scaling)));
 207				}
 208				$newColor = ImageColorAllocate($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue']);
 209				ImageSetPixel($gdimg, $x, $y, $newColor);
 210			}
 211		}
 212	}
 213
 214
 215	function Colorize(&$gdimg, $amount, $targetColor) {
 216		$amount      = (is_numeric($amount)                          ? $amount      : 25);
 217		$amountPct   = $amount / 100;
 218		$targetColor = (phpthumb_functions::IsHexColor($targetColor) ? $targetColor : 'gray');
 219
 220		if ($amount == 0) {
 221			return true;
 222		}
 223
 224		if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) {
 225			if ($targetColor == 'gray') {
 226				$targetColor = '808080';
 227			}
 228			$r = round($amountPct * hexdec(substr($targetColor, 0, 2)));
 229			$g = round($amountPct * hexdec(substr($targetColor, 2, 2)));
 230			$b = round($amountPct * hexdec(substr($targetColor, 4, 2)));
 231			if (ImageFilter($gdimg, IMG_FILTER_COLORIZE, $r, $g, $b)) {
 232				return true;
 233			}
 234			$this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_COLORIZE)', __FILE__, __LINE__);
 235			// fall through and try it the hard way
 236		}
 237
 238		// overridden below for grayscale
 239		if ($targetColor != 'gray') {
 240			$TargetPixel['red']   = hexdec(substr($targetColor, 0, 2));
 241			$TargetPixel['green'] = hexdec(substr($targetColor, 2, 2));
 242			$TargetPixel['blue']  = hexdec(substr($targetColor, 4, 2));
 243		}
 244
 245		for ($x = 0; $x < ImageSX($gdimg); $x++) {
 246			for ($y = 0; $y < ImageSY($gdimg); $y++) {
 247				$OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y);
 248				if ($targetColor == 'gray') {
 249					$TargetPixel = phpthumb_functions::GrayscalePixel($OriginalPixel);
 250				}
 251				foreach ($TargetPixel as $key => $value) {
 252					$NewPixel[$key] = round(max(0, min(255, ($OriginalPixel[$key] * ((100 - $amount) / 100)) + ($TargetPixel[$key] * $amountPct))));
 253				}
 254				//$newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue'], $OriginalPixel['alpha']);
 255				$newColor = ImageColorAllocate($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue']);
 256				ImageSetPixel($gdimg, $x, $y, $newColor);
 257			}
 258		}
 259		return true;
 260	}
 261
 262
 263	function Crop(&$gdimg, $left=0, $right=0, $top=0, $bottom=0) {
 264		if (!$left && !$right && !$top && !$bottom) {
 265			return true;
 266		}
 267		$oldW = ImageSX($gdimg);
 268		$oldH = ImageSY($gdimg);
 269		if (($left   > 0) && ($left   < 1)) { $left   = round($left   * $oldW); }
 270		if (($right  > 0) && ($right  < 1)) { $right  = round($right  * $oldW); }
 271		if (($top    > 0) && ($top    < 1)) { $top    = round($top    * $oldH); }
 272		if (($bottom > 0) && ($bottom < 1)) { $bottom = round($bottom * $oldH); }
 273		$right  = min($oldW - $left - 1, $right);
 274		$bottom = min($oldH - $top  - 1, $bottom);
 275		$newW = $oldW - $left - $right;
 276		$newH = $oldH - $top  - $bottom;
 277
 278		if ($imgCropped = ImageCreateTrueColor($newW, $newH)) {
 279			ImageCopy($imgCropped, $gdimg, 0, 0, $left, $top, $newW, $newH);
 280			if ($gdimg = ImageCreateTrueColor($newW, $newH)) {
 281				ImageCopy($gdimg, $imgCropped, 0, 0, 0, 0, $newW, $newH);
 282				ImageDestroy($imgCropped);
 283				return true;
 284			}
 285			ImageDestroy($imgCropped);
 286		}
 287		return false;
 288	}
 289
 290
 291	function Desaturate(&$gdimg, $amount, $color='') {
 292		if ($amount == 0) {
 293			return true;
 294		}
 295		return phpthumb_filters::Colorize($gdimg, $amount, (phpthumb_functions::IsHexColor($color) ? $color : 'gray'));
 296	}
 297
 298
 299	function DropShadow(&$gdimg, $distance, $width, $hexcolor, $angle, $alpha) {
 300		if (phpthumb_functions::gd_version() < 2) {
 301			return false;
 302		}
 303		$distance =                 ($distance ? $distance : 10);
 304		$width    =                 ($width    ? $width    : 10);
 305		$hexcolor =                 ($hexcolor ? $hexcolor : '000000');
 306		$angle    =                 ($angle    ? $angle    : 225) % 360;
 307		$alpha    = max(0, min(100, ($alpha    ? $alpha    : 100)));
 308
 309		if ($alpha <= 0) {
 310			// invisible shadow, nothing to do
 311			return true;
 312		}
 313		if ($distance <= 0) {
 314			// shadow completely obscured by source image, nothing to do
 315			return true;
 316		}
 317
 318		$width_shadow  = cos(deg2rad($angle)) * ($distance + $width);
 319		$height_shadow = sin(deg2rad($angle)) * ($distance + $width);
 320
 321		$scaling = min(ImageSX($gdimg) / (ImageSX($gdimg) + abs($width_shadow)), ImageSY($gdimg) / (ImageSY($gdimg) + abs($height_shadow)));
 322
 323		for ($i = 0; $i < $width; $i++) {
 324			$WidthAlpha[$i] = (abs(($width / 2) - $i) / $width);
 325			$Offset['x'] = cos(deg2rad($angle)) * ($distance + $i);
 326			$Offset['y'] = sin(deg2rad($angle)) * ($distance + $i);
 327		}
 328
 329		$tempImageWidth  = ImageSX($gdimg)  + abs($Offset['x']);
 330		$tempImageHeight = ImageSY($gdimg) + abs($Offset['y']);
 331
 332		if ($gdimg_dropshadow_temp = phpthumb_functions::ImageCreateFunction($tempImageWidth, $tempImageHeight)) {
 333
 334			ImageAlphaBlending($gdimg_dropshadow_temp, false);
 335			ImageSaveAlpha($gdimg_dropshadow_temp, true);
 336			$transparent1 = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_dropshadow_temp, 0, 0, 0, 127);
 337			ImageFill($gdimg_dropshadow_temp, 0, 0, $transparent1);
 338
 339			for ($x = 0; $x < ImageSX($gdimg); $x++) {
 340				for ($y = 0; $y < ImageSY($gdimg); $y++) {
 341					$PixelMap[$x][$y] = phpthumb_functions::GetPixelColor($gdimg, $x, $y);
 342				}
 343			}
 344			for ($x = 0; $x < $tempImageWidth; $x++) {
 345				for ($y = 0; $y < $tempImageHeight; $y++) {
 346					//for ($i = 0; $i < $width; $i++) {
 347					for ($i = 0; $i < 1; $i++) {
 348						if (!isset($PixelMap[$x][$y]['alpha']) || ($PixelMap[$x][$y]['alpha'] > 0)) {
 349							if (isset($PixelMap[$x + $Offset['x']][$y + $Offset['y']]['alpha']) && ($PixelMap[$x + $Offset['x']][$y + $Offset['y']]['alpha'] < 127)) {
 350								$thisColor = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor, false, $PixelMap[$x + $Offset['x']][$y + $Offset['y']]['alpha']);
 351								ImageSetPixel($gdimg_dropshadow_temp, $x, $y, $thisColor);
 352							}
 353						}
 354					}
 355				}
 356			}
 357
 358			ImageAlphaBlending($gdimg_dropshadow_temp, true);
 359			for ($x = 0; $x < ImageSX($gdimg); $x++) {
 360				for ($y = 0; $y < ImageSY($gdimg); $y++) {
 361					if ($PixelMap[$x][$y]['alpha'] < 127) {
 362						$thisColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_dropshadow_temp, $PixelMap[$x][$y]['red'], $PixelMap[$x][$y]['green'], $PixelMap[$x][$y]['blue'], $PixelMap[$x][$y]['alpha']);
 363						ImageSetPixel($gdimg_dropshadow_temp, $x, $y, $thisColor);
 364					}
 365				}
 366			}
 367
 368			ImageSaveAlpha($gdimg, true);
 369			ImageAlphaBlending($gdimg, false);
 370			//$this->is_alpha = true;
 371			$transparent2 = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 0, 0, 0, 127);
 372			ImageFilledRectangle($gdimg, 0, 0, ImageSX($gdimg), ImageSY($gdimg), $transparent2);
 373			ImageCopyResampled($gdimg, $gdimg_dropshadow_temp, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg), ImageSX($gdimg_dropshadow_temp), ImageSY($gdimg_dropshadow_temp));
 374
 375			ImageDestroy($gdimg_dropshadow_temp);
 376		}
 377		return true;
 378	}
 379
 380
 381	function EdgeDetect(&$gdimg) {
 382		if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) {
 383			if (ImageFilter($gdimg, IMG_FILTER_EDGEDETECT)) {
 384				return true;
 385			}
 386			$this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_EDGEDETECT)', __FILE__, __LINE__);
 387			// fall through and try it the hard way
 388		}
 389		// currently not implemented "the hard way"
 390		$this->DebugMessage('FAILED: phpthumb_filters::EdgeDetect($gdimg) [function not implemented]', __FILE__, __LINE__);
 391		return false;
 392	}
 393
 394
 395	function Elipse($gdimg) {
 396		if (phpthumb_functions::gd_version() < 2) {
 397			return false;
 398		}
 399		// generate mask at twice desired resolution and downsample afterwards for easy antialiasing
 400		if ($gdimg_elipsemask_double = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg) * 2, ImageSY($gdimg) * 2)) {
 401			if ($gdimg_elipsemask = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg), ImageSY($gdimg))) {
 402
 403				$color_transparent = ImageColorAllocate($gdimg_elipsemask_double, 255, 255, 255);
 404				ImageFilledEllipse($gdimg_elipsemask_double, ImageSX($gdimg), ImageSY($gdimg), (ImageSX($gdimg) - 1) * 2, (ImageSY($gdimg) - 1) * 2, $color_transparent);
 405				ImageCopyResampled($gdimg_elipsemask, $gdimg_elipsemask_double, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg), ImageSX($gdimg) * 2, ImageSY($gdimg) * 2);
 406
 407				phpthumb_filters::ApplyMask($gdimg_elipsemask, $gdimg);
 408				ImageDestroy($gdimg_elipsemask);
 409				return true;
 410
 411			} else {
 412				$this->DebugMessage('$gdimg_elipsemask = phpthumb_functions::ImageCreateFunction() failed', __FILE__, __LINE__);
 413			}
 414			ImageDestroy($gdimg_elipsemask_double);
 415		} else {
 416			$this->DebugMessage('$gdimg_elipsemask_double = phpthumb_functions::ImageCreateFunction() failed', __FILE__, __LINE__);
 417		}
 418		return false;
 419	}
 420
 421
 422	function Emboss(&$gdimg) {
 423		if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) {
 424			if (ImageFilter($gdimg, IMG_FILTER_EMBOSS)) {
 425				return true;
 426			}
 427			$this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_EMBOSS)', __FILE__, __LINE__);
 428			// fall through and try it the hard way
 429		}
 430		// currently not implemented "the hard way"
 431		$this->DebugMessage('FAILED: phpthumb_filters::Emboss($gdimg) [function not implemented]', __FILE__, __LINE__);
 432		return false;
 433	}
 434
 435
 436	function Flip(&$gdimg, $x=false, $y=false) {
 437		if (!$x && !$y) {
 438			return false;
 439		}
 440		if ($tempImage = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg), ImageSY($gdimg))) {
 441			if ($x) {
 442				ImageCopy($tempImage, $gdimg, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg));
 443				for ($x = 0; $x < ImageSX($gdimg); $x++) {
 444					ImageCopy($gdimg, $tempImage, ImageSX($gdimg) - 1 - $x, 0, $x, 0, 1, ImageSY($gdimg));
 445				}
 446			}
 447			if ($y) {
 448				ImageCopy($tempImage, $gdimg, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg));
 449				for ($y = 0; $y < ImageSY($gdimg); $y++) {
 450					ImageCopy($gdimg, $tempImage, 0, ImageSY($gdimg) - 1 - $y, 0, $y, ImageSX($gdimg), 1);
 451				}
 452			}
 453			ImageDestroy($tempImage);
 454		}
 455		return true;
 456	}
 457
 458
 459	function Frame(&$gdimg, $frame_width, $edge_width, $hexcolor_frame, $hexcolor1, $hexcolor2) {
 460		$frame_width    = ($frame_width    ? $frame_width    : 5);
 461		$edge_width     = ($edge_width     ? $edge_width     : 1);
 462		$hexcolor_frame = ($hexcolor_frame ? $hexcolor_frame : 'CCCCCC');
 463		$hexcolor1      = ($hexcolor1      ? $hexcolor1      : 'FFFFFF');
 464		$hexcolor2      = ($hexcolor2      ? $hexcolor2      : '000000');
 465
 466		$color_frame = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor_frame);
 467		$color1      = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor1);
 468		$color2      = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor2);
 469		for ($i = 0; $i < $edge_width; $i++) {
 470			// outer bevel
 471			ImageLine($gdimg,                   $i,                   $i,                   $i, ImageSY($gdimg) - $i, $color1); // left
 472			ImageLine($gdimg,                   $i,                   $i, ImageSX($gdimg) - $i,                   $i, $color1); // top
 473			ImageLine($gdimg, ImageSX($gdimg) - $i, ImageSY($gdimg) - $i, ImageSX($gdimg) - $i,                   $i, $color2); // right
 474			ImageLine($gdimg, ImageSX($gdimg) - $i, ImageSY($gdimg) - $i,                   $i, ImageSY($gdimg) - $i, $color2); // bottom
 475		}
 476		for ($i = 0; $i < $frame_width; $i++) {
 477			// actual frame
 478			ImageRectangle($gdimg, $edge_width + $i, $edge_width + $i, ImageSX($gdimg) - $edge_width - $i, ImageSY($gdimg) - $edge_width - $i, $color_frame);
 479		}
 480		for ($i = 0; $i < $edge_width; $i++) {
 481			// inner bevel
 482			ImageLine($gdimg,                   $frame_width + $edge_width + $i,                   $frame_width + $edge_width + $i,                   $frame_width + $edge_width + $i, ImageSY($gdimg) - $frame_width - $edge_width - $i, $color2); // left
 483			ImageLine($gdimg,                   $frame_width + $edge_width + $i,                   $frame_width + $edge_width + $i, ImageSX($gdimg) - $frame_width - $edge_width - $i,                   $frame_width + $edge_width + $i, $color2); // top
 484			ImageLine($gdimg, ImageSX($gdimg) - $frame_width - $edge_width - $i, ImageSY($gdimg) - $frame_width - $edge_width - $i, ImageSX($gdimg) - $frame_width - $edge_width - $i,                   $frame_width + $edge_width + $i, $color1); // right
 485			ImageLine($gdimg, ImageSX($gdimg) - $frame_width - $edge_width - $i, ImageSY($gdimg) - $frame_width - $edge_width - $i,                   $frame_width + $edge_width + $i, ImageSY($gdimg) - $frame_width - $edge_width - $i, $color1); // bottom
 486		}
 487		return true;
 488	}
 489
 490
 491	function Gamma(&$gdimg, $amount) {
 492		if (number_format($amount, 4) == '1.0000') {
 493			return true;
 494		}
 495		return ImageGammaCorrect($gdimg, 1.0, $amount);
 496	}
 497
 498
 499	function Grayscale(&$gdimg) {
 500		if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) {
 501			if (ImageFilter($gdimg, IMG_FILTER_GRAYSCALE)) {
 502				return true;
 503			}
 504			$this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_GRAYSCALE)', __FILE__, __LINE__);
 505			// fall through and try it the hard way
 506		}
 507		return phpthumb_filters::Colorize($gdimg, 100, 'gray');
 508	}
 509
 510
 511	function HistogramAnalysis(&$gdimg, $calculateGray=false) {
 512		$ImageSX = ImageSX($gdimg);
 513		$ImageSY = ImageSY($gdimg);
 514		for ($x = 0; $x < $ImageSX; $x++) {
 515			for ($y = 0; $y < $ImageSY; $y++) {
 516				$OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y);
 517				@$Analysis['red'][$OriginalPixel['red']]++;
 518				@$Analysis['green'][$OriginalPixel['green']]++;
 519				@$Analysis['blue'][$OriginalPixel['blue']]++;
 520				@$Analysis['alpha'][$OriginalPixel['alpha']]++;
 521				if ($calculateGray) {
 522					$GrayPixel = phpthumb_functions::GrayscalePixel($OriginalPixel);
 523					@$Analysis['gray'][$GrayPixel['red']]++;
 524				}
 525			}
 526		}
 527		$keys = array('red', 'green', 'blue', 'alpha');
 528		if ($calculateGray) {
 529			$keys[] = 'gray';
 530		}
 531		foreach ($keys as $dummy => $key) {
 532			ksort($Analysis[$key]);
 533		}
 534		return $Analysis;
 535	}
 536
 537
 538	function HistogramStretch(&$gdimg, $band='*', $method=0, $threshold=0.1) {
 539		// equivalent of "Auto Contrast" in Adobe Photoshop
 540		// method 0 stretches according to RGB colors. Gives a more conservative stretch.
 541		// method 1 band stretches according to grayscale which is color-biased (59% green, 30% red, 11% blue). May give a punchier / more aggressive stretch, possibly appearing over-saturated
 542		$Analysis = phpthumb_filters::HistogramAnalysis($gdimg, true);
 543		$keys = array('r'=>'red', 'g'=>'green', 'b'=>'blue', 'a'=>'alpha', '*'=>(($method == 0) ? 'all' : 'gray'));
 544		$band = substr($band, 0, 1);
 545		if (!isset($keys[$band])) {
 546			return false;
 547		}
 548		$key = $keys[$band];
 549
 550		// If the absolute brightest and darkest pixels are used then one random
 551		// pixel in the image could throw off the whole system. Instead, count up/down
 552		// from the limit and allow <threshold> (default = 0.1%) of brightest/darkest
 553		// pixels to be clipped to min/max
 554		$threshold = floatval($threshold) / 100;
 555		$clip_threshold = ImageSX($gdimg) * ImageSX($gdimg) * $threshold;
 556		//if ($min >= 0) {
 557		//	$range_min = min($min, 255);
 558		//} else {
 559			$countsum = 0;
 560			for ($i = 0; $i <= 255; $i++) {
 561				if ($method == 0) {
 562					$countsum = max(@$Analysis['red'][$i], @$Analysis['green'][$i], @$Analysis['blue'][$i]);
 563				} else {
 564					$countsum += @$Analysis[$key][$i];
 565				}
 566				if ($countsum >= $clip_threshold) {
 567					$range_min = $i - 1;
 568					break;
 569				}
 570			}
 571			$range_min = max($range_min, 0);
 572		//}
 573		//if ($max > 0) {
 574		//	$range_max = max($max, 255);
 575		//} else {
 576			$countsum = 0;
 577			for ($i = 255; $i >= 0; $i--) {
 578				if ($method == 0) {
 579					$countsum = max(@$Analysis['red'][$i], @$Analysis['green'][$i], @$Analysis['blue'][$i]);
 580				} else {
 581					$countsum += @$Analysis[$key][$i];
 582				}
 583				if ($countsum >= $clip_threshold) {
 584					$range_max = $i + 1;
 585					break;
 586				}
 587			}
 588			$range_max = min($range_max, 255);
 589		//}
 590		$range_scale = (($range_max == $range_min) ? 1 : (255 / ($range_max - $range_min)));
 591		if (($range_min == 0) && ($range_max == 255)) {
 592			// no adjustment neccesary - don't waste CPU time!
 593			return true;
 594		}
 595
 596		$ImageSX = ImageSX($gdimg);
 597		$ImageSY = ImageSY($gdimg);
 598		for ($x = 0; $x < $ImageSX; $x++) {
 599			for ($y = 0; $y < $ImageSY; $y++) {
 600				$OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y);
 601				if ($band == '*') {
 602					$new['red']   = min(255, max(0, ($OriginalPixel['red']   - $range_min) * $range_scale));
 603					$new['green'] = min(255, max(0, ($OriginalPixel['green'] - $range_min) * $range_scale));
 604					$new['blue']  = min(255, max(0, ($OriginalPixel['blue']  - $range_min) * $range_scale));
 605					$new['alpha'] = min(255, max(0, ($OriginalPixel['alpha'] - $range_min) * $range_scale));
 606				} else {
 607					$new = $OriginalPixel;
 608					$new[$key] = min(255, max(0, ($OriginalPixel[$key] - $range_min) * $range_scale));
 609				}
 610				$newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, $new['red'], $new['green'], $new['blue'], $new['alpha']);
 611				ImageSetPixel($gdimg, $x, $y, $newColor);
 612			}
 613		}
 614
 615		return true;
 616	}
 617
 618
 619	function HistogramOverlay(&$gdimg, $bands='*', $colors='', $width=0.25, $height=0.25, $alignment='BR', $opacity=50, $margin_x=5, $margin_y=null) {
 620		$margin_y = (is_null($margin_y) ? $margin_x : $margin_y);
 621
 622		$Analysis = phpthumb_filters::HistogramAnalysis($gdimg, true);
 623		$histW = round(($width > 1) ? min($width, ImageSX($gdimg)) : ImageSX($gdimg) * $width);
 624		$histH = round(($width > 1) ? min($width, ImageSX($gdimg)) : ImageSX($gdimg) * $width);
 625		if ($gdHist = ImageCreateTrueColor($histW, $histH)) {
 626			$color_back = phpthumb_functions::ImageColorAllocateAlphaSafe($gdHist, 0, 0, 0, 127);
 627			ImageFilledRectangle($gdHist, 0, 0, $histW, $histH, $color_back);
 628			ImageAlphaBlending($gdHist, false);
 629			ImageSaveAlpha($gdHist, true);
 630
 631			$HistogramTempWidth  = 256;
 632			$HistogramTempHeight = 100;
 633			if ($gdHistTemp = ImageCreateTrueColor($HistogramTempWidth, $HistogramTempHeight)) {
 634				$color_back_temp = phpthumb_functions::ImageColorAllocateAlphaSafe($gdHistTemp, 255, 0, 255, 127);
 635				ImageAlphaBlending($gdHistTemp, false);
 636				ImageSaveAlpha($gdHistTemp, true);
 637				ImageFilledRectangle($gdHistTemp, 0, 0, ImageSX($gdHistTemp), ImageSY($gdHistTemp), $color_back_temp);
 638
 639				$DefaultColors = array('r'=>'FF0000', 'g'=>'00FF00', 'b'=>'0000FF', 'a'=>'999999', '*'=>'FFFFFF');
 640				$Colors = explode(';', $colors);
 641				$BandsToGraph = array_unique(preg_split('##', $bands));
 642				$keys = array('r'=>'red', 'g'=>'green', 'b'=>'blue', 'a'=>'alpha', '*'=>'gray');
 643				foreach ($BandsToGraph as $key => $band) {
 644					if (!isset($keys[$band])) {
 645						continue;
 646					}
 647					$PeakValue = max($Analysis[$keys[$band]]);
 648					$thisColor = phpthumb_functions::ImageHexColorAllocate($gdHistTemp, phpthumb_functions::IsHexColor(@$Colors[$key]) ? $Colors[$key] : $DefaultColors[$band]);
 649					for ($x = 0; $x < $HistogramTempWidth; $x++) {
 650						ImageLine($gdHistTemp, $x, $HistogramTempHeight - 1, $x, $HistogramTempHeight - 1 - round(@$Analysis[$keys[$band]][$x] / $PeakValue * $HistogramTempHeight), $thisColor);
 651					}
 652					ImageLine($gdHistTemp, 0, $HistogramTempHeight - 1, $HistogramTempWidth - 1, $HistogramTempHeight - 1, $thisColor);
 653					ImageLine($gdHistTemp, 0, $HistogramTempHeight - 2, $HistogramTempWidth - 1, $HistogramTempHeight - 2, $thisColor);
 654				}
 655				ImageCopyResampled($gdHist, $gdHistTemp, 0, 0, 0, 0, ImageSX($gdHist), ImageSY($gdHist), ImageSX($gdHistTemp), ImageSY($gdHistTemp));
 656				ImageDestroy($gdHistTemp);
 657			} else {
 658				return false;
 659			}
 660
 661			phpthumb_filters::WatermarkOverlay($gdimg, $gdHist, $alignment, $opacity, $margin_x, $margin_y);
 662			ImageDestroy($gdHist);
 663			return true;
 664		}
 665		return false;
 666	}
 667
 668
 669	function ImageBorder(&$gdimg, $border_width, $radius_x, $radius_y, $hexcolor_border) {
 670		$border_width = ($border_width ? $border_width : 1);
 671		$radius_x     = ($radius_x     ? $radius_x     : 0);
 672		$radius_y     = ($radius_y     ? $radius_y     : 0);
 673
 674		$output_width  = ImageSX($gdimg);
 675		$output_height = ImageSY($gdimg);
 676
 677		list($new_width, $new_height) = phpthumb_functions::ProportionalResize($output_width, $output_height, $output_width - max($border_width * 2, $radius_x), $output_height - max($border_width * 2, $radius_y));
 678		$offset_x = ($radius_x ? $output_width  - $new_width  - $radius_x : 0);
 679		$offset_y = ($radius_y ? $output_height - $new_height - $radius_y : 0);
 680
 681//header('Content-Type: image/png');
 682//ImagePNG($gdimg);
 683//exit;
 684		if ($gd_border_canvas = phpthumb_functions::ImageCreateFunction($output_width, $output_height)) {
 685
 686			ImageSaveAlpha($gd_border_canvas, true);
 687			ImageAlphaBlending($gd_border_canvas, false);
 688			$color_background = phpthumb_functions::ImageColorAllocateAlphaSafe($gd_border_canvas, 255, 255, 255, 127);
 689			ImageFilledRectangle($gd_border_canvas, 0, 0, $output_width, $output_height, $color_background);
 690
 691			$color_border = phpthumb_functions::ImageHexColorAllocate($gd_border_canvas, (phpthumb_functions::IsHexColor($hexcolor_border) ? $hexcolor_border : '000000'));
 692
 693			for ($i = 0; $i < $border_width; $i++) {
 694				ImageLine($gd_border_canvas,             floor($offset_x / 2) + $radius_x,                      $i, $output_width - $radius_x - ceil($offset_x / 2),                         $i, $color_border); // top
 695				ImageLine($gd_border_canvas,             floor($offset_x / 2) + $radius_x, $output_height - 1 - $i, $output_width - $radius_x - ceil($offset_x / 2),    $output_height - 1 - $i, $color_border); // bottom
 696				ImageLine($gd_border_canvas,                    floor($offset_x / 2) + $i,               $radius_y,                      floor($offset_x / 2) +  $i, $output_height - $radius_y, $color_border); // left
 697				ImageLine($gd_border_canvas, $output_width - 1 - $i - ceil($offset_x / 2),               $radius_y,    $output_width - 1 - $i - ceil($offset_x / 2), $output_height - $radius_y, $color_border); // right
 698			}
 699
 700			if ($radius_x && $radius_y) {
 701
 702				// PHP bug: ImageArc() with thicknesses > 1 give bad/undesirable/unpredicatable results
 703				// Solution: Draw multiple 1px arcs side-by-side.
 704
 705				// Problem: parallel arcs give strange/ugly antialiasing problems
 706				// Solution: draw non-parallel arcs, from one side of the line thickness at the start angle
 707				//   to the opposite edge of the line thickness at the terminating angle
 708				for ($thickness_offset = 0; $thickness_offset < $border_width; $thickness_offset++) {
 709					ImageArc($gd_border_canvas, floor($offset_x / 2) + 1 +                 $radius_x,              $thickness_offset - 1 + $radius_y, $radius_x * 2, $radius_y * 2, 180, 270, $color_border); // top-left
 710					ImageArc($gd_border_canvas,                     $output_width - $radius_x - 1 - ceil($offset_x / 2),              $thickness_offset - 1 + $radius_y, $radius_x * 2, $radius_y * 2, 270, 360, $color_border); // top-right
 711					ImageArc($gd_border_canvas,                     $output_width - $radius_x - 1 - ceil($offset_x / 2), $output_height - $thickness_offset - $radius_y, $radius_x * 2, $radius_y * 2,   0,  90, $color_border); // bottom-right
 712					ImageArc($gd_border_canvas, floor($offset_x / 2) + 1 +                 $radius_x, $output_height - $thickness_offset - $radius_y, $radius_x * 2, $radius_y * 2,  90, 180, $color_border); // bottom-left
 713				}
 714				if ($border_width > 1) {
 715					for ($thickness_offset = 0; $thickness_offset < $border_width; $thickness_offset++) {
 716						ImageArc($gd_border_canvas, floor($offset_x / 2) + $thickness_offset + $radius_x,                                      $radius_y, $radius_x * 2, $radius_y * 2, 180, 270, $color_border); // top-left
 717						ImageArc($gd_border_canvas, $output_width - $thickness_offset - $radius_x - 1 - ceil($offset_x / 2),                                      $radius_y, $radius_x * 2, $radius_y * 2, 270, 360, $color_border); // top-right
 718						ImageArc($gd_border_canvas, $output_width - $thickness_offset - $radius_x - 1 - ceil($offset_x / 2),                     $output_height - $radius_y, $radius_x * 2, $radius_y * 2,   0,  90, $color_border); // bottom-right
 719						ImageArc($gd_border_canvas, floor($offset_x / 2) + $thickness_offset + $radius_x,                     $output_height - $radius_y, $radius_x * 2, $radius_y * 2,  90, 180, $color_border); // bottom-left
 720					}
 721				}
 722
 723			}
 724			$this->phpThumbObject->ImageResizeFunction($gd_border_canvas, $gdimg, floor(($output_width - $new_width) / 2), round(($output_height - $new_height) / 2), 0, 0, $new_width, $new_height, $output_width, $output_height);
 725
 726			ImageDestroy($gdimg);
 727			$gdimg = phpthumb_functions::ImageCreateFunction($output_width, $output_height);
 728			ImageSaveAlpha($gdimg, true);
 729			ImageAlphaBlending($gdimg, false);
 730			$gdimg_color_background = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 255, 255, 255, 127);
 731			ImageFilledRectangle($gdimg, 0, 0, $output_width, $output_height, $gdimg_color_background);
 732
 733			ImageCopy($gdimg, $gd_border_canvas, 0, 0, 0, 0, $output_width, $output_height);
 734			//$gdimg = $gd_border_canvas;
 735			ImageDestroy($gd_border_canvas);
 736			return true;
 737
 738
 739		} else {
 740			$this->DebugMessage('FAILED: $gd_border_canvas = phpthumb_functions::ImageCreateFunction('.$output_width.', '.$output_height.')', __FILE__, __LINE__);
 741		}
 742		return false;
 743	}
 744
 745
 746	function ImprovedImageRotate(&$gdimg_source, $rotate_angle=0, $config_background_hexcolor='FFFFFF', $bg=null) {
 747		while ($rotate_angle < 0) {
 748			$rotate_angle += 360;
 749		}
 750		$rotate_angle = $rotate_angle % 360;
 751		if ($rotate_angle != 0) {
 752
 753			$background_color = phpthumb_functions::ImageHexColorAllocate($gdimg_source, $config_background_hexcolor);
 754
 755			if ((phpthumb_functions::gd_version() >= 2) && !$bg && ($rotate_angle % 90)) {
 756
 757				//$this->DebugMessage('Using alpha rotate', __FILE__, __LINE__);
 758				if ($gdimg_rotate_mask = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg_source), ImageSY($gdimg_source))) {
 759
 760					for ($i = 0; $i <= 255; $i++) {
 761						$color_mask[$i] = ImageColorAllocate($gdimg_rotate_mask, $i, $i, $i);
 762					}
 763					ImageFilledRectangle($gdimg_rotate_mask, 0, 0, ImageSX($gdimg_rotate_mask), ImageSY($gdimg_rotate_mask), $color_mask[255]);
 764					$imageX = ImageSX($gdimg_source);
 765					$imageY = ImageSY($gdimg_source);
 766					for ($x = 0; $x < $imageX; $x++) {
 767						for ($y = 0; $y < $imageY; $y++) {
 768							$pixelcolor = phpthumb_functions::GetPixelColor($gdimg_source, $x, $y);
 769							ImageSetPixel($gdimg_rotate_mask, $x, $y, $color_mask[255 - round($pixelcolor['alpha'] * 255 / 127)]);
 770						}
 771					}
 772					$gdimg_rotate_mask  = ImageRotate($gdimg_rotate_mask,  $rotate_angle, $color_mask[0]);
 773					$gdimg_source = ImageRotate($gdimg_source, $rotate_angle, $background_color);
 774
 775					ImageAlphaBlending($gdimg_source, false);
 776					ImageSaveAlpha($gdimg_source, true);
 777					//$this->is_alpha = true;
 778					$phpThumbFilters = new phpthumb_filters();
 779					$phpThumbFilters->phpThumbObject = $this;
 780					$phpThumbFilters->ApplyMask($gdimg_rotate_mask, $gdimg_source);
 781
 782					ImageDestroy($gdimg_rotate_mask);
 783
 784				} else {
 785					//$this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__);
 786				}
 787
 788			} else {
 789
 790				if (phpthumb_functions::gd_version() < 2) {
 791					//$this->DebugMessage('Using non-alpha rotate because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
 792				} elseif ($bg) {
 793					//$this->DebugMessage('Using non-alpha rotate because $this->bg is "'.$bg.'"', __FILE__, __LINE__);
 794				} elseif ($rotate_angle % 90) {
 795					//$this->DebugMessage('Using non-alpha rotate because ($rotate_angle % 90) = "'.($rotate_angle % 90).'"', __FILE__, __LINE__);
 796				} else {
 797					//$this->DebugMessage('Using non-alpha rotate because $this->thumbnailFormat is "'.$this->thumbnailFormat.'"', __FILE__, __LINE__);
 798				}
 799
 800				if (ImageColorTransparent($gdimg_source) >= 0) {
 801					// ImageRotate() forgets all about an image's transparency and sets the transparent color to black
 802					// To compensate, flood-fill the transparent color of the source image with the specified background color first
 803					// then rotate and the colors should match
 804
 805					if (!function_exists('ImageIsTrueColor') || !ImageIsTrueColor($gdimg_source)) {
 806						// convert paletted image to true-color before rotating to prevent nasty aliasing artifacts
 807
 808						//$this->source_width  = ImageSX($gdimg_source);
 809						//$this->source_height = ImageSY($gdimg_source);
 810						$gdimg_newsrc = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg_source), ImageSY($gdimg_source));
 811						$background_color = phpthumb_functions::ImageHexColorAllocate($gdimg_newsrc, $config_background_hexcolor);
 812						ImageFilledRectangle($gdimg_newsrc, 0, 0, ImageSX($gdimg_source), ImageSY($gdimg_source), phpthumb_functions::ImageHexColorAllocate($gdimg_newsrc, $config_background_hexcolor));
 813						ImageCopy($gdimg_newsrc, $gdimg_source, 0, 0, 0, 0, ImageSX($gdimg_source), ImageSY($gdimg_source));
 814						ImageDestroy($gdimg_source);
 815						unset($gdimg_source);
 816						$gdimg_source = $gdimg_newsrc;
 817						unset($gdimg_newsrc);
 818
 819					} else {
 820
 821						ImageColorSet(
 822							$gdimg_source,
 823							ImageColorTransparent($gdimg_source),
 824							hexdec(substr($config_background_hexcolor, 0, 2)),
 825							hexdec(substr($config_background_hexcolor, 2, 2)),
 826							hexdec(substr($config_background_hexcolor, 4, 2)));
 827
 828						ImageColorTransparent($gdimg_source, -1);
 829
 830					}
 831				}
 832
 833				$gdimg_source = ImageRotate($gdimg_source, $rotate_angle, $background_color);
 834
 835			}
 836		}
 837		return true;
 838	}
 839
 840
 841	function MeanRemoval(&$gdimg) {
 842		if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) {
 843			if (ImageFilter($gdimg, IMG_FILTER_MEAN_REMOVAL)) {
 844				return true;
 845			}
 846			$this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_MEAN_REMOVAL)', __FILE__, __LINE__);
 847			// fall through and try it the hard way
 848		}
 849		// currently not implemented "the hard way"
 850		$this->DebugMessage('FAILED: phpthumb_filters::MeanRemoval($gdimg) [function not implemented]', __FILE__, __LINE__);
 851		return false;
 852	}
 853
 854
 855	function Negative(&$gdimg) {
 856		if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) {
 857			if (ImageFilter($gdimg, IMG_FILTER_NEGATE)) {
 858				return true;
 859			}
 860			$this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_NEGATE)', __FILE__, __LINE__);
 861			// fall through and try it the hard way
 862		}
 863		$ImageSX = ImageSX($gdimg);
 864		$ImageSY = ImageSY($gdimg);
 865		for ($x = 0; $x < $ImageSX; $x++) {
 866			for ($y = 0; $y < $ImageSY; $y++) {
 867				$currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y);
 868				$newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, (~$currentPixel['red'] & 0xFF), (~$currentPixel['green'] & 0xFF), (~$currentPixel['blue'] & 0xFF), $currentPixel['alpha']);
 869				ImageSetPixel($gdimg, $x, $y, $newColor);
 870			}
 871		}
 872		return true;
 873	}
 874
 875
 876	function RoundedImageCorners(&$gdimg, $radius_x, $radius_y) {
 877		// generate mask at twice desired resolution and downsample afterwards for easy antialiasing
 878		// mask is generated as a white double-size elipse on a triple-size black background and copy-paste-resampled
 879		// onto a correct-size mask image as 4 corners due to errors when the entire mask is resampled at once (gray edges)
 880		if ($gdimg_cornermask_triple = phpthumb_functions::ImageCreateFunction($radius_x * 6, $radius_y * 6)) {
 881			if ($gdimg_cornermask = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg), ImageSY($gdimg))) {
 882
 883				$color_transparent = ImageColorAllocate($gdimg_cornermask_triple, 255, 255, 255);
 884				ImageFilledEllipse($gdimg_cornermask_triple, $radius_x * 3, $radius_y * 3, $radius_x * 4, $radius_y * 4, $color_transparent);
 885
 886				ImageFilledRectangle($gdimg_cornermask, 0, 0, ImageSX($gdimg), ImageSY($gdimg), $color_transparent);
 887
 888				ImageCopyResampled($gdimg_cornermask, $gdimg_cornermask_triple,                           0,                           0,     $radius_x,     $radius_y, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2);
 889				ImageCopyResampled($gdimg_cornermask, $gdimg_cornermask_triple,                           0, ImageSY($gdimg) - $radius_y,     $radius_x, $radius_y * 3, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2);
 890				ImageCopyResampled($gdimg_cornermask, $gdimg_cornermask_triple, ImageSX($gdimg) - $radius_x, ImageSY($gdimg) - $radius_y, $radius_x * 3, $radius_y * 3, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2);
 891				ImageCopyResampled($gdimg_cornermask, $gdimg_cornermask_triple, ImageSX($gdimg) - $radius_x,                           0, $radius_x * 3,     $radius_y, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2);
 892
 893				phpthumb_filters::ApplyMask($gdimg_cornermask, $gdimg);
 894				ImageDestroy($gdimg_cornermask);
 895				$this->DebugMessage('RoundedImageCorners('.$radius_x.', '.$radius_y.') succeeded', __FILE__, __LINE__);
 896				return true;
 897
 898			} else {
 899				$this->DebugMessage('FAILED: $gdimg_cornermask = phpthumb_functions::ImageCreateFunction('.ImageSX($gdimg).', '.ImageSY($gdimg).')', __FILE__, __LINE__);
 900			}
 901			ImageDestroy($gdimg_cornermask_triple);
 902
 903		} else {
 904			$this->DebugMessage('FAILED: $gdimg_cornermask_triple = phpthumb_functions::ImageCreateFunction('.($radius_x * 6).', '.($radius_y * 6).')', __FILE__, __LINE__);
 905		}
 906		return false;
 907	}
 908
 909
 910	function Saturation(&$gdimg, $amount, $color='') {
 911		if ($amount == 0) {
 912			return true;
 913		} elseif ($amount > 0) {
 914			$amount = 0 - $amount;
 915		} else {
 916			$amount = abs($amount);
 917		}
 918		return phpthumb_filters::Desaturate($gdimg, $amount, $color);
 919	}
 920
 921
 922	function Sepia(&$gdimg, $amount, $targetColor) {
 923		$amount      = (is_numeric($amount) ? max(0, min(100, $amount)) : 50);
 924		$amountPct   = $amount / 100;
 925		$targetColor = (phpthumb_functions::IsHexColor($targetColor) ? $targetColor : 'A28065');
 926
 927		if ($amount == 0) {
 928			return true;
 929		}
 930
 931		if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) {
 932			if (ImageFilter($gdimg, IMG_FILTER_GRAYSCALE)) {
 933
 934				$r = round($amountPct * hexdec(substr($targetColor, 0, 2)));
 935				$g = round($amountPct * hexdec(substr($targetColor, 2, 2)));
 936				$b = round($amountPct * hexdec(substr($targetColor, 4, 2)));
 937				if (ImageFilter($gdimg, IMG_FILTER_COLORIZE, $r, $g, $b)) {
 938					return true;
 939				}
 940				$this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_COLORIZE)', __FILE__, __LINE__);
 941				// fall through and try it the hard way
 942
 943			} else {
 944
 945				$this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_GRAYSCALE)', __FILE__, __LINE__);
 946				// fall through and try it the hard way
 947
 948			}
 949		}
 950
 951		$TargetPixel['red']   = hexdec(substr($targetColor, 0, 2));
 952		$TargetPixel['green'] = hexdec(substr($targetColor, 2, 2));
 953		$TargetPixel['blue']  = hexdec(substr($targetColor, 4, 2));
 954
 955		$ImageSX = ImageSX($gdimg);
 956		$ImageSY = ImageSY($gdimg);
 957		for ($x = 0; $x < $ImageSX; $x++) {
 958			for ($y = 0; $y < $ImageSY; $y++) {
 959				$OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y);
 960				$GrayPixel = phpthumb_functions::GrayscalePixel($OriginalPixel);
 961
 962				// http://www.gimpguru.org/Tutorials/SepiaToning/
 963				// "In the traditional sepia toning process, the tinting occurs most in
 964				// the mid-tones: the lighter and darker areas appear to be closer to B&W."
 965				$SepiaAmount = ((128 - abs($GrayPixel['red'] - 128)) / 128) * $amountPct;
 966
 967				foreach ($TargetPixel as $key => $value) {
 968					$NewPixel[$key] = round(max(0, min(255, $GrayPixel[$key] * (1 - $SepiaAmount) + ($TargetPixel[$key] * $SepiaAmount))));
 969				}
 970				$newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue'], $OriginalPixel['alpha']);
 971				ImageSetPixel($gdimg, $x, $y, $newColor);
 972			}
 973		}
 974		return true;
 975	}
 976
 977
 978	function Smooth(&$gdimg, $amount=6) {
 979		$amount = min(25, max(0, $amount));
 980		if ($amount == 0) {
 981			return true;
 982		}
 983		if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) {
 984			if (ImageFilter($gdimg, IMG_FILTER_SMOOTH, $amount)) {
 985				return true;
 986			}
 987			$this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_SMOOTH, '.$amount.')', __FILE__, __LINE__);
 988			// fall through and try it the hard way
 989		}
 990		// currently not implemented "the hard way"
 991		$this->DebugMessage('FAILED: phpthumb_filters::Smooth($gdimg, '.$amount.') [function not implemented]', __FILE__, __LINE__);
 992		return false;
 993	}
 994
 995
 996	function SourceTransparentColorMask(&$gdimg, $hexcolor, $min_limit=5, $max_limit=10) {
 997		$width  = ImageSX($gdimg);
 998		$height = ImageSY($gdimg);
 999		if ($gdimg_mask = ImageCreateTrueColor($width, $height)) {
1000			$R = hexdec(substr($hexcolor, 0, 2));
1001			$G = hexdec(substr($hexcolor, 2, 2));
1002			$B = hexdec(substr($hexcolor, 4, 2));
1003			$targetPixel = array('red'=>$R, 'green'=>$G, 'blue'=>$B);
1004			$cutoffRange = $max_limit - $min_limit;
1005			for ($x = 0; $x < $width; $x++) {
1006				for ($y = 0; $y < $height; $y++) {
1007					$currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y);
1008					$colorDiff = phpthumb_functions::PixelColorDifferencePercent($currentPixel, $targetPixel);
1009					$grayLevel = min($cutoffRange, MAX(0, -$min_limit + $colorDiff)) * (255 / MAX(1, $cutoffRange));
1010					$newColor = ImageColorAllocate($gdimg_mask, $grayLevel, $grayLevel, $grayLevel);
1011					ImageSetPixel($gdimg_mask, $x, $y, $newColor);
1012				}
1013			}
1014			return $gdimg_mask;
1015		}
1016		return false;
1017	}
1018
1019
1020	function Threshold(&$gdimg, $cutoff) {
1021		$width  = ImageSX($gdimg);
1022		$height = ImageSY($gdimg);
1023		$cutoff = min(255, max(0, ($cutoff ? $cutoff : 128)));
1024		for ($x = 0; $x < $width; $x++) {
1025			for ($y = 0; $y < $height; $y++) {
1026				$currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y);
1027				$grayPixel = phpthumb_functions::GrayscalePixel($currentPixel);
1028				if ($grayPixel['red'] < $cutoff) {
1029					$newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 0x00, 0x00, 0x00, $currentPixel['alpha']);
1030				} else {
1031					$newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 0xFF, 0xFF, 0xFF, $currentPixel['alpha']);
1032				}
1033				ImageSetPixel($gdimg, $x, $y, $newColor);
1034			}
1035		}
1036		return true;
1037	}
1038
1039
1040	function ImageTrueColorToPalette2(&$image, $dither, $ncolors) {
1041		// http://www.php.net/manual/en/function.imagetruecolortopalette.php
1042		// zmorris at zsculpt dot com (17-Aug-2004 06:58)
1043		$width  = ImageSX($image);
1044		$height = ImageSY($image);
1045		$image_copy = ImageCreateTrueColor($width, $height);
1046		//ImageCopyMerge($image_copy, $image, 0, 0, 0, 0, $width, $height, 100);
1047		ImageCopy($image_copy, $image, 0, 0, 0, 0, $width, $height);
1048		ImageTrueColorToPalette($image, $dither, $ncolors);
1049		ImageColorMatch($image_copy, $image);
1050		ImageDestroy($image_copy);
1051		return true;
1052	}
1053
1054	function ReduceColorDepth(&$gdimg, $colors=256, $dither=true) {
1055		$colors = max(min($colors, 256), 2);
1056		// ImageTrueColorToPalette usually makes ugly colors, the replacement is a bit better
1057		//ImageTrueColorToPalette($gdimg, $dither, $colors);
1058		phpthumb_filters::ImageTrueColorToPalette2($gdimg, $dither, $colors);
1059		return true;
1060	}
1061
1062
1063	function WhiteBalance(&$gdimg, $targetColor='') {
1064		if (phpthumb_functions::IsHexColor($targetColor)) {
1065			$targetPixel = array(
1066				'red'   => hexdec(substr($targetColor, 0, 2)),
1067				'green' => hexdec(substr($targetColor, 2, 2)),
1068				'blue'  => hexdec(substr($targetColor, 4, 2))
1069			);
1070		} else {
1071			$Analysis = phpthumb_filters::HistogramAnalysis($gdimg, false);
1072			$targetPixel = array(
1073				'red'   => max(array_keys($Analysis['red'])),
1074				'green' => max(array_keys($Analysis['green'])),
1075				'blue'  => max(array_keys($Analysis['blue']))
1076			);
1077		}
1078		$grayValue = phpthumb_functions::GrayscaleValue($targetPixel['red'], $targetPixel['green'], $targetPixel['blue']);
1079		$scaleR = $grayValue / $targetPixel['red'];
1080		$scaleG = $grayValue / $targetPixel['green'];
1081		$scaleB = $grayValue / $targetPixel['blue'];
1082
1083		for ($x = 0; $x < ImageSX($gdimg); $x++) {
1084			for ($y = 0; $y < ImageSY($gdimg); $y++) {
1085				$currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y);
1086				$newColor = phpthumb_functions::ImageColorAllocateAlphaSafe(
1087					$gdimg,
1088					max(0, min(255, round($currentPixel['red']   * $scaleR))),
1089					max(0, min(255, round($currentPixel['green'] * $scaleG))),
1090					max(0, min(255, round($currentPixel['blue']  * $scaleB))),
1091					$currentPixel['alpha']
1092				);
1093				ImageSetPixel($gdimg, $x, $y, $newColor);
1094			}
1095		}
1096		return true;
1097	}
1098
1099
1100	function WatermarkText(&$gdimg, $text, $size, $alignment, $hex_color='000000', $ttffont='', $opacity=100, $margin=5, $angle=0, $bg_color=false, $bg_opacity=0, $fillextend='') {
1101		// text watermark requested
1102		if (!$text) {
1103			return false;
1104		}
1105		ImageAlphaBlending($gdimg, true);
1106
1107		if (preg_match('#^([0-9\\.\\-]*)x([0-9\\.\\-]*)(@[LCR])?$#i', $alignment, $matches)) {
1108			$originOffsetX = intval($matches[1]);
1109			$originOffsetY = intval($matches[2]);
1110			$alignment = (@$matches[4] ? $matches[4] : 'L');
1111			$margin = 0;
1112		} else {
1113			$originOffsetX = 0;
1114			$originOffsetY = 0;
1115		}
1116
1117		$metaTextArray = array(
1118			'^Fb' =>       $this->phpThumbObject->getimagesizeinfo['filesize'],
1119			'^Fk' => round($this->phpThumbObject->get…

Large files files are truncated, but you can click here to view the full file