PageRenderTime 83ms CodeModel.GetById 25ms app.highlight 45ms RepoModel.GetById 1ms app.codeStats 1ms

/thumb/phpthumb.filters.php

https://bitbucket.org/webnroll/cosyx
PHP | 1492 lines | 1140 code | 225 blank | 127 comment | 239 complexity | d8b008922bacaadf933d699fbcddfaf8 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, $fade) {
 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);
 307		$fade     = ($fade     ? $fade     : 1);
 308
 309		$width_shadow  = cos(deg2rad($angle)) * ($distance + $width);
 310		$height_shadow = sin(deg2rad($angle)) * ($distance + $width);
 311
 312		$scaling = min(ImageSX($gdimg) / (ImageSX($gdimg) + abs($width_shadow)), ImageSY($gdimg) / (ImageSY($gdimg) + abs($height_shadow)));
 313
 314		for ($i = 0; $i < $width; $i++) {
 315			$WidthAlpha[$i] = (abs(($width / 2) - $i) / $width) * $fade;
 316			$Offset['x'] = cos(deg2rad($angle)) * ($distance + $i);
 317			$Offset['y'] = sin(deg2rad($angle)) * ($distance + $i);
 318		}
 319
 320		$tempImageWidth  = ImageSX($gdimg)  + abs($Offset['x']);
 321		$tempImageHeight = ImageSY($gdimg) + abs($Offset['y']);
 322
 323		if ($gdimg_dropshadow_temp = phpthumb_functions::ImageCreateFunction($tempImageWidth, $tempImageHeight)) {
 324
 325			ImageAlphaBlending($gdimg_dropshadow_temp, false);
 326			ImageSaveAlpha($gdimg_dropshadow_temp, true);
 327			$transparent1 = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_dropshadow_temp, 0, 0, 0, 127);
 328			ImageFill($gdimg_dropshadow_temp, 0, 0, $transparent1);
 329
 330			for ($x = 0; $x < ImageSX($gdimg); $x++) {
 331				for ($y = 0; $y < ImageSY($gdimg); $y++) {
 332					$PixelMap[$x][$y] = phpthumb_functions::GetPixelColor($gdimg, $x, $y);
 333				}
 334			}
 335			for ($x = 0; $x < $tempImageWidth; $x++) {
 336				for ($y = 0; $y < $tempImageHeight; $y++) {
 337					//for ($i = 0; $i < $width; $i++) {
 338					for ($i = 0; $i < 1; $i++) {
 339						if (!isset($PixelMap[$x][$y]['alpha']) || ($PixelMap[$x][$y]['alpha'] > 0)) {
 340							if (isset($PixelMap[$x + $Offset['x']][$y + $Offset['y']]['alpha']) && ($PixelMap[$x + $Offset['x']][$y + $Offset['y']]['alpha'] < 127)) {
 341								$thisColor = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor, false, $PixelMap[$x + $Offset['x']][$y + $Offset['y']]['alpha']);
 342								ImageSetPixel($gdimg_dropshadow_temp, $x, $y, $thisColor);
 343							}
 344						}
 345					}
 346				}
 347			}
 348
 349			ImageAlphaBlending($gdimg_dropshadow_temp, true);
 350			for ($x = 0; $x < ImageSX($gdimg); $x++) {
 351				for ($y = 0; $y < ImageSY($gdimg); $y++) {
 352					if ($PixelMap[$x][$y]['alpha'] < 127) {
 353						$thisColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_dropshadow_temp, $PixelMap[$x][$y]['red'], $PixelMap[$x][$y]['green'], $PixelMap[$x][$y]['blue'], $PixelMap[$x][$y]['alpha']);
 354						ImageSetPixel($gdimg_dropshadow_temp, $x, $y, $thisColor);
 355					}
 356				}
 357			}
 358
 359			ImageSaveAlpha($gdimg, true);
 360			ImageAlphaBlending($gdimg, false);
 361			//$this->is_alpha = true;
 362			$transparent2 = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 0, 0, 0, 127);
 363			ImageFilledRectangle($gdimg, 0, 0, ImageSX($gdimg), ImageSY($gdimg), $transparent2);
 364			ImageCopyResampled($gdimg, $gdimg_dropshadow_temp, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg), ImageSX($gdimg_dropshadow_temp), ImageSY($gdimg_dropshadow_temp));
 365
 366			ImageDestroy($gdimg_dropshadow_temp);
 367		}
 368		return true;
 369	}
 370
 371
 372	function EdgeDetect(&$gdimg) {
 373		if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) {
 374			if (ImageFilter($gdimg, IMG_FILTER_EDGEDETECT)) {
 375				return true;
 376			}
 377			$this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_EDGEDETECT)', __FILE__, __LINE__);
 378			// fall through and try it the hard way
 379		}
 380		// currently not implemented "the hard way"
 381		$this->DebugMessage('FAILED: phpthumb_filters::EdgeDetect($gdimg) [function not implemented]', __FILE__, __LINE__);
 382		return false;
 383	}
 384
 385
 386	function Elipse($gdimg) {
 387		if (phpthumb_functions::gd_version() < 2) {
 388			return false;
 389		}
 390		// generate mask at twice desired resolution and downsample afterwards for easy antialiasing
 391		if ($gdimg_elipsemask_double = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg) * 2, ImageSY($gdimg) * 2)) {
 392			if ($gdimg_elipsemask = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg), ImageSY($gdimg))) {
 393
 394				$color_transparent = ImageColorAllocate($gdimg_elipsemask_double, 255, 255, 255);
 395				ImageFilledEllipse($gdimg_elipsemask_double, ImageSX($gdimg), ImageSY($gdimg), (ImageSX($gdimg) - 1) * 2, (ImageSY($gdimg) - 1) * 2, $color_transparent);
 396				ImageCopyResampled($gdimg_elipsemask, $gdimg_elipsemask_double, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg), ImageSX($gdimg) * 2, ImageSY($gdimg) * 2);
 397
 398				phpthumb_filters::ApplyMask($gdimg_elipsemask, $gdimg);
 399				ImageDestroy($gdimg_elipsemask);
 400				return true;
 401
 402			} else {
 403				$this->DebugMessage('$gdimg_elipsemask = phpthumb_functions::ImageCreateFunction() failed', __FILE__, __LINE__);
 404			}
 405			ImageDestroy($gdimg_elipsemask_double);
 406		} else {
 407			$this->DebugMessage('$gdimg_elipsemask_double = phpthumb_functions::ImageCreateFunction() failed', __FILE__, __LINE__);
 408		}
 409		return false;
 410	}
 411
 412
 413	function Emboss(&$gdimg) {
 414		if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) {
 415			if (ImageFilter($gdimg, IMG_FILTER_EMBOSS)) {
 416				return true;
 417			}
 418			$this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_EMBOSS)', __FILE__, __LINE__);
 419			// fall through and try it the hard way
 420		}
 421		// currently not implemented "the hard way"
 422		$this->DebugMessage('FAILED: phpthumb_filters::Emboss($gdimg) [function not implemented]', __FILE__, __LINE__);
 423		return false;
 424	}
 425
 426
 427	function Flip(&$gdimg, $x=false, $y=false) {
 428		if (!$x && !$y) {
 429			return false;
 430		}
 431		if ($tempImage = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg), ImageSY($gdimg))) {
 432			if ($x) {
 433				ImageCopy($tempImage, $gdimg, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg));
 434				for ($x = 0; $x < ImageSX($gdimg); $x++) {
 435					ImageCopy($gdimg, $tempImage, ImageSX($gdimg) - 1 - $x, 0, $x, 0, 1, ImageSY($gdimg));
 436				}
 437			}
 438			if ($y) {
 439				ImageCopy($tempImage, $gdimg, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg));
 440				for ($y = 0; $y < ImageSY($gdimg); $y++) {
 441					ImageCopy($gdimg, $tempImage, 0, ImageSY($gdimg) - 1 - $y, 0, $y, ImageSX($gdimg), 1);
 442				}
 443			}
 444			ImageDestroy($tempImage);
 445		}
 446		return true;
 447	}
 448
 449
 450	function Frame(&$gdimg, $frame_width, $edge_width, $hexcolor_frame, $hexcolor1, $hexcolor2) {
 451		$frame_width    = ($frame_width    ? $frame_width    : 5);
 452		$edge_width     = ($edge_width     ? $edge_width     : 1);
 453		$hexcolor_frame = ($hexcolor_frame ? $hexcolor_frame : 'CCCCCC');
 454		$hexcolor1      = ($hexcolor1      ? $hexcolor1      : 'FFFFFF');
 455		$hexcolor2      = ($hexcolor2      ? $hexcolor2      : '000000');
 456
 457		$color_frame = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor_frame);
 458		$color1      = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor1);
 459		$color2      = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor2);
 460		for ($i = 0; $i < $edge_width; $i++) {
 461			// outer bevel
 462			ImageLine($gdimg,                   $i,                   $i,                   $i, ImageSY($gdimg) - $i, $color1); // left
 463			ImageLine($gdimg,                   $i,                   $i, ImageSX($gdimg) - $i,                   $i, $color1); // top
 464			ImageLine($gdimg, ImageSX($gdimg) - $i, ImageSY($gdimg) - $i, ImageSX($gdimg) - $i,                   $i, $color2); // right
 465			ImageLine($gdimg, ImageSX($gdimg) - $i, ImageSY($gdimg) - $i,                   $i, ImageSY($gdimg) - $i, $color2); // bottom
 466		}
 467		for ($i = 0; $i < $frame_width; $i++) {
 468			// actual frame
 469			ImageRectangle($gdimg, $edge_width + $i, $edge_width + $i, ImageSX($gdimg) - $edge_width - $i, ImageSY($gdimg) - $edge_width - $i, $color_frame);
 470		}
 471		for ($i = 0; $i < $edge_width; $i++) {
 472			// inner bevel
 473			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
 474			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
 475			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
 476			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
 477		}
 478		return true;
 479	}
 480
 481
 482	function Gamma(&$gdimg, $amount) {
 483		if (number_format($amount, 4) == '1.0000') {
 484			return true;
 485		}
 486		return ImageGammaCorrect($gdimg, 1.0, $amount);
 487	}
 488
 489
 490	function Grayscale(&$gdimg) {
 491		if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) {
 492			if (ImageFilter($gdimg, IMG_FILTER_GRAYSCALE)) {
 493				return true;
 494			}
 495			$this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_GRAYSCALE)', __FILE__, __LINE__);
 496			// fall through and try it the hard way
 497		}
 498		return phpthumb_filters::Colorize($gdimg, 100, 'gray');
 499	}
 500
 501
 502	function HistogramAnalysis(&$gdimg, $calculateGray=false) {
 503		$ImageSX = ImageSX($gdimg);
 504		$ImageSY = ImageSY($gdimg);
 505		for ($x = 0; $x < $ImageSX; $x++) {
 506			for ($y = 0; $y < $ImageSY; $y++) {
 507				$OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y);
 508				@$Analysis['red'][$OriginalPixel['red']]++;
 509				@$Analysis['green'][$OriginalPixel['green']]++;
 510				@$Analysis['blue'][$OriginalPixel['blue']]++;
 511				@$Analysis['alpha'][$OriginalPixel['alpha']]++;
 512				if ($calculateGray) {
 513					$GrayPixel = phpthumb_functions::GrayscalePixel($OriginalPixel);
 514					@$Analysis['gray'][$GrayPixel['red']]++;
 515				}
 516			}
 517		}
 518		$keys = array('red', 'green', 'blue', 'alpha');
 519		if ($calculateGray) {
 520			$keys[] = 'gray';
 521		}
 522		foreach ($keys as $dummy => $key) {
 523			ksort($Analysis[$key]);
 524		}
 525		return $Analysis;
 526	}
 527
 528
 529	function HistogramStretch(&$gdimg, $band='*', $method=0, $threshold=0.1) {
 530		// equivalent of "Auto Contrast" in Adobe Photoshop
 531		// method 0 stretches according to RGB colors. Gives a more conservative stretch.
 532		// 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
 533		$Analysis = phpthumb_filters::HistogramAnalysis($gdimg, true);
 534		$keys = array('r'=>'red', 'g'=>'green', 'b'=>'blue', 'a'=>'alpha', '*'=>(($method == 0) ? 'all' : 'gray'));
 535		$band = substr($band, 0, 1);
 536		if (!isset($keys[$band])) {
 537			return false;
 538		}
 539		$key = $keys[$band];
 540
 541		// If the absolute brightest and darkest pixels are used then one random
 542		// pixel in the image could throw off the whole system. Instead, count up/down
 543		// from the limit and allow <threshold> (default = 0.1%) of brightest/darkest
 544		// pixels to be clipped to min/max
 545		$threshold = floatval($threshold) / 100;
 546		$clip_threshold = ImageSX($gdimg) * ImageSX($gdimg) * $threshold;
 547		//if ($min >= 0) {
 548		//	$range_min = min($min, 255);
 549		//} else {
 550			$countsum = 0;
 551			for ($i = 0; $i <= 255; $i++) {
 552				if ($method == 0) {
 553					$countsum = max(@$Analysis['red'][$i], @$Analysis['green'][$i], @$Analysis['blue'][$i]);
 554				} else {
 555					$countsum += @$Analysis[$key][$i];
 556				}
 557				if ($countsum >= $clip_threshold) {
 558					$range_min = $i - 1;
 559					break;
 560				}
 561			}
 562			$range_min = max($range_min, 0);
 563		//}
 564		//if ($max > 0) {
 565		//	$range_max = max($max, 255);
 566		//} else {
 567			$countsum = 0;
 568			for ($i = 255; $i >= 0; $i--) {
 569				if ($method == 0) {
 570					$countsum = max(@$Analysis['red'][$i], @$Analysis['green'][$i], @$Analysis['blue'][$i]);
 571				} else {
 572					$countsum += @$Analysis[$key][$i];
 573				}
 574				if ($countsum >= $clip_threshold) {
 575					$range_max = $i + 1;
 576					break;
 577				}
 578			}
 579			$range_max = min($range_max, 255);
 580		//}
 581		$range_scale = (($range_max == $range_min) ? 1 : (255 / ($range_max - $range_min)));
 582		if (($range_min == 0) && ($range_max == 255)) {
 583			// no adjustment neccesary - don't waste CPU time!
 584			return true;
 585		}
 586
 587		$ImageSX = ImageSX($gdimg);
 588		$ImageSY = ImageSY($gdimg);
 589		for ($x = 0; $x < $ImageSX; $x++) {
 590			for ($y = 0; $y < $ImageSY; $y++) {
 591				$OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y);
 592				if ($band == '*') {
 593					$new['red']   = min(255, max(0, ($OriginalPixel['red']   - $range_min) * $range_scale));
 594					$new['green'] = min(255, max(0, ($OriginalPixel['green'] - $range_min) * $range_scale));
 595					$new['blue']  = min(255, max(0, ($OriginalPixel['blue']  - $range_min) * $range_scale));
 596					$new['alpha'] = min(255, max(0, ($OriginalPixel['alpha'] - $range_min) * $range_scale));
 597				} else {
 598					$new = $OriginalPixel;
 599					$new[$key] = min(255, max(0, ($OriginalPixel[$key] - $range_min) * $range_scale));
 600				}
 601				$newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, $new['red'], $new['green'], $new['blue'], $new['alpha']);
 602				ImageSetPixel($gdimg, $x, $y, $newColor);
 603			}
 604		}
 605
 606		return true;
 607	}
 608
 609
 610	function HistogramOverlay(&$gdimg, $bands='*', $colors='', $width=0.25, $height=0.25, $alignment='BR', $opacity=50, $margin_x=5, $margin_y=null) {
 611		$margin_y = (is_null($margin_y) ? $margin_x : $margin_y);
 612
 613		$Analysis = phpthumb_filters::HistogramAnalysis($gdimg, true);
 614		$histW = round(($width > 1) ? min($width, ImageSX($gdimg)) : ImageSX($gdimg) * $width);
 615		$histH = round(($width > 1) ? min($width, ImageSX($gdimg)) : ImageSX($gdimg) * $width);
 616		if ($gdHist = ImageCreateTrueColor($histW, $histH)) {
 617			$color_back = phpthumb_functions::ImageColorAllocateAlphaSafe($gdHist, 0, 0, 0, 127);
 618			ImageFilledRectangle($gdHist, 0, 0, $histW, $histH, $color_back);
 619			ImageAlphaBlending($gdHist, false);
 620			ImageSaveAlpha($gdHist, true);
 621
 622			$HistogramTempWidth  = 256;
 623			$HistogramTempHeight = 100;
 624			if ($gdHistTemp = ImageCreateTrueColor($HistogramTempWidth, $HistogramTempHeight)) {
 625				$color_back_temp = phpthumb_functions::ImageColorAllocateAlphaSafe($gdHistTemp, 255, 0, 255, 127);
 626				ImageAlphaBlending($gdHistTemp, false);
 627				ImageSaveAlpha($gdHistTemp, true);
 628				ImageFilledRectangle($gdHistTemp, 0, 0, ImageSX($gdHistTemp), ImageSY($gdHistTemp), $color_back_temp);
 629
 630				$DefaultColors = array('r'=>'FF0000', 'g'=>'00FF00', 'b'=>'0000FF', 'a'=>'999999', '*'=>'FFFFFF');
 631				$Colors = explode(';', $colors);
 632				$BandsToGraph = array_unique(preg_split('//', $bands));
 633				$keys = array('r'=>'red', 'g'=>'green', 'b'=>'blue', 'a'=>'alpha', '*'=>'gray');
 634				foreach ($BandsToGraph as $key => $band) {
 635					if (!isset($keys[$band])) {
 636						continue;
 637					}
 638					$PeakValue = max($Analysis[$keys[$band]]);
 639					$thisColor = phpthumb_functions::ImageHexColorAllocate($gdHistTemp, phpthumb_functions::IsHexColor(@$Colors[$key]) ? $Colors[$key] : $DefaultColors[$band]);
 640					for ($x = 0; $x < $HistogramTempWidth; $x++) {
 641						ImageLine($gdHistTemp, $x, $HistogramTempHeight - 1, $x, $HistogramTempHeight - 1 - round(@$Analysis[$keys[$band]][$x] / $PeakValue * $HistogramTempHeight), $thisColor);
 642					}
 643					ImageLine($gdHistTemp, 0, $HistogramTempHeight - 1, $HistogramTempWidth - 1, $HistogramTempHeight - 1, $thisColor);
 644					ImageLine($gdHistTemp, 0, $HistogramTempHeight - 2, $HistogramTempWidth - 1, $HistogramTempHeight - 2, $thisColor);
 645				}
 646				ImageCopyResampled($gdHist, $gdHistTemp, 0, 0, 0, 0, ImageSX($gdHist), ImageSY($gdHist), ImageSX($gdHistTemp), ImageSY($gdHistTemp));
 647				ImageDestroy($gdHistTemp);
 648			} else {
 649				return false;
 650			}
 651
 652			phpthumb_filters::WatermarkOverlay($gdimg, $gdHist, $alignment, $opacity, $margin_x, $margin_y);
 653			ImageDestroy($gdHist);
 654			return true;
 655		}
 656		return false;
 657	}
 658
 659
 660	function ImageBorder(&$gdimg, $border_width, $radius_x, $radius_y, $hexcolor_border) {
 661		$border_width = ($border_width ? $border_width : 1);
 662		$radius_x     = ($radius_x     ? $radius_x     : 0);
 663		$radius_y     = ($radius_y     ? $radius_y     : 0);
 664
 665		$output_width  = ImageSX($gdimg);
 666		$output_height = ImageSY($gdimg);
 667
 668		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));
 669		$offset_x = ($radius_x ? $output_width  - $new_width  - $radius_x : 0);
 670		$offset_y = ($radius_y ? $output_height - $new_height - $radius_y : 0);
 671
 672//header('Content-Type: image/png');
 673//ImagePNG($gdimg);
 674//exit;
 675		if ($gd_border_canvas = phpthumb_functions::ImageCreateFunction($output_width, $output_height)) {
 676
 677			ImageSaveAlpha($gd_border_canvas, true);
 678			ImageAlphaBlending($gd_border_canvas, false);
 679			$color_background = phpthumb_functions::ImageColorAllocateAlphaSafe($gd_border_canvas, 255, 255, 255, 127);
 680			ImageFilledRectangle($gd_border_canvas, 0, 0, $output_width, $output_height, $color_background);
 681
 682			$color_border = phpthumb_functions::ImageHexColorAllocate($gd_border_canvas, (phpthumb_functions::IsHexColor($hexcolor_border) ? $hexcolor_border : '000000'));
 683
 684			for ($i = 0; $i < $border_width; $i++) {
 685				ImageLine($gd_border_canvas,             floor($offset_x / 2) + $radius_x,                      $i, $output_width - $radius_x - ceil($offset_x / 2),                         $i, $color_border); // top
 686				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
 687				ImageLine($gd_border_canvas,                    floor($offset_x / 2) + $i,               $radius_y,                      floor($offset_x / 2) +  $i, $output_height - $radius_y, $color_border); // left
 688				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
 689			}
 690
 691			if ($radius_x && $radius_y) {
 692
 693				// PHP bug: ImageArc() with thicknesses > 1 give bad/undesirable/unpredicatable results
 694				// Solution: Draw multiple 1px arcs side-by-side.
 695
 696				// Problem: parallel arcs give strange/ugly antialiasing problems
 697				// Solution: draw non-parallel arcs, from one side of the line thickness at the start angle
 698				//   to the opposite edge of the line thickness at the terminating angle
 699				for ($thickness_offset = 0; $thickness_offset < $border_width; $thickness_offset++) {
 700					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
 701					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
 702					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
 703					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
 704				}
 705				if ($border_width > 1) {
 706					for ($thickness_offset = 0; $thickness_offset < $border_width; $thickness_offset++) {
 707						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
 708						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
 709						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
 710						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
 711					}
 712				}
 713
 714			}
 715			$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);
 716
 717			ImageDestroy($gdimg);
 718			$gdimg = phpthumb_functions::ImageCreateFunction($output_width, $output_height);
 719			ImageSaveAlpha($gdimg, true);
 720			ImageAlphaBlending($gdimg, false);
 721			$gdimg_color_background = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 255, 255, 255, 127);
 722			ImageFilledRectangle($gdimg, 0, 0, $output_width, $output_height, $gdimg_color_background);
 723
 724			ImageCopy($gdimg, $gd_border_canvas, 0, 0, 0, 0, $output_width, $output_height);
 725			//$gdimg = $gd_border_canvas;
 726			ImageDestroy($gd_border_canvas);
 727			return true;
 728
 729
 730		} else {
 731			$this->DebugMessage('FAILED: $gd_border_canvas = phpthumb_functions::ImageCreateFunction('.$output_width.', '.$output_height.')', __FILE__, __LINE__);
 732		}
 733		return false;
 734	}
 735
 736
 737	function ImprovedImageRotate(&$gdimg_source, $rotate_angle=0, $config_background_hexcolor='FFFFFF', $bg=null) {
 738		while ($rotate_angle < 0) {
 739			$rotate_angle += 360;
 740		}
 741		$rotate_angle = $rotate_angle % 360;
 742		if ($rotate_angle != 0) {
 743
 744			$background_color = phpthumb_functions::ImageHexColorAllocate($gdimg_source, $config_background_hexcolor);
 745
 746			if ((phpthumb_functions::gd_version() >= 2) && !$bg && ($rotate_angle % 90)) {
 747
 748				//$this->DebugMessage('Using alpha rotate', __FILE__, __LINE__);
 749				if ($gdimg_rotate_mask = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg_source), ImageSY($gdimg_source))) {
 750
 751					for ($i = 0; $i <= 255; $i++) {
 752						$color_mask[$i] = ImageColorAllocate($gdimg_rotate_mask, $i, $i, $i);
 753					}
 754					ImageFilledRectangle($gdimg_rotate_mask, 0, 0, ImageSX($gdimg_rotate_mask), ImageSY($gdimg_rotate_mask), $color_mask[255]);
 755					$imageX = ImageSX($gdimg_source);
 756					$imageY = ImageSY($gdimg_source);
 757					for ($x = 0; $x < $imageX; $x++) {
 758						for ($y = 0; $y < $imageY; $y++) {
 759							$pixelcolor = phpthumb_functions::GetPixelColor($gdimg_source, $x, $y);
 760							ImageSetPixel($gdimg_rotate_mask, $x, $y, $color_mask[255 - round($pixelcolor['alpha'] * 255 / 127)]);
 761						}
 762					}
 763					$gdimg_rotate_mask  = ImageRotate($gdimg_rotate_mask,  $rotate_angle, $color_mask[0]);
 764					$gdimg_source = ImageRotate($gdimg_source, $rotate_angle, $background_color);
 765
 766					ImageAlphaBlending($gdimg_source, false);
 767					ImageSaveAlpha($gdimg_source, true);
 768					//$this->is_alpha = true;
 769					$phpThumbFilters = new phpthumb_filters();
 770					$phpThumbFilters->phpThumbObject = $this;
 771					$phpThumbFilters->ApplyMask($gdimg_rotate_mask, $gdimg_source);
 772
 773					ImageDestroy($gdimg_rotate_mask);
 774
 775				} else {
 776					//$this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__);
 777				}
 778
 779			} else {
 780
 781				if (phpthumb_functions::gd_version() < 2) {
 782					//$this->DebugMessage('Using non-alpha rotate because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
 783				} elseif ($bg) {
 784					//$this->DebugMessage('Using non-alpha rotate because $this->bg is "'.$bg.'"', __FILE__, __LINE__);
 785				} elseif ($rotate_angle % 90) {
 786					//$this->DebugMessage('Using non-alpha rotate because ($rotate_angle % 90) = "'.($rotate_angle % 90).'"', __FILE__, __LINE__);
 787				} else {
 788					//$this->DebugMessage('Using non-alpha rotate because $this->thumbnailFormat is "'.$this->thumbnailFormat.'"', __FILE__, __LINE__);
 789				}
 790
 791				if (ImageColorTransparent($gdimg_source) >= 0) {
 792					// ImageRotate() forgets all about an image's transparency and sets the transparent color to black
 793					// To compensate, flood-fill the transparent color of the source image with the specified background color first
 794					// then rotate and the colors should match
 795
 796					if (!function_exists('ImageIsTrueColor') || !ImageIsTrueColor($gdimg_source)) {
 797						// convert paletted image to true-color before rotating to prevent nasty aliasing artifacts
 798
 799						//$this->source_width  = ImageSX($gdimg_source);
 800						//$this->source_height = ImageSY($gdimg_source);
 801						$gdimg_newsrc = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg_source), ImageSY($gdimg_source));
 802						$background_color = phpthumb_functions::ImageHexColorAllocate($gdimg_newsrc, $config_background_hexcolor);
 803						ImageFilledRectangle($gdimg_newsrc, 0, 0, ImageSX($gdimg_source), ImageSY($gdimg_source), phpthumb_functions::ImageHexColorAllocate($gdimg_newsrc, $config_background_hexcolor));
 804						ImageCopy($gdimg_newsrc, $gdimg_source, 0, 0, 0, 0, ImageSX($gdimg_source), ImageSY($gdimg_source));
 805						ImageDestroy($gdimg_source);
 806						unset($gdimg_source);
 807						$gdimg_source = $gdimg_newsrc;
 808						unset($gdimg_newsrc);
 809
 810					} else {
 811
 812						ImageColorSet(
 813							$gdimg_source,
 814							ImageColorTransparent($gdimg_source),
 815							hexdec(substr($config_background_hexcolor, 0, 2)),
 816							hexdec(substr($config_background_hexcolor, 2, 2)),
 817							hexdec(substr($config_background_hexcolor, 4, 2)));
 818
 819						ImageColorTransparent($gdimg_source, -1);
 820
 821					}
 822				}
 823
 824				$gdimg_source = ImageRotate($gdimg_source, $rotate_angle, $background_color);
 825
 826			}
 827		}
 828		return true;
 829	}
 830
 831
 832	function MeanRemoval(&$gdimg) {
 833		if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) {
 834			if (ImageFilter($gdimg, IMG_FILTER_MEAN_REMOVAL)) {
 835				return true;
 836			}
 837			$this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_MEAN_REMOVAL)', __FILE__, __LINE__);
 838			// fall through and try it the hard way
 839		}
 840		// currently not implemented "the hard way"
 841		$this->DebugMessage('FAILED: phpthumb_filters::MeanRemoval($gdimg) [function not implemented]', __FILE__, __LINE__);
 842		return false;
 843	}
 844
 845
 846	function Negative(&$gdimg) {
 847		if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) {
 848			if (ImageFilter($gdimg, IMG_FILTER_NEGATE)) {
 849				return true;
 850			}
 851			$this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_NEGATE)', __FILE__, __LINE__);
 852			// fall through and try it the hard way
 853		}
 854		$ImageSX = ImageSX($gdimg);
 855		$ImageSY = ImageSY($gdimg);
 856		for ($x = 0; $x < $ImageSX; $x++) {
 857			for ($y = 0; $y < $ImageSY; $y++) {
 858				$currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y);
 859				$newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, (~$currentPixel['red'] & 0xFF), (~$currentPixel['green'] & 0xFF), (~$currentPixel['blue'] & 0xFF), $currentPixel['alpha']);
 860				ImageSetPixel($gdimg, $x, $y, $newColor);
 861			}
 862		}
 863		return true;
 864	}
 865
 866
 867	function RoundedImageCorners(&$gdimg, $radius_x, $radius_y) {
 868		// generate mask at twice desired resolution and downsample afterwards for easy antialiasing
 869		// mask is generated as a white double-size elipse on a triple-size black background and copy-paste-resampled
 870		// onto a correct-size mask image as 4 corners due to errors when the entire mask is resampled at once (gray edges)
 871		if ($gdimg_cornermask_triple = phpthumb_functions::ImageCreateFunction($radius_x * 6, $radius_y * 6)) {
 872			if ($gdimg_cornermask = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg), ImageSY($gdimg))) {
 873
 874				$color_transparent = ImageColorAllocate($gdimg_cornermask_triple, 255, 255, 255);
 875				ImageFilledEllipse($gdimg_cornermask_triple, $radius_x * 3, $radius_y * 3, $radius_x * 4, $radius_y * 4, $color_transparent);
 876
 877				ImageFilledRectangle($gdimg_cornermask, 0, 0, ImageSX($gdimg), ImageSY($gdimg), $color_transparent);
 878
 879				ImageCopyResampled($gdimg_cornermask, $gdimg_cornermask_triple,                           0,                           0,     $radius_x,     $radius_y, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2);
 880				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);
 881				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);
 882				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);
 883
 884				phpthumb_filters::ApplyMask($gdimg_cornermask, $gdimg);
 885				ImageDestroy($gdimg_cornermask);
 886				$this->DebugMessage('RoundedImageCorners('.$radius_x.', '.$radius_y.') succeeded', __FILE__, __LINE__);
 887				return true;
 888
 889			} else {
 890				$this->DebugMessage('FAILED: $gdimg_cornermask = phpthumb_functions::ImageCreateFunction('.ImageSX($gdimg).', '.ImageSY($gdimg).')', __FILE__, __LINE__);
 891			}
 892			ImageDestroy($gdimg_cornermask_triple);
 893
 894		} else {
 895			$this->DebugMessage('FAILED: $gdimg_cornermask_triple = phpthumb_functions::ImageCreateFunction('.($radius_x * 6).', '.($radius_y * 6).')', __FILE__, __LINE__);
 896		}
 897		return false;
 898	}
 899
 900
 901	function Saturation(&$gdimg, $amount, $color='') {
 902		if ($amount == 0) {
 903			return true;
 904		} elseif ($amount > 0) {
 905			$amount = 0 - $amount;
 906		} else {
 907			$amount = abs($amount);
 908		}
 909		return phpthumb_filters::Desaturate($gdimg, $amount, $color);
 910	}
 911
 912
 913	function Sepia(&$gdimg, $amount, $targetColor) {
 914		$amount      = (is_numeric($amount) ? max(0, min(100, $amount)) : 50);
 915		$amountPct   = $amount / 100;
 916		$targetColor = (phpthumb_functions::IsHexColor($targetColor) ? $targetColor : 'A28065');
 917
 918		if ($amount == 0) {
 919			return true;
 920		}
 921
 922		if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) {
 923			if (ImageFilter($gdimg, IMG_FILTER_GRAYSCALE)) {
 924
 925				$r = round($amountPct * hexdec(substr($targetColor, 0, 2)));
 926				$g = round($amountPct * hexdec(substr($targetColor, 2, 2)));
 927				$b = round($amountPct * hexdec(substr($targetColor, 4, 2)));
 928				if (ImageFilter($gdimg, IMG_FILTER_COLORIZE, $r, $g, $b)) {
 929					return true;
 930				}
 931				$this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_COLORIZE)', __FILE__, __LINE__);
 932				// fall through and try it the hard way
 933
 934			} else {
 935
 936				$this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_GRAYSCALE)', __FILE__, __LINE__);
 937				// fall through and try it the hard way
 938
 939			}
 940		}
 941
 942		$TargetPixel['red']   = hexdec(substr($targetColor, 0, 2));
 943		$TargetPixel['green'] = hexdec(substr($targetColor, 2, 2));
 944		$TargetPixel['blue']  = hexdec(substr($targetColor, 4, 2));
 945
 946		$ImageSX = ImageSX($gdimg);
 947		$ImageSY = ImageSY($gdimg);
 948		for ($x = 0; $x < $ImageSX; $x++) {
 949			for ($y = 0; $y < $ImageSY; $y++) {
 950				$OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y);
 951				$GrayPixel = phpthumb_functions::GrayscalePixel($OriginalPixel);
 952
 953				// http://www.gimpguru.org/Tutorials/SepiaToning/
 954				// "In the traditional sepia toning process, the tinting occurs most in
 955				// the mid-tones: the lighter and darker areas appear to be closer to B&W."
 956				$SepiaAmount = ((128 - abs($GrayPixel['red'] - 128)) / 128) * $amountPct;
 957
 958				foreach ($TargetPixel as $key => $value) {
 959					$NewPixel[$key] = round(max(0, min(255, $GrayPixel[$key] * (1 - $SepiaAmount) + ($TargetPixel[$key] * $SepiaAmount))));
 960				}
 961				$newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue'], $OriginalPixel['alpha']);
 962				ImageSetPixel($gdimg, $x, $y, $newColor);
 963			}
 964		}
 965		return true;
 966	}
 967
 968
 969	function Smooth(&$gdimg, $amount=6) {
 970		$amount = min(25, max(0, $amount));
 971		if ($amount == 0) {
 972			return true;
 973		}
 974		if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) {
 975			if (ImageFilter($gdimg, IMG_FILTER_SMOOTH, $amount)) {
 976				return true;
 977			}
 978			$this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_SMOOTH, '.$amount.')', __FILE__, __LINE__);
 979			// fall through and try it the hard way
 980		}
 981		// currently not implemented "the hard way"
 982		$this->DebugMessage('FAILED: phpthumb_filters::Smooth($gdimg, '.$amount.') [function not implemented]', __FILE__, __LINE__);
 983		return false;
 984	}
 985
 986
 987	function SourceTransparentColorMask(&$gdimg, $hexcolor, $min_limit=5, $max_limit=10) {
 988		$width  = ImageSX($gdimg);
 989		$height = ImageSY($gdimg);
 990		if ($gdimg_mask = ImageCreateTrueColor($width, $height)) {
 991			$R = hexdec(substr($hexcolor, 0, 2));
 992			$G = hexdec(substr($hexcolor, 2, 2));
 993			$B = hexdec(substr($hexcolor, 4, 2));
 994			$targetPixel = array('red'=>$R, 'green'=>$G, 'blue'=>$B);
 995			$cutoffRange = $max_limit - $min_limit;
 996			for ($x = 0; $x < $width; $x++) {
 997				for ($y = 0; $y < $height; $y++) {
 998					$currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y);
 999					$colorDiff = phpthumb_functions::PixelColorDifferencePercent($currentPixel, $targetPixel);
1000					$grayLevel = min($cutoffRange, MAX(0, -$min_limit + $colorDiff)) * (255 / MAX(1, $cutoffRange));
1001					$newColor = ImageColorAllocate($gdimg_mask, $grayLevel, $grayLevel, $grayLevel);
1002					ImageSetPixel($gdimg_mask, $x, $y, $newColor);
1003				}
1004			}
1005			return $gdimg_mask;
1006		}
1007		return false;
1008	}
1009
1010
1011	function Threshold(&$gdimg, $cutoff) {
1012		$width  = ImageSX($gdimg);
1013		$height = ImageSY($gdimg);
1014		$cutoff = min(255, max(0, ($cutoff ? $cutoff : 128)));
1015		for ($x = 0; $x < $width; $x++) {
1016			for ($y = 0; $y < $height; $y++) {
1017				$currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y);
1018				$grayPixel = phpthumb_functions::GrayscalePixel($currentPixel);
1019				if ($grayPixel['red'] < $cutoff) {
1020					$newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 0x00, 0x00, 0x00, $currentPixel['alpha']);
1021				} else {
1022					$newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 0xFF, 0xFF, 0xFF, $currentPixel['alpha']);
1023				}
1024				ImageSetPixel($gdimg, $x, $y, $newColor);
1025			}
1026		}
1027		return true;
1028	}
1029
1030
1031	function ImageTrueColorToPalette2(&$image, $dither, $ncolors) {
1032		// http://www.php.net/manual/en/function.imagetruecolortopalette.php
1033		// zmorris at zsculpt dot com (17-Aug-2004 06:58)
1034		$width  = ImageSX($image);
1035		$height = ImageSY($image);
1036		$image_copy = ImageCreateTrueColor($width, $height);
1037		//ImageCopyMerge($image_copy, $image, 0, 0, 0, 0, $width, $height, 100);
1038		ImageCopy($image_copy, $image, 0, 0, 0, 0, $width, $height);
1039		ImageTrueColorToPalette($image, $dither, $ncolors);
1040		ImageColorMatch($image_copy, $image);
1041		ImageDestroy($image_copy);
1042		return true;
1043	}
1044
1045	function ReduceColorDepth(&$gdimg, $colors=256, $dither=true) {
1046		$colors = max(min($colors, 256), 2);
1047		// ImageTrueColorToPalette usually makes ugly colors, the replacement is a bit better
1048		//ImageTrueColorToPalette($gdimg, $dither, $colors);
1049		phpthumb_filters::ImageTrueColorToPalette2($gdimg, $dither, $colors);
1050		return true;
1051	}
1052
1053
1054	function WhiteBalance(&$gdimg, $targetColor='') {
1055		if (phpthumb_functions::IsHexColor($targetColor)) {
1056			$targetPixel = array(
1057				'red'   => hexdec(substr($targetColor, 0, 2)),
1058				'green' => hexdec(substr($targetColor, 2, 2)),
1059				'blue'  => hexdec(substr($targetColor, 4, 2))
1060			);
1061		} else {
1062			$Analysis = phpthumb_filters::HistogramAnalysis($gdimg, false);
1063			$targetPixel = array(
1064				'red'   => max(array_keys($Analysis['red'])),
1065				'green' => max(array_keys($Analysis['green'])),
1066				'blue'  => max(array_keys($Analysis['blue']))
1067			);
1068		}
1069		$grayValue = phpthumb_functions::GrayscaleValue($targetPixel['red'], $targetPixel['green'], $targetPixel['blue']);
1070		$scaleR = $grayValue / $targetPixel['red'];
1071		$scaleG = $grayValue / $targetPixel['green'];
1072		$scaleB = $grayValue / $targetPixel['blue'];
1073
1074		for ($x = 0; $x < ImageSX($gdimg); $x++) {
1075			for ($y = 0; $y < ImageSY($gdimg); $y++) {
1076				$currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y);
1077				$newColor = phpthumb_functions::ImageColorAllocateAlphaSafe(
1078					$gdimg,
1079					max(0, min(255, round($currentPixel['red']   * $scaleR))),
1080					max(0, min(255, round($currentPixel['green'] * $scaleG))),
1081					max(0, min(255, round($currentPixel['blue']  * $scaleB))),
1082					$currentPixel['alpha']
1083				);
1084				ImageSetPixel($gdimg, $x, $y, $newColor);
1085			}
1086		}
1087		return true;
1088	}
1089
1090
1091	function WatermarkText(&$gdimg, $text, $size, $alignment, $hex_color='000000', $ttffont='', $opacity=100, $margin=5, $angle=0, $bg_color=false, $bg_opacity=0, $fillextend='') {
1092		// text watermark requested
1093		if (!$text) {
1094			return false;
1095		}
1096		ImageAlphaBlending($gdimg, true);
1097
1098		if (eregi('^([0-9\\.\\-]*)x([0-9\\.\\-]*)(@[LCR])?$', $alignment, $matches)) {
1099			$originOffsetX = intval($matches[1]);
1100			$originOffsetY = intval($matches[2]);
1101			$alignment = (@$matches[4] ? $matches[4] : 'L');
1102			$margin = 0;
1103		} else {
1104			$originOffsetX = 0;
1105			$originOffsetY = 0;
1106		}
1107
1108		$metaTextArray = array(
1109			'^Fb' =>       $this->phpThumbObject->getimagesizeinfo['filesize'],
1110			'^Fk' => round($this->phpThumbObject->getimagesizeinfo['filesize'] / 1024),
1111			'^Fm' => round($this->phpThumbObject->getimagesizeinfo['filesize'] / 1048576),
1112			'^X'  => $this->phpThumbObject->getimagesizeinfo[0],
1113			'^Y'  => $this->phpThumbObject->getimagesizeinfo[1],
1114			'^x'  => ImageSX($gdimg),
1115			'^y'  => ImageSY($…

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