<?php
//////////////////////////////////////////////////////////////
///  phpThumb() by James Heinrich <info@silisoftware.com>   //
//        available at http://phpthumb.sourceforge.net     ///
//////////////////////////////////////////////////////////////
///                                                         //
// See: phpthumb.readme.txt for usage instructions          //
//                                                         ///
//////////////////////////////////////////////////////////////

// NOTE: Modified paths for inclusion in OpenDb, but thats all I
// modified.

if (!include_once('./functions/phpthumb/phpthumb.functions.php')) {
	die('failed to include_once("'.realpath('./functions/phpthumb/phpthumb.functions.php').'")');
}

class phpthumb {

	// public:
	// START CONFIGURATION OPTIONS
	// See phpThumb.config.php for descriptions of what each of these settings do

	// * Directory Configuration
	var $config_cache_directory              = null;
	var $config_temp_directory               = null;
	var $config_document_root                = null;

	// * Default output configuration:
	var $config_output_format                = 'jpeg';
	var $config_output_maxwidth              = 0;
	var $config_output_maxheight             = 0;
	var $config_output_interlace             = true;

	// * Error message configuration
	var $config_error_message_image_default  = '';
	var $config_error_bgcolor                = 'CCCCFF';
	var $config_error_textcolor              = 'FF0000';
	var $config_error_fontsize               = 1;
	var $config_error_die_on_error           = true;
	var $config_error_silent_die_on_error    = false;

	// * Anti-Hotlink Configuration:
	var $config_nohotlink_enabled            = true;
	var $config_nohotlink_valid_domains      = array();
	var $config_nohotlink_erase_image        = true;
	var $config_nohotlink_fill_hexcolor      = 'CCCCCC';
	var $config_nohotlink_text_hexcolor      = 'FF0000';
	var $config_nohotlink_text_message       = 'Hotlinking is not allowed!';
	var $config_nohotlink_text_fontsize      = 3;

	// * Border & Background default colors
	var $config_border_hexcolor              = '000000';
	var $config_background_hexcolor          = 'FFFFFF';

	var $config_max_source_pixels            = 0;
	var $config_use_exif_thumbnail_for_speed = true;
	var $config_output_allow_enlarging       = false;

	var $config_imagemagick_path             = null;

	var $config_disable_debug                = false;
	// END CONFIGURATION OPTIONS


	// public: data source
	var $sourceFilename = null;
	var $rawImageData   = null;

	// public: error message(s)
	var $debugmessages = array();


	// public:
	// START PARAMETERS
	// See phpthumb.readme.txt for descriptions of what each of these values are
	var $src  = null;
	var $w    = null;
	var $h    = null;
	var $f    = 'jpeg';
	var $q    = 75;
	var $sx   = null;
	var $sy   = null;
	var $sw   = null;
	var $sh   = null;
	var $bw   = null;
	var $bg   = null;
	var $bgt  = null;
	var $bc   = null;
	var $usr  = null;
	var $usa  = null;
	var $ust  = null;
	var $wmf  = null;
	var $wmp  = null;
	var $wmm  = null;
	var $wma  = null;
	var $file = null;
	var $goto = null;
	var $err  = null;
	var $xto  = null;
	var $ra   = null;
	var $ar   = null;
	var $aoe  = null;
	var $iar  = null;
	var $brx  = null;
	var $bry  = null;
	var $maxb = null;
	var $down = null;
	// END PARAMETERS


	// private:
	var $phpThumbDebug    = null;
	var $thumbnailQuality = 75;
	var $thumbnailFormat  = null;

	var $gdimg_output     = null;
	var $gdimg_source     = null;

	var $getimagesizeinfo = null;

	var $source_width  = null;
	var $source_height = null;

	var $thumbnailCropX = null;
	var $thumbnailCropY = null;
	var $thumbnailCropW = null;
	var $thumbnailCropH = null;

	var $exif_thumbnail_width  = null;
	var $exif_thumbnail_height = null;
	var $exif_thumbnail_type   = null;
	var $exif_thumbnail_data   = null;

	var $thumbnail_width        = null;
	var $thumbnail_height       = null;
	var $thumbnail_image_width  = null;
	var $thumbnail_image_height = null;

	var $cache_filename         = null;
	var $RemoveFileOnCompletion = false;

	var $phpthumb_version = '1.4.11-200410111029';
	var $iswindows = null;
	var $osslash   = null;

	//////////////////////////////////////////////////////////////////////

	// public: constructor
	function phpThumb() {
		if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
			$this->iswindows = true;
			$this->osslash   = '\\';
		} else {
			$this->iswindows = false;
			$this->osslash   = '/';
		}
		if (!empty($_SERVER['DOCUMENT_ROOT'])) {
			$this->config_document_root = $_SERVER['DOCUMENT_ROOT'];
		}
	}

	// public:
	function setSourceFilename($sourceFilename) {
		$this->rawImageData   = null;
		$this->sourceFilename = $sourceFilename;

		// i know this is overkill, but I can't be bothered going through
		// and working out what of these variables is not reset everytime
		// setSourceData or setSourceFilename is called.
		$this->gdimg_output = NULL;
		$this->gdimg_source = NULL;
		$this->getimagesizeinfo = null;

		$this->source_width  = null;
		$this->source_height = null;

		$this->thumbnailCropX = null;
		$this->thumbnailCropY = null;
		$this->thumbnailCropW = null;
		$this->thumbnailCropH = null;

		$this->exif_thumbnail_width  = null;
		$this->exif_thumbnail_height = null;
		$this->exif_thumbnail_type   = null;
		$this->exif_thumbnail_data   = null;

		$this->thumbnail_width        = null;
		$this->thumbnail_height       = null;
		$this->thumbnail_image_width  = null;
		$this->thumbnail_image_height = null;
		
		return true;
	}

	// public:
	function setSourceData($rawImageData) {
		$this->sourceFilename = null;
		$this->rawImageData   = $rawImageData;
		
		// i know this is overkill, but I can't be bothered going through
		// and working out what of these variables is not reset everytime
		// setSourceData or setSourceFilename is called.
		$this->gdimg_output = NULL;
		$this->gdimg_source = NULL;
		$this->getimagesizeinfo = null;

		$this->source_width  = null;
		$this->source_height = null;

		$this->thumbnailCropX = null;
		$this->thumbnailCropY = null;
		$this->thumbnailCropW = null;
		$this->thumbnailCropH = null;

		$this->exif_thumbnail_width  = null;
		$this->exif_thumbnail_height = null;
		$this->exif_thumbnail_type   = null;
		$this->exif_thumbnail_data   = null;

		$this->thumbnail_width        = null;
		$this->thumbnail_height       = null;
		$this->thumbnail_image_width  = null;
		$this->thumbnail_image_height = null;
		
		return true;
	}

	// public:
	function GenerateThumbnail() {

		if (empty($this->thumbnailFormat)) {
			$this->setOutputFormat();
		}
		$this->ResolveSource();
		if (empty($this->src) && !empty($this->rawImageData)) {
			$this->SetCacheFilename();
		}
		$this->ExtractEXIFgetImageSize();
		if (!$this->SourceImageToGD()) {
			return false;
		}
		$this->Rotate();
		$this->CreateGDoutput();
		$this->ImageBorder();

		// copy/resize image to appropriate dimensions (either nearest-neighbor or resample, depending on GD version)
		$this->ImageResizeFunction(
			$this->gdimg_output,
			$this->gdimg_source,
			round(($this->thumbnail_width  - $this->thumbnail_image_width)  / 2),
			round(($this->thumbnail_height - $this->thumbnail_image_height) / 2),
			$this->thumbnailCropX,
			$this->thumbnailCropY,
			$this->thumbnail_image_width,
			$this->thumbnail_image_height,
			$this->thumbnailCropW,
			$this->thumbnailCropH);


		$this->UnsharpMasking();
		$this->Watermarking();
		$this->AntiOffsiteLinking();
		$this->RoundedImageCorners();
		$this->MaxFileSize();

		if ($this->RemoveFileOnCompletion) {
			@unlink($this->sourceFilename);
		}
		return true;
	}


	// public:
	function RenderToFile($filename) {
		// render thumbnail to this file only, do not cache, do not output to browser
		$ImageOutFunction = 'image'.$this->thumbnailFormat;
		//$renderfilename = $this->ResolveFilenameToAbsolute(dirname($filename)).'/'.basename($filename);
		$renderfilename = $filename;
		if (($filename{0} != '/') && ($filename{0} != '\\') && ($filename{1} != ':')) {
			$renderfilename = $this->ResolveFilenameToAbsolute($filename);
		}
		$this->DebugMessage('RenderToFile('.$filename.') attempting to render to file "'.$renderfilename.'"', __FILE__, __LINE__);
		ob_start();
		switch ($this->thumbnailFormat) {
			case 'jpeg':
				$ImageOutFunction($this->gdimg_output, $renderfilename, $this->thumbnailQuality);
				break;

			case 'png':
			case 'gif':
				$ImageOutFunction($this->gdimg_output, $renderfilename);
				break;
		}
		$errormessage = strip_tags(ob_get_contents());
		ob_end_clean();
		if (!empty($errormessage)) {
			$this->DebugMessage('RenderToFile ['.$ImageOutFunction.'('.$renderfilename.')] failed with message "'.$errormessage.'"', __FILE__, __LINE__);
			return false;
		}
		return true;
	}


	// public:
	function OutputThumbnail() {
		if ($this->RemoveFileOnCompletion) {
			@unlink($this->sourceFilename);
		}

		if (headers_sent()) {
			return $this->ErrorImage('OutputThumbnail() failed - headers already sent');
			exit;
		}

		if (!empty($this->down)) {
			$downloadfilename = ereg_replace('[/\\:\*\?"<>|]', '_', $this->down);
			if (phpthumb_functions::version_compare_replacement(phpversion(), '4.1.0', '>=')) {
				$downloadfilename = trim($downloadfilename, '.');
			}
			if ($downloadfilename != $this->down) {
				$this->DebugMessage('renaming output file for "down" from "'.$this->down.'" to "'.$downloadfilename.'"', __FILE__, __LINE__);
			}
			if (!empty($downloadfilename)) {
				header('Content-Disposition: attachment; filename="'.$downloadfilename.'"');
			} else {
				$this->DebugMessage('failed to send Content-Disposition header because $downloadfilename is empty', __FILE__, __LINE__);
			}
		}

		ImageInterlace($this->gdimg_output, intval($this->config_output_interlace));
		$ImageOutFunction = 'image'.$this->thumbnailFormat;
		switch ($this->thumbnailFormat) {
			case 'jpeg':
				header('Content-type: image/'.$this->thumbnailFormat);
				@$ImageOutFunction($this->gdimg_output, '', $this->thumbnailQuality);
				break;

			case 'png':
			case 'gif':
				header('Content-type: image/'.$this->thumbnailFormat);
				@$ImageOutFunction($this->gdimg_output);
				break;
		}
		ImageDestroy($this->gdimg_output);
		return true;
	}


	// public:
	function CleanUpCacheDirectory() {
		if (($this->config_cache_maxage > 0) || ($this->config_cache_maxsize > 0) || ($this->config_cache_maxfiles > 0)) {
			$CacheDirOldFilesAge  = array();
			$CacheDirOldFilesSize = array();
			if ($dirhandle = opendir($this->config_cache_directory)) {
				while ($oldcachefile = readdir($dirhandle)) {
					if (eregi('^phpThumb_cache_', $oldcachefile)) {
						$CacheDirOldFilesAge[$oldcachefile] = fileatime($this->config_cache_directory.'/'.$oldcachefile);
						if ($CacheDirOldFilesAge[$oldcachefile] == 0) {
							$CacheDirOldFilesAge[$oldcachefile] = filemtime($this->config_cache_directory.'/'.$oldcachefile);
						}

						$CacheDirOldFilesSize[$oldcachefile] = filesize($this->config_cache_directory.'/'.$oldcachefile);
					}
				}
			}
			asort($CacheDirOldFilesAge);

			if ($this->config_cache_maxfiles > 0) {
				$TotalCachedFiles = count($CacheDirOldFilesAge);
				$DeletedKeys = array();
				foreach ($CacheDirOldFilesAge as $oldcachefile => $filedate) {
					if ($TotalCachedFiles > $this->config_cache_maxfiles) {
						$TotalCachedFiles--;
						unlink($this->config_cache_directory.'/'.$oldcachefile);
						$DeletedKeys[] = $oldcachefile;
					} else {
						// there are few enough files to keep the rest
						break;
					}
				}
				foreach ($DeletedKeys as $oldcachefile) {
					unset($CacheDirOldFilesAge[$oldcachefile]);
					unset($CacheDirOldFilesSize[$oldcachefile]);
				}
			}

			if ($this->config_cache_maxage > 0) {
				$mindate = time() - $this->config_cache_maxage;
				$DeletedKeys = array();
				foreach ($CacheDirOldFilesAge as $oldcachefile => $filedate) {
					if ($filedate > 0) {
						if ($filedate < $mindate) {
							unlink($this->config_cache_directory.'/'.$oldcachefile);
							$DeletedKeys[] = $oldcachefile;
						} else {
							// the rest of the files are new enough to keep
							break;
						}
					}
				}
				foreach ($DeletedKeys as $oldcachefile) {
					unset($CacheDirOldFilesAge[$oldcachefile]);
					unset($CacheDirOldFilesSize[$oldcachefile]);
				}
			}

			if ($this->config_cache_maxsize > 0) {
				$TotalCachedFileSize = array_sum($CacheDirOldFilesSize);
				$DeletedKeys = array();
				foreach ($CacheDirOldFilesAge as $oldcachefile => $filedate) {
					if ($TotalCachedFileSize > $this->config_cache_maxsize) {
						$TotalCachedFileSize -= $CacheDirOldFilesSize[$oldcachefile];
						unlink($this->config_cache_directory.'/'.$oldcachefile);
						$DeletedKeys[] = $oldcachefile;
					} else {
						// the total filesizes are small enough to keep the rest of the files
						break;
					}
				}
				foreach ($DeletedKeys as $oldcachefile) {
					unset($CacheDirOldFilesAge[$oldcachefile]);
					unset($CacheDirOldFilesSize[$oldcachefile]);
				}
			}

		}
		return true;
	}

	//////////////////////////////////////////////////////////////////////

	function ResolveSource() {
		if (empty($this->sourceFilename)) {
			if (empty($this->rawImageData)) {

				$this->sourceFilename = $this->ResolveFilenameToAbsolute($this->src);

			} else {

				$this->RemoveFileOnCompletion = true;
				if ($tempfilename = $this->phpThumb_tempnam()) {
					$this->sourceFilename = $tempfilename;
					if ($fp_tempfile = @fopen($tempfilename, 'wb')) {
						fwrite($fp_tempfile, $this->rawImageData);
						unset($this->rawImageData);
						fclose($fp_tempfile);
					} else {
						return $this->ErrorImage('Failed to open temp file "'.$this->sourceFilename.'" for writing in '.__FILE__.' on line '.__LINE__."\n".'You may need to set $PHPTHUMB_CONFIG[temp_directory] in phpThumb.config.php');
					}
				} else {
					return $this->ErrorImage('Failed to generate temp filename in '.__FILE__.' on line '.__LINE__);
				}

			}
		}
		return true;
	}

	function setOutputFormat() {
		$AvailableImageOutputFormats = array();
		$AvailableImageOutputFormats[] = 'text';
		$this->thumbnailFormat         = 'text';

		// Set default output format based on what image types are available
		if (!function_exists('ImageTypes')) {
			return $this->ErrorImage('ImageTypes() does not exist - GD support might not be enabled?');
		}
		$imagetypes = ImageTypes();
		if ($imagetypes & IMG_WBMP) {
			$this->thumbnailFormat         = 'wbmp';
			$AvailableImageOutputFormats[] = 'wbmp';
		}
		if ($imagetypes & IMG_GIF) {
			$this->thumbnailFormat         = 'gif';
			$AvailableImageOutputFormats[] = 'gif';
		}
		if ($imagetypes & IMG_PNG) {
			$this->thumbnailFormat         = 'png';
			$AvailableImageOutputFormats[] = 'png';
		}
		if ($imagetypes & IMG_JPG) {
			$this->thumbnailFormat         = 'jpeg';
			$AvailableImageOutputFormats[] = 'jpeg';
		}
		if (in_array($this->config_output_format, $AvailableImageOutputFormats)) {
			// set output format to config default if that format is available
			$this->thumbnailFormat = $this->config_output_format;
		}
		if (!empty($this->f) && (in_array($this->f, $AvailableImageOutputFormats))) {
			// override output format if $this->f is set and that format is available
			$this->thumbnailFormat = $this->f;
		}

		// for JPEG images, quality 0 (worst) to 100 (best)
		// quality < 25 is nasty, with not much size savings - not recommended
		// problems with 100 - invalid JPEG?
		$this->thumbnailQuality = max(1, min(95, (!empty($this->q) ? $this->q : 75)));

		return true;
	}

	function setCacheDirectory() {
		// resolve cache directory to absolute pathname
		if ($this->iswindows) {
			$this->config_cache_directory = str_replace('/', $this->osslash, $this->config_cache_directory);
		}
		if ((substr($this->config_cache_directory, 0, 1) == '.') && (substr($this->src, 0, 1) == '/')) {
			// resolve relative cache directory to source image
			$this->config_cache_directory = realpath(dirname($this->config_document_root.$this->src).'/'.$this->config_cache_directory);
		}
		if (substr($this->config_cache_directory, -1) == '/') {
			$this->config_cache_directory = substr($this->config_cache_directory, 0, -1);
		}
		if (!is_dir($this->config_cache_directory)) {
			$this->DebugMessage('$this->config_cache_directory is not a directory ('.$this->config_cache_directory.')', __FILE__, __LINE__);
			$this->config_cache_directory = null;
		}

		return true;
	}


	function ResolveFilenameToAbsolute($filename) {
		$this->iswindows = (bool) (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN');
		if (substr($filename, 0, 7) == 'http://') {

			// URL
			$AbsoluteFilename = $filename;

		} elseif ($this->iswindows && (substr($filename, 1, 1) == ':')) {

			// absolute pathname (Windows)
			$AbsoluteFilename = $filename;

		} elseif ($this->iswindows && ((substr($filename, 0, 2) == '//') || (substr($filename, 0, 2) == '\\\\'))) {

			// absolute pathname (Windows)
			$AbsoluteFilename = $filename;

		} elseif (substr($filename, 0, 1) == '/') {

			if (is_readable($filename) && !is_readable($this->config_document_root.$filename)) {
				// absolute filename (*nix)
				$AbsoluteFilename = $filename;
			} elseif (substr($filename, 1, 1) == '~') {
				// /~user/path
				if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray($filename)) {
					$AbsoluteFilename = $ApacheLookupURIarray['filename'];
				} else {
					$AbsoluteFilename = realpath($filename);
					if (is_readable($AbsoluteFilename)) {
						$this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.$filename.'", but the correct filename ('.$AbsoluteFilename.') seems to have been resolved with realpath($filename)', __FILE__, __LINE__);
					} else {
						return $this->ErrorImage('phpthumb_functions::ApacheLookupURIarray() failed for "'.$filename.'". This has been known to fail on Apache2 - try using the absolute filename for the source image');
					}
				}
			} else {
				// relative filename (any OS)
				$AbsoluteFilename = $this->config_document_root.$filename;
			}

		} else {

			// relative to current directory (any OS)
			$AbsoluteFilename = $this->config_document_root.dirname(@$_SERVER['PHP_SELF']).'/'.$filename;
			if (substr(dirname(@$_SERVER['PHP_SELF']), 0, 2) == '/~') {
				if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray(dirname(@$_SERVER['PHP_SELF']))) {
					$AbsoluteFilename = $ApacheLookupURIarray['filename'].'/'.$filename;
				} else {
					$AbsoluteFilename = realpath('.').'/'.$filename;
					if (is_readable($AbsoluteFilename)) {
						$this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname(@$_SERVER['PHP_SELF']).'", but the correct filename ('.$AbsoluteFilename.') seems to have been resolved with realpath(.)/$filename', __FILE__, __LINE__);
					} else {
						return $this->ErrorImage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname(@$_SERVER['PHP_SELF']).'". This has been known to fail on Apache2 - try using the absolute filename for the source image');
					}
				}
			}

		}
		return $AbsoluteFilename;
	}


	function ImageMagickVersion() {
		$which_convert = phpthumb_functions::SafeBackTick('which convert');
		if (file_exists($this->config_imagemagick_path)) {
			if ($this->iswindows) {
				$commandline = substr($this->config_imagemagick_path, 0, 2).' && cd "'.substr(dirname($this->config_imagemagick_path), 2).'" && '.basename($this->config_imagemagick_path);
			} else {
				$commandline = '"'.$this->config_imagemagick_path.'"';
			}
		} elseif ($which_convert && !eregi('^sh: convert: not found', $which_convert)) {
			$commandline = 'convert';
		} else {
			$this->DebugMessage('Cannot find "convert'.(($this->iswindows) ? '.exe' : '').'" '.(($this->iswindows) ? '' : 'in path or ').'as specified in config_imagemagick_path ('.$this->config_imagemagick_path.')', __FILE__, __LINE__);
		}
		if (!empty($commandline)) {
			$commandline .= ' -version';
			$versionstring = phpthumb_functions::SafeBackTick($commandline);
			if (eregi('^Version: (.*) http', $versionstring, $matches)) {
				return $matches[1];
			}
			$this->DebugMessage('ImageMagick did not return recognized version string ('.$versionstring.')', __FILE__, __LINE__);
			return $versionstring;
		}
		return false;
	}

	function ImageMagickThumbnailToGD() {
		// http://freealter.org/doc_distrib/ImageMagick-5.1.1/www/convert.html
		if (ini_get('safe_mode')) {
			return false;
		}
		if (!function_exists('ImageCreateFromPNG')) {
			// ImageMagickThumbnailToGD() depends on ImageCreateFromPNG()
			return false;
		}

		$which_convert = phpthumb_functions::SafeBackTick('which convert');
		if (file_exists($this->config_imagemagick_path)) {

			if ($this->iswindows) {
				$commandline = substr($this->config_imagemagick_path, 0, 2).' && cd "'.substr(dirname($this->config_imagemagick_path), 2).'" && '.basename($this->config_imagemagick_path);
			} else {
				$commandline = '"'.$this->config_imagemagick_path.'"';
			}

		} elseif ($which_convert && file_exists($which_convert)) {

			// `which convert` *should* return the path if "convert" exist, or nothing if it doesn't
			// other things *may* get returned, like "sh: config: not found" or "no convert in /usr/local/bin /usr/sbin /usr/bin /usr/ccs/bin"
			// so only do this if the value returned exists as a file
			$commandline = 'convert';

		}
		if (!empty($commandline)) {
			if ($IMtempfilename = $this->phpThumb_tempnam()) {
				$IMtempfilename = realpath($IMtempfilename);
				$IMwidth  = ((intval($this->w) > 0) ? intval($this->w) : 640);
				$IMheight = ((intval($this->h) > 0) ? intval($this->h) : 480);
				if ((empty($this->aoe) && empty($this->iar)) && ($getimagesize = @GetImageSize($this->sourceFilename))) {
					// limit output size to input size unless AllowOutputEnlargement is enabled
					$IMwidth  = min($IMwidth,  $getimagesize[0]);
					$IMheight = min($IMheight, $getimagesize[1]);
				}
				//$commandline .= ' -resize '.$IMwidth.'x'.$IMheight; // behaves badly with IM v5.3.x
				$commandline .= ' -geometry '.$IMwidth.'x'.$IMheight;
				if (!empty($this->iar) && (intval($this->w) > 0) && (intval($this->h) > 0)) {
					$commandline .= '!';
				}
				$commandline .= ' "'.str_replace('/', $this->osslash, $this->sourceFilename).'"';
				$commandline .= ' png:'.$IMtempfilename;
				$commandline .= ' 2>&1';

				$IMresult = phpthumb_functions::SafeBackTick($commandline);
				if (!empty($IMresult)) {
					return $this->ErrorImage('ImageMagick was called as:'."\n".$commandline."\n\n".'but failed with message:'."\n".$IMresult);
				} else {
					if ($this->gdimg_source = @ImageCreateFromPNG($IMtempfilename)) {
						unlink($IMtempfilename);
						$this->source_width  = ImageSX($this->gdimg_source);
						$this->source_height = ImageSY($this->gdimg_source);
						return true;
					}
				}
				unlink($IMtempfilename);
			}
		}
		return false;
	}


	function ImageResizeFunction(&$dst_im, &$src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH) {
		if ($this->gd_version() >= 2.0) {
			return ImageCopyResampled($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH);
		}
		return ImageCopyResized($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH);
	}

	function ImageCreateFunction($x_size, $y_size) {
		$ImageCreateFunction = 'ImageCreate';
		if ($this->gd_version() >= 2.0) {
			$ImageCreateFunction = 'ImageCreateTrueColor';
		}
		if (!function_exists($ImageCreateFunction)) {
			return $this->ErrorImage($ImageCreateFunction.'() does not exist - no GD support?');
		}
		return $ImageCreateFunction($x_size, $y_size);
	}


	function Rotate() {
		if (!function_exists('ImageRotate')) {
			return false;
		}
		if (!empty($this->ra) || !empty($this->ar)) {
			$this->config_background_hexcolor = (!empty($this->bg) ? $this->bg : $this->config_background_hexcolor);
			if (!eregi('^[0-9A-F]{6}$', $this->config_background_hexcolor)) {
				return $this->ErrorImage('Invalid hex color string "'.$this->config_background_hexcolor.'" for parameter "bg"');
			}

			$rotate_angle = 0;
			if (!empty($this->ra)) {

				$rotate_angle = floatval($this->ra);

			} else {

				if (($this->ar == 'l') && ($this->source_height > $this->source_width)) {
					$rotate_angle = 270;
				} elseif (($this->ar == 'L') && ($this->source_height > $this->source_width)) {
					$rotate_angle = 90;
				} elseif (($this->ar == 'p') && ($this->source_width > $this->source_height)) {
					$rotate_angle = 90;
				} elseif (($this->ar == 'P') && ($this->source_width > $this->source_height)) {
					$rotate_angle = 270;
				}

			}
			while ($rotate_angle < 0) {
				$rotate_angle += 360;
			}
			$rotate_angle = $rotate_angle % 360;
			if ($rotate_angle != 0) {

				if (ImageColorTransparent($this->gdimg_source) >= 0) {
					// ImageRotate() forgets all about an image's transparency and sets the transparent color to black
					// To compensate, flood-fill the transparent color of the source image with the specified background color first
					// then rotate and the colors should match

					if (!function_exists('ImageIsTrueColor') || !ImageIsTrueColor($this->gdimg_source)) {
						// convert paletted image to true-color before rotating to prevent nasty aliasing artifacts

						$this->source_width  = ImageSX($this->gdimg_source);
						$this->source_height = ImageSY($this->gdimg_source);
						$gdimg_newsrc = $this->ImageCreateFunction($this->source_width, $this->source_height);
						$background_color = phpthumb_functions::ImageHexColorAllocate($gdimg_newsrc, $this->config_background_hexcolor);
						ImageFilledRectangle($gdimg_newsrc, 0, 0, $this->source_width, $this->source_height, phpthumb_functions::ImageHexColorAllocate($gdimg_newsrc, $this->config_background_hexcolor));
						ImageCopy($gdimg_newsrc, $this->gdimg_source, 0, 0, 0, 0, $this->source_width, $this->source_height);
						ImageDestroy($this->gdimg_source);
						unset($this->gdimg_source);
						$this->gdimg_source = $gdimg_newsrc;
						unset($gdimg_newsrc);

					} else {

						ImageColorSet(
							$this->gdimg_source,
							ImageColorTransparent($this->gdimg_source),
							hexdec(substr($this->config_background_hexcolor, 0, 2)),
							hexdec(substr($this->config_background_hexcolor, 2, 2)),
							hexdec(substr($this->config_background_hexcolor, 4, 2)));

						ImageColorTransparent($this->gdimg_source, -1);

					}
				}

				$background_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_source, $this->config_background_hexcolor);
				$this->gdimg_source = ImageRotate($this->gdimg_source, $rotate_angle, $background_color);
				$this->source_width  = ImageSX($this->gdimg_source);
				$this->source_height = ImageSY($this->gdimg_source);
			}
		}
		return true;
	}



	function FixedAspectRatio() {
		// optional image border and fixed-dimension images (regardless of aspect ratio)
		if (isset($this->bw)) {
			if ($this->thumbnail_image_width >= $this->thumbnail_width) {
				if (isset($this->w)) {
					$aspectratio = $this->thumbnail_image_height / $this->thumbnail_image_width;
					$this->thumbnail_image_width -= ($this->bw * 2);
					$this->thumbnail_image_height = round($this->thumbnail_image_width * $aspectratio);
					if (!isset($this->h)) {
						$this->thumbnail_height = $this->thumbnail_image_height + ($this->bw * 2);
					}
				} elseif (($this->thumbnail_image_height + ($this->bw * 2)) < $this->thumbnail_height) {
					$this->thumbnail_image_height = $this->thumbnail_height - ($this->bw * 2);
					$this->thumbnail_image_width  = round($this->thumbnail_image_height / $aspectratio);
				}
			} else {
				if (isset($this->h)) {
					$aspectratio = $this->thumbnail_image_width / $this->thumbnail_image_height;
					$this->thumbnail_image_height -= ($this->bw * 2);
					$this->thumbnail_image_width = round($this->thumbnail_image_height * $aspectratio);
				} elseif (($this->thumbnail_image_width + ($this->bw * 2)) < $this->thumbnail_width) {
					$this->thumbnail_image_width = $this->thumbnail_width - ($this->bw * 2);
					$this->thumbnail_image_height  = round($this->thumbnail_image_width / $aspectratio);
				}
			}
			if (!empty($this->brx) && !empty($this->bry) && ($this->bw > 0)) {
				$this->thumbnail_width  = max($this->thumbnail_width,  $this->thumbnail_image_width  + $this->brx);
				$this->thumbnail_height = max($this->thumbnail_height, $this->thumbnail_image_height + $this->bry);
			} else {
				$this->thumbnail_width  = max($this->thumbnail_width,  $this->thumbnail_image_width  + (2 * $this->bw));
				$this->thumbnail_height = max($this->thumbnail_height, $this->thumbnail_image_height + (2 * $this->bw));
			}
		}
		return true;
	}


	function ImageBorder() {
		if (isset($this->bw)) {
			// optional image border and fixed-dimension images (regardless of aspect ratio)
			$this->config_background_hexcolor = (!empty($this->bg) ? $this->bg : $this->config_background_hexcolor);
			$this->config_border_hexcolor     = (!empty($this->bc) ? $this->bc : $this->config_border_hexcolor);
			if (!eregi('^[0-9A-F]{6}$', $this->config_background_hexcolor)) {
				return $this->ErrorImage('Invalid hex color string "'.$this->config_background_hexcolor.'" for parameter "bg"');
			}
			if (!eregi('^[0-9A-F]{6}$', $this->config_border_hexcolor)) {
				return $this->ErrorImage('Invalid hex color string "'.$this->config_border_hexcolor.'" for parameter "bc"');
			}
			$background_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_background_hexcolor);
			$border_color     = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_border_hexcolor);
			ImageFilledRectangle($this->gdimg_output, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $background_color);
			if ($this->bw > 0) {
				// ImageRectangle() draws a rectangle centred on the coordinates given,
				// so coordinates must be offset by half the line thickness
				if (($this->bw > 1) && @ImageSetThickness($this->gdimg_output, $this->bw)) {
					// better way (for lines > 1px thick), but requires GD v2.0.1+
					ImageRectangle($this->gdimg_output, floor($this->bw / 2), floor($this->bw / 2), $this->thumbnail_width - ceil($this->bw / 2), $this->thumbnail_height - ceil($this->bw / 2), $border_color);
				} else {
					for ($i = 0; $i < $this->bw; $i++) {
						ImageRectangle($this->gdimg_output, $i, $i, $this->thumbnail_width - $i - 1, $this->thumbnail_height - $i - 1, $border_color);
					}
				}
			}
			if (!empty($this->brx) && !empty($this->bry) && ($this->bw > 0)) {

				// if 'bw' > 0 then leave the image rectangular and have a rounded border line around the edges of the image
				// if 'bw' == 0 then round off the corners of the image itself (see RoundedImageCorners())

				ImageFilledRectangle($this->gdimg_output,                                   0,                                    0,             $this->brx,              $this->bry, $background_color);
				ImageFilledRectangle($this->gdimg_output, $this->thumbnail_width - $this->brx,                                    0, $this->thumbnail_width,              $this->bry, $background_color);
				ImageFilledRectangle($this->gdimg_output, $this->thumbnail_width - $this->brx, $this->thumbnail_height - $this->bry, $this->thumbnail_width, $this->thumbnail_height, $background_color);
				ImageFilledRectangle($this->gdimg_output,                                   0, $this->thumbnail_height - $this->bry,             $this->brx, $this->thumbnail_height, $background_color);

				// PHP bug: ImageArc() with thicknesses > 1 give bad/undesirable/unpredicatable results
				// Solution: Draw multiple 1px arcs side-by-side.
				if ($this->gd_version(false) >= 2) {
					// imagesetthickness(): requires GD 2.0 or later
					// GD1 always has line thickness of 1
					ImageSetThickness($this->gdimg_output, 1);
				}
				for ($thickness_offset = 0; $thickness_offset < $this->bw; $thickness_offset++) {
					// Problem: parallel arcs give strange/ugly antialiasing problems
					// Solution: draw non-parallel arcs, from one side of the line thickness at the start angle
					//   to the opposite edge of the line thickness at the terminating angle
					if ($this->bw > 1) {
						ImageArc($this->gdimg_output,                                              $this->brx,                       $thickness_offset - 1 + $this->bry, $this->brx * 2, $this->bry * 2, 180, 270, $border_color); // top-left
						ImageArc($this->gdimg_output,                      $thickness_offset - 1 + $this->brx,                                               $this->bry, $this->brx * 2, $this->bry * 2, 180, 270, $border_color); // top-left

						ImageArc($this->gdimg_output,                     $this->thumbnail_width - $this->brx,                       $thickness_offset - 1 + $this->bry, $this->brx * 2, $this->bry * 2, 270, 360, $border_color); // top-right
						ImageArc($this->gdimg_output, $this->thumbnail_width - $thickness_offset - $this->brx,                                               $this->bry, $this->brx * 2, $this->bry * 2, 270, 360, $border_color); // top-right

						ImageArc($this->gdimg_output,                     $this->thumbnail_width - $this->brx, $this->thumbnail_height - $thickness_offset - $this->bry, $this->brx * 2, $this->bry * 2,   0,  90, $border_color); // bottom-right
						ImageArc($this->gdimg_output, $this->thumbnail_width - $thickness_offset - $this->brx,                     $this->thumbnail_height - $this->bry, $this->brx * 2, $this->bry * 2,   0,  90, $border_color); // bottom-right

						ImageArc($this->gdimg_output,                                              $this->brx, $this->thumbnail_height - $thickness_offset - $this->bry, $this->brx * 2, $this->bry * 2,  90, 180, $border_color); // bottom-left
						ImageArc($this->gdimg_output,                     $thickness_offset - 1 +  $this->brx,                     $this->thumbnail_height - $this->bry, $this->brx * 2, $this->bry * 2,  90, 180, $border_color); // bottom-left
					} else {
						ImageArc($this->gdimg_output,                          $this->brx,       $thickness_offset + $this->bry, $this->brx * 2, $this->bry * 2, 180, 270, $border_color); // top-left
						ImageArc($this->gdimg_output, $this->thumbnail_width - $this->brx,                           $this->bry, $this->brx * 2, $this->bry * 2, 270, 360, $border_color); // top-right
						ImageArc($this->gdimg_output, $this->thumbnail_width - $this->brx, $this->thumbnail_height - $this->bry, $this->brx * 2, $this->bry * 2,   0,  90, $border_color); // bottom-right
						ImageArc($this->gdimg_output,                          $this->brx, $this->thumbnail_height - $this->bry, $this->brx * 2, $this->bry * 2,  90, 180, $border_color); // bottom-left
					}
				}


				ImageArc($this->gdimg_output,                          $this->brx,                           $this->bry, $this->brx * 2, $this->bry * 2, 180, 270, $border_color);
				ImageArc($this->gdimg_output, $this->thumbnail_width - $this->brx,                           $this->bry, $this->brx * 2, $this->bry * 2, 270, 360, $border_color);
				ImageArc($this->gdimg_output, $this->thumbnail_width - $this->brx, $this->thumbnail_height - $this->bry, $this->brx * 2, $this->bry * 2,   0,  90, $border_color);
				ImageArc($this->gdimg_output,                          $this->brx, $this->thumbnail_height - $this->bry, $this->brx * 2, $this->bry * 2,  90, 180, $border_color);

			}
		}
		return true;
	}


	function AntiOffsiteLinking() {
		////////////////////////////////////////////////////////////////
		// Optional anti-offsite hijacking of the thumbnail script
		if ($this->config_nohotlink_enabled && (substr(strtolower($this->src), 0, 7) == 'http://')) {
			$parsed_url = parse_url($this->src);
			if (!in_array(@$parsed_url['host'], $this->config_nohotlink_valid_domains)) {
				// This domain is not allowed
				if (!eregi('^[0-9A-F]{6}$', $this->config_nohotlink_fill_hexcolor)) {
					return $this->ErrorImage('Invalid hex color string "'.$this->config_nohotlink_fill_hexcolor.'" for $this->config_nohotlink_fill_hexcolor');
				}
				if (!eregi('^[0-9A-F]{6}$', $this->config_nohotlink_text_hexcolor)) {
					return $this->ErrorImage('Invalid hex color string "'.$this->config_nohotlink_text_hexcolor.'" for $this->config_nohotlink_text_hexcolor');
				}
				if ($this->config_nohotlink_erase_image) {
					return $this->ErrorImage($this->config_nohotlink_text_message, $this->thumbnail_width, $this->thumbnail_height, $this->config_nohotlink_fill_hexcolor, $this->config_nohotlink_text_hexcolor, $this->config_nohotlink_text_fontsize);
				} else {
					$nohotlink_text_array = explode("\n", wordwrap($this->config_nohotlink_text_message, floor($this->thumbnail_width / ImageFontWidth($this->config_nohotlink_text_fontsize)), "\n"));
					$rowcounter = 0;
					$nohotlink_text_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_nohotlink_text_hexcolor);
					foreach ($nohotlink_text_array as $textline) {
						ImageString($this->gdimg_output, $this->config_nohotlink_text_fontsize, 2, $rowcounter++ * ImageFontHeight($this->config_nohotlink_text_fontsize), $textline, $nohotlink_text_color);
					}
				}
			}
		}
		return true;
	}


	function UnsharpMasking() {
		if (!empty($this->usa) || !empty($this->usr)) {
			$this->usa = (isset($this->usa) ? $this->usa : 80);
			$this->usr = (isset($this->usr) ? $this->usr : 0.5);
			$this->ust = (isset($this->ust) ? $this->ust : 3);
			if ($this->gd_version() >= 2.0) {
				if (@include_once('./functions/phpthumb/phpthumb.unsharp.php')) {
					phpUnsharpMask($this->gdimg_output, $this->usa, $this->usr, $this->ust);
				} else {
					return $this->ErrorImage('Error including "phpthumb.unsharp.php" which is required for unsharp masking');
				}
			}
		}
		return true;
	}


	function Watermarking() {
		if (!empty($this->wmf)) {
			$WatermarkFilename = $this->ResolveFilenameToAbsolute($this->wmf);
			if (is_readable($WatermarkFilename)) {
				if ($fp_watermark = @fopen($WatermarkFilename, 'rb')) {
					$WatermarkImageData = fread($fp_watermark, filesize($WatermarkFilename));
					fclose($fp_watermark);
					if ($img_watermark = $this->ImageCreateFromStringReplacement($WatermarkImageData)) {
						$watermark_source_x        = 0;
						$watermark_source_y        = 0;
						$watermark_source_width    = ImageSX($img_watermark);
						$watermark_source_height   = ImageSY($img_watermark);
						$watermark_opacity_percent = (!empty($this->wmp) ? $this->wmp : 50);
						$watermark_margin_percent  = (100 - (!empty($this->wmm) ? $this->wmm : 5)) / 100;
						switch (@$this->wma) {
							case '*':
								$gdimg_tiledwatermark = $this->ImageCreateFunction($this->thumbnail_width, $this->thumbnail_height);
								// set the tiled image transparent color to whatever the untiled image transparency index is
								ImageColorTransparent($gdimg_tiledwatermark, ImageColorTransparent($img_watermark));

								// tile the image as many times as can fit
								for ($x = round((1 - $watermark_margin_percent) * $this->thumbnail_width); $x < ($this->thumbnail_width + $watermark_source_width); $x += round($watermark_source_width + ((1 - $watermark_margin_percent) * $this->thumbnail_width))) {
									for ($y = round((1 - $watermark_margin_percent) * $this->thumbnail_height); $y < ($this->thumbnail_height + $watermark_source_height); $y += round($watermark_source_height + ((1 - $watermark_margin_percent) * $this->thumbnail_height))) {
										ImageCopy($gdimg_tiledwatermark, $img_watermark, $x, $y, 0, 0, $watermark_source_width, $watermark_source_height);
									}
								}
								$watermark_source_width  = ImageSX($gdimg_tiledwatermark);
								$watermark_source_height = ImageSY($gdimg_tiledwatermark);
								$watermark_destination_x = 0;
								$watermark_destination_y = 0;
								ImageDestroy($img_watermark);
								$img_watermark = $gdimg_tiledwatermark;
								break;

							case 'T':
								$watermark_destination_x = round((($this->thumbnail_width  / 2) - ($watermark_source_width / 2)) + $watermark_margin_percent);
								$watermark_destination_y = round((1 - $watermark_margin_percent) * $this->thumbnail_height);
								break;

							case 'B':
								$watermark_destination_x = round((($this->thumbnail_width  / 2) - ($watermark_source_width / 2)) + $watermark_margin_percent);
								$watermark_destination_y = round(($this->thumbnail_height - $watermark_source_height) * $watermark_margin_percent);
								break;

							case 'L':
								$watermark_destination_x = round((1 - $watermark_margin_percent) * $this->thumbnail_width);
								$watermark_destination_y = round((($this->thumbnail_height / 2) - ($watermark_source_height / 2)) + $watermark_margin_percent);
								break;

							case 'R':
								$watermark_destination_x = round(($this->thumbnail_width - $watermark_source_width)  * $watermark_margin_percent);
								$watermark_destination_y = round((($this->thumbnail_height / 2) - ($watermark_source_height / 2)) + $watermark_margin_percent);
								break;

							case 'C':
								$watermark_destination_x = round((($this->thumbnail_width  / 2) - ($watermark_source_width / 2)) + $watermark_margin_percent);
								$watermark_destination_y = round((($this->thumbnail_height / 2) - ($watermark_source_height / 2)) + $watermark_margin_percent);
								break;

							case 'TL':
								$watermark_destination_x = round((1 - $watermark_margin_percent) * $this->thumbnail_width);
								$watermark_destination_y = round((1 - $watermark_margin_percent) * $this->thumbnail_height);
								break;

							case 'TR':
								$watermark_destination_x = round(($this->thumbnail_width - $watermark_source_width)  * $watermark_margin_percent);
								$watermark_destination_y = round((1 - $watermark_margin_percent) * $this->thumbnail_height);
								break;

							case 'BL':
								$watermark_destination_x = round((1 - $watermark_margin_percent) * $this->thumbnail_width);
								$watermark_destination_y = round(($this->thumbnail_height - $watermark_source_height) * $watermark_margin_percent);
								break;

							case 'BR':
							default:
								$watermark_destination_x = round(($this->thumbnail_width - $watermark_source_width)  * $watermark_margin_percent);
								$watermark_destination_y = round(($this->thumbnail_height - $watermark_source_height) * $watermark_margin_percent);
								break;
						}
						ImageCopyMerge($this->gdimg_output, $img_watermark, $watermark_destination_x, $watermark_destination_y, $watermark_source_x, $watermark_source_y, $watermark_source_width, $watermark_source_height, $watermark_opacity_percent);
						return true;
					}
				}
			}
			return false;
		}
		return true;
	}


	function RoundedImageCorners() {
		if ($this->gd_version() < 2) {
			return false;
		}
		if (!empty($this->brx) && !empty($this->bry) && ($this->bw == 0)) {
			$gdimg_cornermask = $this->ImageCreateFunction($this->thumbnail_width, $this->thumbnail_height);
			$background_color_cornermask  = phpthumb_functions::ImageHexColorAllocate($gdimg_cornermask, $this->config_background_hexcolor);
			$border_color_cornermask      = phpthumb_functions::ImageHexColorAllocate($gdimg_cornermask, $this->config_border_hexcolor);

			// Top Left
			ImageArc($gdimg_cornermask, $this->brx - 1, $this->bry - 1, $this->brx * 2, $this->bry * 2, 180, 270, $background_color_cornermask);
			ImageFillToBorder($gdimg_cornermask, 0, 0, $background_color_cornermask, $background_color_cornermask);

			// Top Right
			ImageArc($gdimg_cornermask, $this->thumbnail_width - $this->brx, $this->bry - 1, $this->brx * 2, $this->bry * 2, 270, 360, $background_color_cornermask);
			ImageFillToBorder($gdimg_cornermask, $this->thumbnail_width, 0, $background_color_cornermask, $background_color_cornermask);

			// Bottom Right
			ImageArc($gdimg_cornermask, $this->thumbnail_width - $this->brx, $this->thumbnail_height - $this->bry, $this->brx * 2, $this->bry * 2, 0, 90, $background_color_cornermask);
			ImageFillToBorder($gdimg_cornermask, $this->thumbnail_width, $this->thumbnail_height, $background_color_cornermask, $background_color_cornermask);

			// Bottom Left
			ImageArc($gdimg_cornermask, $this->brx - 1, $this->thumbnail_height - $this->bry, $this->brx * 2, $this->bry * 2, 90, 180, $background_color_cornermask);
			ImageFillToBorder($gdimg_cornermask, 0, $this->thumbnail_height, $background_color_cornermask, $background_color_cornermask);

			$transparent_color_cornermask = ImageColorTransparent($gdimg_cornermask, ImageColorAt($gdimg_cornermask, round($this->thumbnail_width / 2), round($this->thumbnail_height / 2)));
			ImageArc($gdimg_cornermask, $this->brx, $this->bry, $this->brx * 2, $this->bry * 2, 180, 270, $transparent_color_cornermask);
			ImageArc($gdimg_cornermask, $this->thumbnail_width - $this->brx, $this->bry, $this->brx * 2, $this->bry * 2, 270, 360, $transparent_color_cornermask);
			ImageArc($gdimg_cornermask, $this->thumbnail_width - $this->brx, $this->thumbnail_height - $this->bry, $this->brx * 2, $this->bry * 2, 0, 90, $transparent_color_cornermask);
			ImageArc($gdimg_cornermask, $this->brx, $this->thumbnail_height - $this->bry, $this->brx * 2, $this->bry * 2, 90, 180, $transparent_color_cornermask);

			ImageCopyMerge($this->gdimg_output, $gdimg_cornermask, 0, 0, 0, 0, $this->thumbnail_width, $this->thumbnail_height, 100);

			// Make rounded corners transparent (optional)
			if (!empty($this->bct)) {
				if ($this->bct == 256) {
					ImageTrueColorToPalette($this->gdimg_output, true, 256);
				}
				ImageColorTransparent($this->gdimg_output, ImageColorAt($this->gdimg_output, 0, 0));
			}
		}
		return true;
	}


	function MaxFileSize() {
		if ($this->gd_version() < 2) {
			return false;
		}
		if (!empty($this->maxb) && ($this->maxb > 0)) {
			switch ($this->thumbnailFormat) {
				case 'png':
				case 'gif':
					$imgRenderFunction = 'image'.$this->thumbnailFormat;

					ob_start();
					$imgRenderFunction($this->gdimg_output);
					$imgdata = ob_get_contents();
					ob_end_clean();

					if (strlen($imgdata) > $this->maxb) {
						for ($i = 8; $i >= 1; $i--) {
							$tempIMG = ImageCreateTrueColor(ImageSX($this->gdimg_output), ImageSY($this->gdimg_output));
							ImageCopy($tempIMG, $this->gdimg_output, 0, 0, 0, 0, ImageSX($this->gdimg_output), ImageSY($this->gdimg_output));
							ImageTrueColorToPalette($tempIMG, true, pow(2, $i));
							ob_start();
							$imgRenderFunction($tempIMG);
							$imgdata = ob_get_contents();
							ob_end_clean();

							if (strlen($imgdata) <= $this->maxb) {
								ImageTrueColorToPalette($this->gdimg_output, true, pow(2, $i));
								break;
							}
						}
					}
					if (strlen($imgdata) > $this->maxb) {
						ImageTrueColorToPalette($this->gdimg_output, true, pow(2, $i));
						return false;
					}
					break;

				case 'jpeg':
					ob_start();
					ImageJPEG($this->gdimg_output);
					$imgdata = ob_get_contents();
					ob_end_clean();

					$OriginalJPEGquality = $this->thumbnailQuality;
					if (strlen($imgdata) > $this->maxb) {
						for ($i = 3; $i < 20; $i++) {
							$q = round(100 * (1 - log10($i / 2)));
							ob_start();
							ImageJPEG($this->gdimg_output, '', $q);
							$imgdata = ob_get_contents();
							ob_end_clean();

							$this->thumbnailQuality = $q;
							if (strlen($imgdata) <= $this->maxb) {
								break;
							}
						}
					}
					if (strlen($imgdata) > $this->maxb) {
						return false;
					}
					break;

				default:
					return false;
					break;
			}
		}
		return true;
	}


	function CalculateThumbnailDimensions() {

		$this->thumbnailCropX = (!empty($this->sx) ? (($this->sx >= 1) ? $this->sx : round($this->sx * $this->source_width))  : 0);
		$this->thumbnailCropY = (!empty($this->sy) ? (($this->sy >= 1) ? $this->sy : round($this->sy * $this->source_height)) : 0);
		$this->thumbnailCropW = (!empty($this->sw) ? (($this->sw >= 1) ? $this->sw : round($this->sw * $this->source_width))  : $this->source_width);
		$this->thumbnailCropH = (!empty($this->sh) ? (($this->sh >= 1) ? $this->sh : round($this->sh * $this->source_height)) : $this->source_height);

		// limit source area to original image area
		$this->thumbnailCropW = max(1, min($this->thumbnailCropW, $this->source_width  - $this->thumbnailCropX));
		$this->thumbnailCropH = max(1, min($this->thumbnailCropH, $this->source_height - $this->thumbnailCropY));

		$this->DebugMessage('CalculateThumbnailDimensions() [x,y,w,h] initially set to ['.$this->thumbnailCropX.','.$this->thumbnailCropY.','.$this->thumbnailCropW.','.$this->thumbnailCropH.']', __FILE__, __LINE__);

		if (!empty($this->iar) && !empty($this->w) && !empty($this->h)) {

			// Ignore Aspect Ratio
			// forget all the careful proportional resizing we did above, stretch image to fit 'w' && 'h'
			$this->thumbnail_width  = $this->w;
			$this->thumbnail_height = $this->h;
			$this->thumbnail_image_width  = $this->thumbnail_width  - (@$this->bw * 2);
			$this->thumbnail_image_height = $this->thumbnail_height - (@$this->bw * 2);

		} else {

			// default new width and height to source area
			$this->thumbnail_image_width  = $this->thumbnailCropW;
			$this->thumbnail_image_height = $this->thumbnailCropH;
			if (($this->config_output_maxwidth > 0) && ($this->thumbnail_image_width > $this->config_output_maxwidth)) {
				if (($this->config_output_maxwidth < $this->thumbnailCropW) || $this->config_output_allow_enlarging) {
					$maxwidth = $this->config_output_maxwidth;
					$this->thumbnail_image_width = $maxwidth;
					$this->thumbnail_image_height = round($this->thumbnailCropH * ($this->thumbnail_image_width / $this->thumbnailCropW));
				}
			}

			// if user sets width, save as max width
			// and compute new height based on source area aspect ratio
			if (!empty($this->w)) {
				if (($this->w < $this->thumbnailCropW) || $this->config_output_allow_enlarging) {
					$maxwidth = $this->w;
					$this->thumbnail_image_width = $this->w;
					$this->thumbnail_image_height = round($this->thumbnailCropH * $this->w / $this->thumbnailCropW);
				}
			}

			// if user sets height, save as max height
			// if the max width has already been set and the new image is too tall,
			// compute new width based on source area aspect ratio
			// otherwise, use max height and compute new width
			if (!empty($this->h) || ($this->config_output_maxheight > 0)) {
				$maxheight = (!empty($this->h) ? $this->h : $this->config_output_maxheight);
				if (($maxheight < $this->thumbnailCropH) || $this->config_output_allow_enlarging) {
					if (isset($maxwidth)) {
						if ($this->thumbnail_image_height > $maxheight) {
							$this->thumbnail_image_width  = round($this->thumbnailCropW * $maxheight / $this->thumbnailCropH);
							$this->thumbnail_image_height = $maxheight;
						}
					} else {
						$this->thumbnail_image_height = $maxheight;
						$this->thumbnail_image_width  = round($this->thumbnailCropW * $this->thumbnail_image_height / $this->thumbnailCropH);
					}
				}
			}

			$this->thumbnail_width  = $this->thumbnail_image_width;
			$this->thumbnail_height = $this->thumbnail_image_height;
			if (!empty($this->w) && !empty($this->h) && isset($this->bw)) {
				$this->thumbnail_width  = $this->w;
				$this->thumbnail_height = $this->h;
			}

			$this->FixedAspectRatio();

		}
		return true;
	}


	function CreateGDoutput() {

		$this->CalculateThumbnailDimensions();

		// Create the GD image (either true-color or 256-color, depending on GD version)
		$this->gdimg_output = $this->ImageCreateFunction($this->thumbnail_width, $this->thumbnail_height);


		// Images that have transparency must have the background filled with the configured 'bg' color
		// otherwise the transparent color will appear as black
		$current_transparent_color = ImageColorTransparent($this->gdimg_source);
		if ($current_transparent_color >= 0) {

			$this->config_background_hexcolor = (!empty($this->bg) ? $this->bg : $this->config_background_hexcolor);
			if (!eregi('^[0-9A-F]{6}$', $this->config_background_hexcolor)) {
				return $this->ErrorImage('Invalid hex color string "'.$this->config_background_hexcolor.'" for parameter "bg"');
			}
			$background_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_background_hexcolor);
			ImageFilledRectangle($this->gdimg_output, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $background_color);

		}
		return true;
	}



	function ExtractEXIFgetImageSize() {

		if ($this->getimagesizeinfo = @GetImageSize($this->sourceFilename)) {

			$this->source_width  = $this->getimagesizeinfo[0];
			$this->source_height = $this->getimagesizeinfo[1];

			if (function_exists('exif_thumbnail') && ($this->getimagesizeinfo[2] == 2)) {
				// Extract EXIF info from JPEGs

				$this->exif_thumbnail_width  = '';
				$this->exif_thumbnail_height = '';
				$this->exif_thumbnail_type   = '';

				// The parameters width, height and imagetype are available since PHP v4.3.0
				if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.0', '>=')) {

					$this->exif_thumbnail_data = @exif_thumbnail($this->sourceFilename, $this->exif_thumbnail_width, $this->exif_thumbnail_height, $this->exif_thumbnail_type);

				} else {

					// older versions of exif_thumbnail output an error message but NOT return false on failure
					ob_start();
					$this->exif_thumbnail_data = exif_thumbnail($this->sourceFilename);
					$exit_thumbnail_error = ob_get_contents();
					ob_end_clean();
					if (empty($exit_thumbnail_error) && !empty($this->exif_thumbnail_data)) {

						if ($gdimg_exif_temp = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false)) {
							$this->exif_thumbnail_width  = ImageSX($gdimg_exif_temp);
							$this->exif_thumbnail_height = ImageSY($gdimg_exif_temp);
							$this->exif_thumbnail_type   = 2; // (2 == JPEG) before PHP v4.3.0 only JPEG format EXIF thumbnails are returned
							unset($gdimg_exif_temp);
						} else {
							return $this->ErrorImage('Failed - $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data) in '.__FILE__.' on line '.__LINE__);
						}

					}

				}

			} elseif (!function_exists('exif_thumbnail')) {

				$this->DebugMessage('exif_thumbnail() does not exist, cannot extract EXIF thumbnail', __FILE__, __LINE__);

			} else {

				//$this->DebugMessage('"'.$this->sourceFilename.'" is not JPEG, therefore no EXIF is present', __FILE__, __LINE__);

			}

			// see if EXIF thumbnail can be used directly with no processing
			if (!empty($this->exif_thumbnail_data)) {
				while (true) {
					if (empty($this->xto)) {
						if (isset($this->w) && ($this->w != $this->exif_thumbnail_width)) {
							break;
						}
						if (isset($this->h) && ($this->h != $this->exif_thumbnail_height)) {
							break;
						}
						$CannotBeSetParameters = array('sx', 'sy', 'sh', 'sw', 'bw', 'bg', 'bc', 'usa', 'usr', 'ust', 'wmf', 'wmp', 'wmm', 'wma');
						foreach ($CannotBeSetParameters as $parameter) {
							if (!empty($this->$parameter)) {
								break 2;
							}
						}
					}

					// EXIF thumbnail can be used directly for these parameters - write cached file
					$ImageTypesLookup = array(2=>'jpeg'); // EXIF thumbnails are (currently?) only availble from JPEG source images
					if (is_dir($this->config_cache_directory) && is_writable($this->config_cache_directory) && isset($ImageTypesLookup[$this->exif_thumbnail_type])) {
						if (is_writable($this->cache_filename)) {
							if ($fp_cached = @fopen($this->cache_filename, 'wb')) {
								fwrite($fp_cached, $this->exif_thumbnail_data);
								fclose($fp_cached);
							}
						}
					}

					if ($mime_type = phpthumb_functions::ImageTypeToMIMEtype($this->exif_thumbnail_type)) {
						header('Content-type: '.$mime_type);
						echo $this->exif_thumbnail_data;
						exit;
					} else {
						return $this->ErrorImage('phpthumb_functions::ImageTypeToMIMEtype('.$this->exif_thumbnail_type.') failed in '.__FILE__.' on line '.__LINE__);
					}
					break;
				}
			}

			if (($this->config_max_source_pixels > 0) && (($this->source_width * $this->source_height) > $this->config_max_source_pixels)) {
				// Source image is larger than would fit in available PHP memory.
				// If ImageMagick is installed, use it to generate the thumbnail.
				// Else, if an EXIF thumbnail is available, use that as the source image.
				// Otherwise, no choice but to fail with an error message

				if ($this->ImageMagickThumbnailToGD()) {

					// excellent, we have a thumbnailed source image

				} elseif (!empty($this->exif_thumbnail_data)) {

					// EXIF thumbnail exists, and will be use as source image
					$this->gdimg_source  = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data);
					$this->source_width  = $this->exif_thumbnail_width;
					$this->source_height = $this->exif_thumbnail_height;

					// override allow-enlarging setting if EXIF thumbnail is the only source available
					// otherwise thumbnails larger than the EXIF thumbnail will be created at EXIF size
					$this->config_output_allow_enlarging = true;

				} else {

					return $this->ErrorImage('Source image is more than '.sprintf('%1.1f', ($this->config_max_source_pixels / 1000000)).' megapixels - insufficient memory.'."\n".'EXIF thumbnail unavailable.');

				}
			}

		} else {

			$this->DebugMessage('GetImageSize("'.$this->sourceFilename.'") failed', __FILE__, __LINE__);

		}
		return true;
	}


	function SetCacheFilename() {
		$this->setOutputFormat();
		$this->setCacheDirectory();
		if (empty($this->config_cache_directory)) {
			$this->DebugMessage('SetCacheFilename() failed because $this->config_cache_directory is empty', __FILE__, __LINE__);
			return false;
		}

		if (empty($this->sourceFilename) && empty($this->rawImageData) && !empty($this->src)) {
			$this->sourceFilename = $this->ResolveFilenameToAbsolute($this->src);
		}

		$this->cache_filename  = $this->config_cache_directory.'/phpThumb_cache';
		if (empty($this->src) && !empty($this->rawImageData)) {
			$this->cache_filename .= '_'.strtolower(md5($this->rawImageData));
		} else {
			$this->cache_filename .= '_'.urlencode($this->src);
		}
		$FilenameParameters = array('h', 'w', 'sx', 'sy', 'sw', 'sh', 'bw', 'brx', 'bry', 'bg', 'bgt', 'bc', 'usa', 'usr', 'ust', 'wmf', 'wmp', 'wmm', 'wma', 'xto', 'ra', 'ar', 'iar', 'maxb');
		foreach ($FilenameParameters as $key) {
			if (isset($this->$key)) {
				if ($this->$key === true) {
					$this->cache_filename .= '_'.$key.'1';
				} else {
					$this->cache_filename .= '_'.$key.$this->$key;
				}
			}
		}
		$this->cache_filename .= '_'.intval(@filemtime($this->sourceFilename));
		$this->cache_filename .= '_q'.$this->thumbnailQuality;
		$this->cache_filename .= '_'.$this->thumbnailFormat;

		return true;
	}

	function SourceImageToGD() {

		if ($this->config_use_exif_thumbnail_for_speed && !empty($this->exif_thumbnail_data)) {
			if (($this->exif_thumbnail_width >= $this->thumbnail_image_width) && ($this->exif_thumbnail_height >= $this->thumbnail_image_height) &&
				($this->thumbnailCropX == 0) && ($this->thumbnailCropY == 0) &&
				($this->source_width == $this->thumbnailCropW) && ($this->source_height == $this->thumbnailCropH)) {
					// EXIF thumbnail exists, and is equal to or larger than destination thumbnail, and will be use as source image
					// Only benefit here is greater speed, not lower memory usage
					$this->DebugMessage('Trying to use EXIF thumbnail as source image', __FILE__, __LINE__);

					if ($gdimg_exif_temp = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false)) {

						$this->DebugMessage('Successfully using EXIF thumbnail as source image', __FILE__, __LINE__);

						$this->gdimg_source = $gdimg_exif_temp;
						$this->source_width  = $this->exif_thumbnail_width;
						$this->source_height = $this->exif_thumbnail_height;
						$this->thumbnailCropW = $this->source_width;
						$this->thumbnailCropH = $this->source_height;

						return true;

					} else {
						$this->DebugMessage('$this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false) failed', __FILE__, __LINE__);
					}

			} else {
				$this->DebugMessage('Not using EXIF thumbnail data because EXIF thumbnail is too small', __FILE__, __LINE__);
			}

		} else {

			if (!$this->config_use_exif_thumbnail_for_speed) {
				$this->DebugMessage('Not using EXIF thumbnail data because $this->config_use_exif_thumbnail_for_speed is FALSE', __FILE__, __LINE__);
			} elseif ($this->getimagesizeinfo[2] == 2) {
				$this->DebugMessage('Not using EXIF thumbnail data because EXIF thumbnail is unavailable', __FILE__, __LINE__);
			} else {
				//$this->DebugMessage('Not using EXIF thumbnail data because source image is not JPEG, therefore no EXIF thumbnail available', __FILE__, __LINE__);
			}

		}

		if (empty($this->gdimg_source)) {
			// try to create GD image source directly via GD, if possible,
			// rather than buffering to memory and creating with ImageCreateFromString
			$ImageCreateWasAttempted = false;

			if ($this->iswindows && ((substr($this->sourceFilename, 0, 2) == '//') || (substr($this->sourceFilename, 0, 2) == '\\\\'))) {
				// Windows \\share\filename.ext
			} elseif (substr($this->sourceFilename, 0, 7) == 'http://') {
				// URL
			} else {
				if (!file_exists($this->sourceFilename)) {
					return $this->ErrorImage('"'.$this->sourceFilename.'" does not exist');
				} elseif (!is_file($this->sourceFilename)) {
					return $this->ErrorImage('"'.$this->sourceFilename.'" is not a file');
				}
			}

			$ImageCreateFromFunction = array(
				1  => 'ImageCreateFromGIF',
				2  => 'ImageCreateFromJPEG',
				3  => 'ImageCreateFromPNG',
				15 => 'ImageCreateFromWBMP',
			);
			switch (@$this->getimagesizeinfo[2]) {
				case 1:  // GIF
				case 2:  // JPEG
				case 3:  // PNG
				case 15: // WBMP
					$ImageCreateFromFunctionName = $ImageCreateFromFunction[$this->getimagesizeinfo[2]];
					if (function_exists($ImageCreateFromFunctionName)) {
						$this->DebugMessage('Calling '.$ImageCreateFromFunctionName.'('.$this->sourceFilename.')', __FILE__, __LINE__);
						$ImageCreateWasAttempted = true;
						$this->gdimg_source = @$ImageCreateFromFunctionName($this->sourceFilename);
					} else {
						$this->DebugMessage('NOT calling '.$ImageCreateFromFunctionName.'('.$this->sourceFilename.') because !function_exists('.$ImageCreateFromFunctionName.')', __FILE__, __LINE__);
					}
					break;

				default:
					$this->DebugMessage('Unknown value for $this->getimagesizeinfo[2]: "'.@$this->getimagesizeinfo[2].'"', __FILE__, __LINE__);
					break;
			}
			if (empty($this->gdimg_source)) {
				// cannot create from filename, attempt to create source image with ImageCreateFromString, if possible
				if ($ImageCreateWasAttempted) {
					$this->DebugMessage(@$ImageCreateFromFunctionName.'() was attempted but FAILED', __FILE__, __LINE__);
				}
				if (empty($this->rawImageData)) {
					$this->DebugMessage('Populating $this->rawImageData and attempting ImageCreateFromStringReplacement()', __FILE__, __LINE__);
					if ($fp = @fopen($this->sourceFilename, 'rb')) {

						$this->rawImageData = '';
						$filesize = filesize($this->sourceFilename);
						$blocksize = 16384;
						$blockreads = ceil($filesize / $blocksize);
						for ($i = 0; $i < $blockreads; $i++) {
						//while (feof($fp) !== false) {
							$this->rawImageData .= fread($fp, $blocksize);
						}
						fclose($fp);
						$this->gdimg_source = $this->ImageCreateFromStringReplacement($this->rawImageData, true);

					} else {
						return $this->ErrorImage('cannot fopen("'.$this->sourceFilename.'") on line '.__LINE__.' of '.__FILE__);
					}
				}
			}

			if (empty($this->gdimg_source)) {
				$this->DebugMessage('$this->gdimg_source is still empty', __FILE__, __LINE__);

				if ($this->ImageMagickThumbnailToGD()) {

					// excellent, we have a thumbnailed source image
					$this->DebugMessage('ImageMagickThumbnailToGD() succeeded', __FILE__, __LINE__);

				} else {

					// cannot create image for whatever reason (maybe ImageCreateFromJPEG et al are not available?)
					
					//jpell changed
					return false;
					//end jpell changed
					
					// and ImageMagick is not available either, no choice but to output original (not resized/modified) data and exit

					/*$imageHeader = '';
					switch (substr($this->rawImageData, 0, 3)) {
						case 'GIF':
							$imageHeader = 'Content-type: image/gif';
							break;
						case "\xFF\xD8\xFF":
							$imageHeader = 'Content-type: image/jpeg';
							break;
						case "\x89".'PN':
							$imageHeader = 'Content-type: image/png';
							break;
					}
					if ($imageHeader) {
						$this->DebugMessage('All attempts to create GD image source failed, outputing raw image', __FILE__, __LINE__);
						
						//header($imageHeader);
						//echo $this->rawImageData;
						//exit;
					}

					switch (substr($this->rawImageData, 0, 2)) {
						case 'BM':
							if (@include_once('phpthumb.bmp.php')) {
								$phpthumb_bmp = new phpthumb_bmp;
								if ($this->gdimg_source = $phpthumb_bmp->phpthumb_bmp2gd($this->rawImageData, ($this->gd_version() >= 2.0))) {
									$this->DebugMessage('$phpthumb_bmp->phpthumb_bmp2gd() succeeded', __FILE__, __LINE__);
									break;
								} else {
									return $this->ErrorImage('phpthumb_bmp2db failed');
								}
							} else {
								return $this->ErrorImage('include_once(phpthumb.bmp.php) failed');
							}
							return $this->ErrorImage('ImageMagick is unavailable and phpThumb() does not support BMP source images without it');
							break;
					}

					switch (substr($this->rawImageData, 0, 4)) {
						case 'II'."\x2A\x00":
						case 'MM'."\x00\x2A":
							return $this->ErrorImage('ImageMagick is unavailable and phpThumb() does not support TIFF source images without it');
							break;
					}

					if (empty($this->gdimg_source)) {
						return $this->ErrorImage('Unknown image type identified by "'.substr($this->rawImageData, 0, 4).'" ('.phpthumb_functions::HexCharDisplay(substr($this->rawImageData, 0, 4)).') in SourceImageToGD()');
					}
					*/
					//end jpell changed
				}
			}

		}
		$this->source_width  = ImageSX($this->gdimg_source);
		$this->source_height = ImageSY($this->gdimg_source);
		return true;
	}




	function phpThumbDebugVarDump($var) {
		if (is_null($var)) {
			return 'null';
		} elseif (is_bool($var)) {
			return ($var ? 'TRUE' : 'FALSE');
		} elseif (is_string($var)) {
			return 'string('.strlen($var).')'.str_repeat(' ', max(0, 3 - strlen(strlen($var)))).' "'.$var.'"';
		} elseif (is_int($var)) {
			return 'integer     '.$var;
		} elseif (is_float($var)) {
			return 'float       '.$var;
		} elseif (is_array($var)) {
			ob_start();
			var_dump($var);
			$vardumpoutput = ob_get_contents();
			ob_end_clean();
			return strtr($vardumpoutput, "\n\r\t", '   ');
		}
		return gettype($var);
	}

	function phpThumbDebug() {
		if ($this->config_disable_debug) {
			return $this->ErrorImage('phpThumbDebug disabled');
		}

		$FunctionsExistance = array('exif_thumbnail', 'gd_info', 'image_type_to_mime_type', 'ImageCopyResampled', 'ImageCopyResized', 'ImageCreate', 'ImageCreateFromString', 'ImageCreateTrueColor', 'ImageIsTrueColor', 'ImageRotate', 'ImageTypes', 'version_compare', 'ImageCreateFromGIF', 'ImageCreateFromJPEG', 'ImageCreateFromPNG', 'ImageCreateFromWBMP', 'ImageCreateFromXBM', 'ImageCreateFromXPM', 'ImageCreateFromString', 'ImageCreateFromGD', 'ImageCreateFromGD2', 'ImageCreateFromGD2Part', 'ImageJPEG', 'ImageGIF', 'ImagePNG', 'ImageWBMP');
		$ParameterNames     = array('src', 'w', 'h', 'f', 'q', 'sx', 'sy', 'sw', 'sh', 'bw', 'bg', 'bgt', 'bc', 'usr', 'usa', 'ust', 'wmf', 'wmp', 'wmm', 'wma', 'file', 'goto', 'err', 'xto', 'ra', 'ar', 'aoe', 'iar', 'brx', 'bry', 'maxb');
		$OtherVariableNames = array('phpThumbDebug', 'thumbnailQuality', 'thumbnailFormat', 'gdimg_output', 'gdimg_source', 'sourceFilename', 'source_width', 'source_height', 'thumbnailCropX', 'thumbnailCropY', 'thumbnailCropW', 'thumbnailCropH', 'exif_thumbnail_width', 'exif_thumbnail_height', 'exif_thumbnail_type', 'thumbnail_width', 'thumbnail_height', 'thumbnail_image_width', 'thumbnail_image_height');

		$DebugOutput = array();
		$DebugOutput[] = 'phpThumb() version         = '.$this->phpthumb_version;
		$DebugOutput[] = 'phpversion()               = '.@phpversion();
		$DebugOutput[] = 'PHP_OS                     = '.PHP_OS;
		$DebugOutput[] = '$_SERVER[PHP_SELF]         = '.@$_SERVER['PHP_SELF'];
		$DebugOutput[] = '$_SERVER[DOCUMENT_ROOT]    = '.@$_SERVER['DOCUMENT_ROOT'];
		$DebugOutput[] = 'realpath(.)                = '.@realpath('.');
		$DebugOutput[] = 'get_magic_quotes_gpc()     = '.@get_magic_quotes_gpc();
		$DebugOutput[] = 'get_magic_quotes_runtime() = '.@get_magic_quotes_runtime();
		$DebugOutput[] = 'ini_get(error_reporting)   = '.@ini_get('error_reporting');
		$DebugOutput[] = 'ini_get(allow_url_fopen)   = '.@ini_get('allow_url_fopen');
		$DebugOutput[] = 'ini_get(disable_functions) = '.@ini_get('disable_functions');
		$DebugOutput[] = 'ini_get(safe_mode)         = '.@ini_get('safe_mode');
		$DebugOutput[] = 'ini_get(open_basedir)      = '.@ini_get('open_basedir');
		$DebugOutput[] = 'ini_get(memory_limit)      = '.@ini_get('memory_limit');
		$DebugOutput[] = 'get_cfg_var(memory_limit)  = '.@get_cfg_var('memory_limit');
		$DebugOutput[] = 'memory_get_usage()         = '.(function_exists('memory_get_usage') ? @memory_get_usage() : 'n/a');
		$DebugOutput[] = '';

		$DebugOutput[] = '$this->config_imagemagick_path              = '.$this->config_imagemagick_path;
		$DebugOutput[] = 'SafeBackTick(which convert)                 = '.trim(phpthumb_functions::SafeBackTick('which convert'));
		$IMpathUsed = ($this->config_imagemagick_path ? $this->config_imagemagick_path : trim(phpthumb_functions::SafeBackTick('which convert')));
		$DebugOutput[] = '[actual ImageMagick path used]              = '.$this->phpThumbDebugVarDump($IMpathUsed);
		$DebugOutput[] = 'file_exists([actual ImageMagick path used]) = '.$this->phpThumbDebugVarDump(file_exists($IMpathUsed));
		$DebugOutput[] = 'ImageMagickVersion()                        = '.$this->ImageMagickVersion();
		$DebugOutput[] = '';

		$DebugOutput[] = '$this->config_cache_directory               = '.$this->phpThumbDebugVarDump($this->config_cache_directory);
		$DebugOutput[] = '$this->cache_filename                       = '.$this->phpThumbDebugVarDump($this->cache_filename);
		$DebugOutput[] = 'is_writable($this->config_cache_directory)  = '.$this->phpThumbDebugVarDump(is_writable($this->config_cache_directory));
		$DebugOutput[] = 'is_writable($this->cache_filename)          = '.(file_exists($this->cache_filename) ? $this->phpThumbDebugVarDump(is_writable($this->cache_filename)) : 'n/a');
		$DebugOutput[] = '';

		$DebugOutput[] = '$this->config_document_root                 = '.$this->phpThumbDebugVarDump($this->config_document_root);
		$DebugOutput[] = '$this->config_output_format                 = '.$this->phpThumbDebugVarDump($this->config_output_format);
		$DebugOutput[] = '$this->config_output_maxwidth               = '.$this->phpThumbDebugVarDump($this->config_output_maxwidth);
		$DebugOutput[] = '$this->config_output_maxheight              = '.$this->phpThumbDebugVarDump($this->config_output_maxheight);
		$DebugOutput[] = '$this->config_error_message_image_default   = '.$this->phpThumbDebugVarDump($this->config_error_message_image_default);
		$DebugOutput[] = '$this->config_error_bgcolor                 = '.$this->phpThumbDebugVarDump($this->config_error_bgcolor);
		$DebugOutput[] = '$this->config_error_textcolor               = '.$this->phpThumbDebugVarDump($this->config_error_textcolor);
		$DebugOutput[] = '$this->config_error_fontsize                = '.$this->phpThumbDebugVarDump($this->config_error_fontsize);
		$DebugOutput[] = '$this->config_nohotlink_enabled             = '.$this->phpThumbDebugVarDump($this->config_nohotlink_enabled);
		$DebugOutput[] = '$this->config_nohotlink_valid_domains       = '.$this->phpThumbDebugVarDump($this->config_nohotlink_valid_domains);
		$DebugOutput[] = '$this->config_nohotlink_erase_image         = '.$this->phpThumbDebugVarDump($this->config_nohotlink_erase_image);
		$DebugOutput[] = '$this->config_nohotlink_fill_hexcolor       = '.$this->phpThumbDebugVarDump($this->config_nohotlink_fill_hexcolor);
		$DebugOutput[] = '$this->config_nohotlink_text_hexcolor       = '.$this->phpThumbDebugVarDump($this->config_nohotlink_text_hexcolor);
		$DebugOutput[] = '$this->config_nohotlink_text_message        = '.$this->phpThumbDebugVarDump($this->config_nohotlink_text_message);
		$DebugOutput[] = '$this->config_nohotlink_text_fontsize       = '.$this->phpThumbDebugVarDump($this->config_nohotlink_text_fontsize);
		$DebugOutput[] = '$this->config_border_hexcolor               = '.$this->phpThumbDebugVarDump($this->config_border_hexcolor);
		$DebugOutput[] = '$this->config_background_hexcolor           = '.$this->phpThumbDebugVarDump($this->config_background_hexcolor);
		$DebugOutput[] = '$this->config_max_source_pixels             = '.$this->phpThumbDebugVarDump($this->config_max_source_pixels);
		$DebugOutput[] = '$this->config_use_exif_thumbnail_for_speed  = '.$this->phpThumbDebugVarDump($this->config_use_exif_thumbnail_for_speed);
		$DebugOutput[] = '$this->config_output_allow_enlarging        = '.$this->phpThumbDebugVarDump($this->config_output_allow_enlarging);
		$DebugOutput[] = '';

		foreach ($OtherVariableNames as $varname) {
			$value = $this->$varname;
			$DebugOutput[] = '$this->'.str_pad($varname, 27, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value);
		}
		$DebugOutput[] = 'strlen($this->rawImageData)        = '.strlen(@$this->rawImageData);
		$DebugOutput[] = 'strlen($this->exif_thumbnail_data) = '.strlen(@$this->exif_thumbnail_data);
		$DebugOutput[] = '';

		foreach ($ParameterNames as $varname) {
			$value = $this->$varname;
			$DebugOutput[] = '$this->'.str_pad($varname, 4, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value);
		}
		$DebugOutput[] = '';

		foreach ($FunctionsExistance as $functionname) {
			$DebugOutput[] = 'builtin_function_exists('.$functionname.')'.str_repeat(' ', 23 - strlen($functionname)).' = '.$this->phpThumbDebugVarDump(phpthumb_functions::builtin_function_exists($functionname));
		}
		$DebugOutput[] = '';

		$gd_info = $this->gd_info();
		foreach ($gd_info as $key => $value) {
			$DebugOutput[] = 'gd_info.'.str_pad($key, 34, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value);
		}
		$DebugOutput[] = '';

		$exif_info = phpthumb_functions::exif_info();
		foreach ($exif_info as $key => $value) {
			$DebugOutput[] = 'exif_info.'.str_pad($key, 26, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value);
		}
		$DebugOutput[] = '';

		if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray(dirname(@$_SERVER['PHP_SELF']))) {
			foreach ($ApacheLookupURIarray as $key => $value) {
				$DebugOutput[] = 'ApacheLookupURIarray.'.str_pad($key, 15, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value);
			}
		} else {
				$DebugOutput[] = 'ApacheLookupURIarray() -- FAILED';
		}
		$DebugOutput[] = '';

		if (isset($_GET) && is_array($_GET)) {
			foreach ($_GET as $key => $value) {
				$DebugOutput[] = '$_GET['.$key.']'.str_repeat(' ', 30 - strlen($key)).'= '.$this->phpThumbDebugVarDump($value);
			}
		}
		if (isset($_POST) && is_array($_POST)) {
			foreach ($_POST as $key => $value) {
				$DebugOutput[] = '$_POST['.$key.']'.str_repeat(' ', 29 - strlen($key)).'= '.$this->phpThumbDebugVarDump($value);
			}
		}
		$DebugOutput[] = '';

		$DebugOutput[] = '$this->debugmessages:';
		foreach ($this->debugmessages as $errorstring) {
			$DebugOutput[] = '  * '.$errorstring;
		}

		return $this->ErrorImage(implode("\n", $DebugOutput), 700, 500);
	}

	function ErrorImage($text, $width=400, $height=100) {
		if ($this->RemoveFileOnCompletion) {
			@unlink($this->sourceFilename);
		}

		$this->DebugMessage($text);
		if (!$this->config_error_die_on_error) {
			return false;
		}
		if ($this->config_error_silent_die_on_error) {
			exit;
		}
		if (!empty($this->err) || !empty($this->config_error_message_image_default)) {
			// Show generic custom error image instead of error message
			// for use on production sites where you don't want debug messages
			if (@$this->err == 'showerror') {
				// fall through and actually show error message even if default error image is set
			} else {
				header('Location: '.(!empty($this->err) ? $this->err : $this->config_error_message_image_default));
				exit;
			}
		}
		if (@$this->f == 'text') {
			// bypass all GD functions and output text error message
			die('<PRE>'.$text.'</PRE>');
		}

		$FontWidth  = ImageFontWidth($this->config_error_fontsize);
		$FontHeight = ImageFontHeight($this->config_error_fontsize);

		$LinesOfText = explode("\n", wordwrap($text, floor($width / $FontWidth), "\n", true));
		$height = max($height, count($LinesOfText) * $FontHeight);

		if (headers_sent()) {

			echo "\n".'**Headers already sent, dumping error message as text:**<br>'."\n\n".$text;

		} elseif ($gdimg_error = @ImageCreate($width, $height)) {

			$background_color = phpthumb_functions::ImageHexColorAllocate($gdimg_error, $this->config_error_bgcolor,   true);
			$text_color       = phpthumb_functions::ImageHexColorAllocate($gdimg_error, $this->config_error_textcolor, true);
			ImageFilledRectangle($gdimg_error, 0, 0, $width, $height, $background_color);
			$lineYoffset = 0;
			foreach ($LinesOfText as $line) {
				ImageString($gdimg_error, $this->config_error_fontsize, 2, $lineYoffset, $line, $text_color);
				$lineYoffset += $FontHeight;
			}
			if (function_exists('ImageTypes')) {
				$imagetypes = ImageTypes();
				if ($imagetypes & IMG_PNG) {
					header('Content-type: image/png');
					ImagePNG($gdimg_error);
				} elseif ($imagetypes & IMG_GIF) {
					header('Content-type: image/gif');
					ImageGIF($gdimg_error);
				} elseif ($imagetypes & IMG_JPG) {
					header('Content-type: image/jpeg');
					ImageJPEG($gdimg_error);
				} elseif ($imagetypes & IMG_WBMP) {
					header('Content-type: image/wbmp');
					ImageWBMP($gdimg_error);
				}
			}
			ImageDestroy($gdimg_error);

		}
		if (!headers_sent()) {
			echo "\n".'**Failed to send graphical error image, dumping error message as text:**<br>'."\n\n".$text;
		}
		exit;
		return true;
	}

	function ImageCreateFromStringReplacement(&$RawImageData, $DieOnErrors=false) {
		// there are serious bugs in the non-bundled versions of GD which may cause
		// PHP to segfault when calling ImageCreateFromString() - avoid if at all possible
		// when not using a bundled version of GD2
		$gd_info = $this->gd_info();
		if (strpos($gd_info['GD Version'], 'bundled') !== false) {
			return @ImageCreateFromString($RawImageData);
		}

		switch (substr($RawImageData, 0, 3)) {
			case 'GIF':
				$ICFSreplacementFunctionName = 'ImageCreateFromGIF';
				break;
			case "\xFF\xD8\xFF":
				$ICFSreplacementFunctionName = 'ImageCreateFromJPEG';
				break;
			case "\x89".'PN':
				$ICFSreplacementFunctionName = 'ImageCreateFromPNG';
				break;
			default:
				//if ($DieOnErrors) {
				//	return $this->ErrorImage('Unknown image type identified by "'.substr($RawImageData, 0, 3).'" ('.phpthumb_functions::HexCharDisplay(substr($this->rawImageData, 0, 3)).') in ImageCreateFromStringReplacement()');
				//}
				return false;
				break;
		}
		if ($tempnam = $this->phpThumb_tempnam()) {
			if ($fp_tempnam = @fopen($tempnam, 'wb')) {
				fwrite($fp_tempnam, $RawImageData);
				fclose($fp_tempnam);
				if (($ICFSreplacementFunctionName == 'ImageCreateFromGIF') && !function_exists($ICFSreplacementFunctionName)) {

					// Need to create from GIF file, but ImageCreateFromGIF does not exist
					if (@include_once('./functions/phpthumb/phpthumb.gif.php')) {
						// gif_loadFileToGDimageResource() cannot read from raw data, write to file first
						if ($tempfilename = $this->phpThumb_tempnam()) {
							if ($fp_tempfile = @fopen($tempfilename, 'wb')) {
								fwrite($fp_tempfile, $RawImageData);
								fclose($fp_tempfile);
								$gdimg_source = gif_loadFileToGDimageResource($tempfilename);
								unlink($tempfilename);
								return $gdimg_source;
								break;
							} else {
								$ErrorMessage = 'Failed to open tempfile in '.__FILE__.' on line '.__LINE__;
							}
						} else {
							$ErrorMessage = 'Failed to open generate tempfile name in '.__FILE__.' on line '.__LINE__;
						}
					} else {
						$ErrorMessage = 'Failed to include required file "./functions/phpthumb/phpthumb.gif.php" in '.__FILE__.' on line '.__LINE__;
					}

				} elseif (function_exists($ICFSreplacementFunctionName) && ($gdimg_source = $ICFSreplacementFunctionName($tempnam))) {

					// great
					unlink($tempnam);
					return $gdimg_source;

				} else { // GD functions not available

					//jpell changed
					// base64-encoded error image in GIF format
					//$ERROR_NOGD = 'R0lGODlhIAAgALMAAAAAABQUFCQkJDY2NkZGRldXV2ZmZnJycoaGhpSUlKWlpbe3t8XFxdXV1eTk5P7+/iwAAAAAIAAgAAAE/vDJSau9WILtTAACUinDNijZtAHfCojS4W5H+qxD8xibIDE9h0OwWaRWDIljJSkUJYsN4bihMB8th3IToAKs1VtYM75cyV8sZ8vygtOE5yMKmGbO4jRdICQCjHdlZzwzNW4qZSQmKDaNjhUMBX4BBAlmMywFSRWEmAI6b5gAlhNxokGhooAIK5o/pi9vEw4Lfj4OLTAUpj6IabMtCwlSFw0DCKBoFqwAB04AjI54PyZ+yY3TD0ss2YcVmN/gvpcu4TOyFivWqYJlbAHPpOntvxNAACcmGHjZzAZqzSzcq5fNjxFmAFw9iFRunD1epU6tsIPmFCAJnWYE0FURk7wJDA0MTKpEzoWAAskiAAA7';
					//header('Content-type: image/gif');
					//echo base64_decode($ERROR_NOGD);
					//exit;
					return false;
					//end jpell changed.
				}
			} else {
				$ErrorMessage = 'Failed to fopen('.$tempnam.', "wb") in '.__FILE__.' on line '.__LINE__."\n".'You may need to set $PHPTHUMB_CONFIG[temp_directory] in phpThumb.config.php';
			}
			unlink($tempnam);
		} else {
			$ErrorMessage = 'Failed to generate phpThumb_tempnam() in '.__FILE__.' on line '.__LINE__."\n".'You may need to set $PHPTHUMB_CONFIG[temp_directory] in phpThumb.config.php';
		}
		if ($DieOnErrors && !empty($ErrorMessage)) {
			return $this->ErrorImage($ErrorMessage);
		}
		return false;
	}

	function phpThumb_tempnam() {
		return tempnam($this->config_temp_directory, 'pThumb');
	}

	function gd_version($fullstring=false) {
		static $cache_gd_version = array();
		if (empty($cache_gd_version)) {
			$gd_info = $this->gd_info();
			if (substr($gd_info['GD Version'], 0, strlen('bundled (')) == 'bundled (') {
				$cache_gd_version[1] = $gd_info['GD Version'];                                         // e.g. "bundled (2.0.15 compatible)"
				$cache_gd_version[0] = (float) substr($gd_info['GD Version'], strlen('bundled ('), 3); // e.g. "2.0" (not "bundled (2.0.15 compatible)")
			} else {
				$cache_gd_version[1] = $gd_info['GD Version'];                       // e.g. "1.6.2 or higher"
				$cache_gd_version[0] = (float) substr($gd_info['GD Version'], 0, 3); // e.g. "1.6" (not "1.6.2 or higher")
			}
		}
		return $cache_gd_version[intval($fullstring)];
	}

	function gd_info() {
		if (function_exists('gd_info')) {
			// built into PHP v4.3.0+ (with bundled GD2 library)
			return gd_info();
		}

		static $gd_info = array();
		if (empty($gd_info)) {
			// based on code by johnschaefer at gmx dot de
			// from PHP help on gd_info()
			$gd_info = array(
				'GD Version'         => '',
				'FreeType Support'   => false,
				'FreeType Linkage'   => '',
				'T1Lib Support'      => false,
				'GIF Read Support'   => false,
				'GIF Create Support' => false,
				'JPG Support'        => false,
				'PNG Support'        => false,
				'WBMP Support'       => false,
				'XBM Support'        => false
			);
			$phpinfo_array = phpthumb_functions::phpinfo_array();
			foreach ($phpinfo_array as $line) {
				$line = trim(strip_tags($line));
				foreach ($gd_info as $key => $value) {
					//if (strpos($line, $key) !== false) {
					if (strpos($line, $key) === 0) {
						$newvalue = trim(str_replace($key, '', $line));
						$gd_info[$key] = $newvalue;
					}
				}
			}
			if (empty($gd_info['GD Version'])) {
				// probable cause: "phpinfo() disabled for security reasons"
				if (function_exists('ImageTypes')) {
					$imagetypes = ImageTypes();
					if ($imagetypes & IMG_PNG) {
						$gd_info['PNG Support'] = true;
					}
					if ($imagetypes & IMG_GIF) {
						$gd_info['GIF Create Support'] = true;
					}
					if ($imagetypes & IMG_JPG) {
						$gd_info['JPG Support'] = true;
					}
					if ($imagetypes & IMG_WBMP) {
						$gd_info['WBMP Support'] = true;
					}
				}
				// to determine capability of GIF creation, try to use ImageCreateFromGIF on a 1px GIF
				if (function_exists('ImageCreateFromGIF')) {
					if ($tempfilename = $this->phpThumb_tempnam()) {
						if ($fp_tempfile = @fopen($tempfilename, 'wb')) {
							fwrite($fp_tempfile, base64_decode('R0lGODlhAQABAIAAAH//AP///ywAAAAAAQABAAACAUQAOw==')); // very simple 1px GIF file base64-encoded as string
							fclose($fp_tempfile);

							// if we can convert the GIF file to a GD image then GIF create support must be enabled, otherwise it's not
							$gd_info['GIF Read Support'] = (bool) @ImageCreateFromGIF($tempfilename);
						}
						unlink($tempfilename);
					}
				}
				if (function_exists('ImageCreateTrueColor') && @ImageCreateTrueColor(1, 1)) {
					$gd_info['GD Version'] = '2.0.1 or higher (assumed)';
				} elseif (function_exists('ImageCreate') && @ImageCreate(1, 1)) {
					$gd_info['GD Version'] = '1.6.0 or higher (assumed)';
				}
			}
		}
		return $gd_info;
	}

	function DebugMessage($message, $file='', $line='') {
		$this->debugmessages[] = $message.($file ? ' in file "'.(basename($file) ? basename($file) : $file).'"' : '').($line ? ' on line '.$line : '');
		return true;
	}

}

?>