You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							616 lines
						
					
					
						
							14 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							616 lines
						
					
					
						
							14 KiB
						
					
					
				| <?php | |
| 
 | |
| /* | |
|  | |
| 	Copyright (c) 2009-2019 F3::Factory/Bong Cosca, All rights reserved. | |
|  | |
| 	This file is part of the Fat-Free Framework (http://fatfreeframework.com). | |
|  | |
| 	This is free software: you can redistribute it and/or modify it under the | |
| 	terms of the GNU General Public License as published by the Free Software | |
| 	Foundation, either version 3 of the License, or later. | |
|  | |
| 	Fat-Free Framework is distributed in the hope that it will be useful, | |
| 	but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | |
| 	General Public License for more details. | |
|  | |
| 	You should have received a copy of the GNU General Public License along | |
| 	with Fat-Free Framework.  If not, see <http://www.gnu.org/licenses/>. | |
|  | |
| */ | |
| 
 | |
| //! Image manipulation tools | |
| class Image { | |
| 
 | |
| 	//@{ Messages | |
| 	const | |
| 		E_Color='Invalid color specified: %s', | |
| 		E_File='File not found', | |
| 		E_Font='CAPTCHA font not found', | |
| 		E_TTF='No TrueType support in GD module', | |
| 		E_Length='Invalid CAPTCHA length: %s'; | |
| 	//@} | |
|  | |
| 	//@{ Positional cues | |
| 	const | |
| 		POS_Left=1, | |
| 		POS_Center=2, | |
| 		POS_Right=4, | |
| 		POS_Top=8, | |
| 		POS_Middle=16, | |
| 		POS_Bottom=32; | |
| 	//@} | |
|  | |
| 	protected | |
| 		//! Source filename | |
| 		$file, | |
| 		//! Image resource | |
| 		$data, | |
| 		//! Enable/disable history | |
| 		$flag=FALSE, | |
| 		//! Filter count | |
| 		$count=0; | |
| 
 | |
| 	/** | |
| 	*	Convert RGB hex triad to array | |
| 	*	@return array|FALSE | |
| 	*	@param $color int|string | |
| 	**/ | |
| 	function rgb($color) { | |
| 		if (is_string($color)) | |
| 			$color=hexdec($color); | |
| 		$hex=str_pad($hex=dechex($color),$color<4096?3:6,'0',STR_PAD_LEFT); | |
| 		if (($len=strlen($hex))>6) | |
| 			user_error(sprintf(self::E_Color,'0x'.$hex),E_USER_ERROR); | |
| 		$color=str_split($hex,$len/3); | |
| 		foreach ($color as &$hue) { | |
| 			$hue=hexdec(str_repeat($hue,6/$len)); | |
| 			unset($hue); | |
| 		} | |
| 		return $color; | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Invert image | |
| 	*	@return object | |
| 	**/ | |
| 	function invert() { | |
| 		imagefilter($this->data,IMG_FILTER_NEGATE); | |
| 		return $this->save(); | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Adjust brightness (range:-255 to 255) | |
| 	*	@return object | |
| 	*	@param $level int | |
| 	**/ | |
| 	function brightness($level) { | |
| 		imagefilter($this->data,IMG_FILTER_BRIGHTNESS,$level); | |
| 		return $this->save(); | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Adjust contrast (range:-100 to 100) | |
| 	*	@return object | |
| 	*	@param $level int | |
| 	**/ | |
| 	function contrast($level) { | |
| 		imagefilter($this->data,IMG_FILTER_CONTRAST,$level); | |
| 		return $this->save(); | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Convert to grayscale | |
| 	*	@return object | |
| 	**/ | |
| 	function grayscale() { | |
| 		imagefilter($this->data,IMG_FILTER_GRAYSCALE); | |
| 		return $this->save(); | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Adjust smoothness | |
| 	*	@return object | |
| 	*	@param $level int | |
| 	**/ | |
| 	function smooth($level) { | |
| 		imagefilter($this->data,IMG_FILTER_SMOOTH,$level); | |
| 		return $this->save(); | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Emboss the image | |
| 	*	@return object | |
| 	**/ | |
| 	function emboss() { | |
| 		imagefilter($this->data,IMG_FILTER_EMBOSS); | |
| 		return $this->save(); | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Apply sepia effect | |
| 	*	@return object | |
| 	**/ | |
| 	function sepia() { | |
| 		imagefilter($this->data,IMG_FILTER_GRAYSCALE); | |
| 		imagefilter($this->data,IMG_FILTER_COLORIZE,90,60,45); | |
| 		return $this->save(); | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Pixelate the image | |
| 	*	@return object | |
| 	*	@param $size int | |
| 	**/ | |
| 	function pixelate($size) { | |
| 		imagefilter($this->data,IMG_FILTER_PIXELATE,$size,TRUE); | |
| 		return $this->save(); | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Blur the image using Gaussian filter | |
| 	*	@return object | |
| 	*	@param $selective bool | |
| 	**/ | |
| 	function blur($selective=FALSE) { | |
| 		imagefilter($this->data, | |
| 			$selective?IMG_FILTER_SELECTIVE_BLUR:IMG_FILTER_GAUSSIAN_BLUR); | |
| 		return $this->save(); | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Apply sketch effect | |
| 	*	@return object | |
| 	**/ | |
| 	function sketch() { | |
| 		imagefilter($this->data,IMG_FILTER_MEAN_REMOVAL); | |
| 		return $this->save(); | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Flip on horizontal axis | |
| 	*	@return object | |
| 	**/ | |
| 	function hflip() { | |
| 		$tmp=imagecreatetruecolor( | |
| 			$width=$this->width(),$height=$this->height()); | |
| 		imagesavealpha($tmp,TRUE); | |
| 		imagefill($tmp,0,0,IMG_COLOR_TRANSPARENT); | |
| 		imagecopyresampled($tmp,$this->data, | |
| 			0,0,$width-1,0,$width,$height,-$width,$height); | |
| 		imagedestroy($this->data); | |
| 		$this->data=$tmp; | |
| 		return $this->save(); | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Flip on vertical axis | |
| 	*	@return object | |
| 	**/ | |
| 	function vflip() { | |
| 		$tmp=imagecreatetruecolor( | |
| 			$width=$this->width(),$height=$this->height()); | |
| 		imagesavealpha($tmp,TRUE); | |
| 		imagefill($tmp,0,0,IMG_COLOR_TRANSPARENT); | |
| 		imagecopyresampled($tmp,$this->data, | |
| 			0,0,0,$height-1,$width,$height,$width,-$height); | |
| 		imagedestroy($this->data); | |
| 		$this->data=$tmp; | |
| 		return $this->save(); | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Crop the image | |
| 	*	@return object | |
| 	*	@param $x1 int | |
| 	*	@param $y1 int | |
| 	*	@param $x2 int | |
| 	*	@param $y2 int | |
| 	**/ | |
| 	function crop($x1,$y1,$x2,$y2) { | |
| 		$tmp=imagecreatetruecolor($width=$x2-$x1+1,$height=$y2-$y1+1); | |
| 		imagesavealpha($tmp,TRUE); | |
| 		imagefill($tmp,0,0,IMG_COLOR_TRANSPARENT); | |
| 		imagecopyresampled($tmp,$this->data, | |
| 			0,0,$x1,$y1,$width,$height,$width,$height); | |
| 		imagedestroy($this->data); | |
| 		$this->data=$tmp; | |
| 		return $this->save(); | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Resize image (Maintain aspect ratio); Crop relative to center | |
| 	*	if flag is enabled; Enlargement allowed if flag is enabled | |
| 	*	@return object | |
| 	*	@param $width int | |
| 	*	@param $height int | |
| 	*	@param $crop bool | |
| 	*	@param $enlarge bool | |
| 	**/ | |
| 	function resize($width=NULL,$height=NULL,$crop=TRUE,$enlarge=TRUE) { | |
| 		if (is_null($width) && is_null($height)) | |
| 			return $this; | |
| 		$origw=$this->width(); | |
| 		$origh=$this->height(); | |
| 		if (is_null($width)) | |
| 			$width=round(($height/$origh)*$origw); | |
| 		if (is_null($height)) | |
| 			$height=round(($width/$origw)*$origh); | |
| 		// Adjust dimensions; retain aspect ratio | |
| 		$ratio=$origw/$origh; | |
| 		if (!$crop) { | |
| 			if ($width/$ratio<=$height) | |
| 				$height=round($width/$ratio); | |
| 			else | |
| 				$width=round($height*$ratio); | |
| 		} | |
| 		if (!$enlarge) { | |
| 			$width=min($origw,$width); | |
| 			$height=min($origh,$height); | |
| 		} | |
| 		// Create blank image | |
| 		$tmp=imagecreatetruecolor($width,$height); | |
| 		imagesavealpha($tmp,TRUE); | |
| 		imagefill($tmp,0,0,IMG_COLOR_TRANSPARENT); | |
| 		// Resize | |
| 		if ($crop) { | |
| 			if ($width/$ratio<=$height) { | |
| 				$cropw=round($origh*$width/$height); | |
| 				imagecopyresampled($tmp,$this->data, | |
| 					0,0,($origw-$cropw)/2,0,$width,$height,$cropw,$origh); | |
| 			} | |
| 			else { | |
| 				$croph=round($origw*$height/$width); | |
| 				imagecopyresampled($tmp,$this->data, | |
| 					0,0,0,($origh-$croph)/2,$width,$height,$origw,$croph); | |
| 			} | |
| 		} | |
| 		else | |
| 			imagecopyresampled($tmp,$this->data, | |
| 				0,0,0,0,$width,$height,$origw,$origh); | |
| 		imagedestroy($this->data); | |
| 		$this->data=$tmp; | |
| 		return $this->save(); | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Rotate image | |
| 	*	@return object | |
| 	*	@param $angle int | |
| 	**/ | |
| 	function rotate($angle) { | |
| 		$this->data=imagerotate($this->data,$angle, | |
| 			imagecolorallocatealpha($this->data,0,0,0,127)); | |
| 		imagesavealpha($this->data,TRUE); | |
| 		return $this->save(); | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Apply an image overlay | |
| 	*	@return object | |
| 	*	@param $img object | |
| 	*	@param $align int|array | |
| 	*	@param $alpha int | |
| 	**/ | |
| 	function overlay(Image $img,$align=NULL,$alpha=100) { | |
| 		if (is_null($align)) | |
| 			$align=self::POS_Right|self::POS_Bottom; | |
| 		if (is_array($align)) { | |
| 			list($posx,$posy)=$align; | |
| 			$align = 0; | |
| 		} | |
| 		$ovr=imagecreatefromstring($img->dump()); | |
| 		imagesavealpha($ovr,TRUE); | |
| 		$imgw=$this->width(); | |
| 		$imgh=$this->height(); | |
| 		$ovrw=imagesx($ovr); | |
| 		$ovrh=imagesy($ovr); | |
| 		if ($align & self::POS_Left) | |
| 			$posx=0; | |
| 		if ($align & self::POS_Center) | |
| 			$posx=($imgw-$ovrw)/2; | |
| 		if ($align & self::POS_Right) | |
| 			$posx=$imgw-$ovrw; | |
| 		if ($align & self::POS_Top) | |
| 			$posy=0; | |
| 		if ($align & self::POS_Middle) | |
| 			$posy=($imgh-$ovrh)/2; | |
| 		if ($align & self::POS_Bottom) | |
| 			$posy=$imgh-$ovrh; | |
| 		if (empty($posx)) | |
| 			$posx=0; | |
| 		if (empty($posy)) | |
| 			$posy=0; | |
| 		if ($alpha==100) | |
| 			imagecopy($this->data,$ovr,$posx,$posy,0,0,$ovrw,$ovrh); | |
| 		else { | |
| 			$cut=imagecreatetruecolor($ovrw,$ovrh); | |
| 			imagecopy($cut,$this->data,0,0,$posx,$posy,$ovrw,$ovrh); | |
| 			imagecopy($cut,$ovr,0,0,0,0,$ovrw,$ovrh); | |
| 			imagecopymerge($this->data, | |
| 				$cut,$posx,$posy,0,0,$ovrw,$ovrh,$alpha); | |
| 		} | |
| 		return $this->save(); | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Generate identicon | |
| 	*	@return object | |
| 	*	@param $str string | |
| 	*	@param $size int | |
| 	*	@param $blocks int | |
| 	**/ | |
| 	function identicon($str,$size=64,$blocks=4) { | |
| 		$sprites=[ | |
| 			[.5,1,1,0,1,1], | |
| 			[.5,0,1,0,.5,1,0,1], | |
| 			[.5,0,1,0,1,1,.5,1,1,.5], | |
| 			[0,.5,.5,0,1,.5,.5,1,.5,.5], | |
| 			[0,.5,1,0,1,1,0,1,1,.5], | |
| 			[1,0,1,1,.5,1,1,.5,.5,.5], | |
| 			[0,0,1,0,1,.5,0,0,.5,1,0,1], | |
| 			[0,0,.5,0,1,.5,.5,1,0,1,.5,.5], | |
| 			[.5,0,.5,.5,1,.5,1,1,.5,1,.5,.5,0,.5], | |
| 			[0,0,1,0,.5,.5,1,.5,.5,1,.5,.5,0,1], | |
| 			[0,.5,.5,1,1,.5,.5,0,1,0,1,1,0,1], | |
| 			[.5,0,1,0,1,1,.5,1,1,.75,.5,.5,1,.25], | |
| 			[0,.5,.5,0,.5,.5,1,0,1,.5,.5,1,.5,.5,0,1], | |
| 			[0,0,1,0,1,1,0,1,1,.5,.5,.25,.5,.75,0,.5,.5,.25], | |
| 			[0,.5,.5,.5,.5,0,1,0,.5,.5,1,.5,.5,1,.5,.5,0,1], | |
| 			[0,0,1,0,.5,.5,.5,0,0,.5,1,.5,.5,1,.5,.5,0,1] | |
| 		]; | |
| 		$hash=sha1($str); | |
| 		$this->data=imagecreatetruecolor($size,$size); | |
| 		list($r,$g,$b)=$this->rgb(hexdec(substr($hash,-3))); | |
| 		$fg=imagecolorallocate($this->data,$r,$g,$b); | |
| 		imagefill($this->data,0,0,IMG_COLOR_TRANSPARENT); | |
| 		$ctr=count($sprites); | |
| 		$dim=$blocks*floor($size/$blocks)*2/$blocks; | |
| 		for ($j=0,$y=ceil($blocks/2);$j<$y;$j++) | |
| 			for ($i=$j,$x=$blocks-1-$j;$i<$x;$i++) { | |
| 				$sprite=imagecreatetruecolor($dim,$dim); | |
| 				imagefill($sprite,0,0,IMG_COLOR_TRANSPARENT); | |
| 				$block=$sprites[hexdec($hash[($j*$blocks+$i)*2])%$ctr]; | |
| 				for ($k=0,$pts=count($block);$k<$pts;$k++) | |
| 					$block[$k]*=$dim; | |
| 				imagefilledpolygon($sprite,$block,$pts/2,$fg); | |
| 				for ($k=0;$k<4;$k++) { | |
| 					imagecopyresampled($this->data,$sprite, | |
| 						$i*$dim/2,$j*$dim/2,0,0,$dim/2,$dim/2,$dim,$dim); | |
| 					$this->data=imagerotate($this->data,90, | |
| 						imagecolorallocatealpha($this->data,0,0,0,127)); | |
| 				} | |
| 				imagedestroy($sprite); | |
| 			} | |
| 		imagesavealpha($this->data,TRUE); | |
| 		return $this->save(); | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Generate CAPTCHA image | |
| 	*	@return object|FALSE | |
| 	*	@param $font string | |
| 	*	@param $size int | |
| 	*	@param $len int | |
| 	*	@param $key string | |
| 	*	@param $path string | |
| 	*	@param $fg int | |
| 	*	@param $bg int | |
| 	**/ | |
| 	function captcha($font,$size=24,$len=5, | |
| 		$key=NULL,$path='',$fg=0xFFFFFF,$bg=0x000000) { | |
| 		if ((!$ssl=extension_loaded('openssl')) && ($len<4 || $len>13)) { | |
| 			user_error(sprintf(self::E_Length,$len),E_USER_ERROR); | |
| 			return FALSE; | |
| 		} | |
| 		if (!function_exists('imagettftext')) { | |
| 			user_error(self::E_TTF,E_USER_ERROR); | |
| 			return FALSE; | |
| 		} | |
| 		$fw=Base::instance(); | |
| 		foreach ($fw->split($path?:$fw->UI.';./') as $dir) | |
| 			if (is_file($path=$dir.$font)) { | |
| 				$seed=strtoupper(substr( | |
| 					$ssl?bin2hex(openssl_random_pseudo_bytes($len)):uniqid(), | |
| 					-$len)); | |
| 				$block=$size*3; | |
| 				$tmp=[]; | |
| 				for ($i=0,$width=0,$height=0;$i<$len;$i++) { | |
| 					// Process at 2x magnification | |
| 					$box=imagettfbbox($size*2,0,$path,$seed[$i]); | |
| 					$w=$box[2]-$box[0]; | |
| 					$h=$box[1]-$box[5]; | |
| 					$char=imagecreatetruecolor($block,$block); | |
| 					imagefill($char,0,0,$bg); | |
| 					imagettftext($char,$size*2,0, | |
| 						($block-$w)/2,$block-($block-$h)/2, | |
| 						$fg,$path,$seed[$i]); | |
| 					$char=imagerotate($char,mt_rand(-30,30), | |
| 						imagecolorallocatealpha($char,0,0,0,127)); | |
| 					// Reduce to normal size | |
| 					$tmp[$i]=imagecreatetruecolor( | |
| 						($w=imagesx($char))/2,($h=imagesy($char))/2); | |
| 					imagefill($tmp[$i],0,0,IMG_COLOR_TRANSPARENT); | |
| 					imagecopyresampled($tmp[$i], | |
| 						$char,0,0,0,0,$w/2,$h/2,$w,$h); | |
| 					imagedestroy($char); | |
| 					$width+=$i+1<$len?$block/2:$w/2; | |
| 					$height=max($height,$h/2); | |
| 				} | |
| 				$this->data=imagecreatetruecolor($width,$height); | |
| 				imagefill($this->data,0,0,IMG_COLOR_TRANSPARENT); | |
| 				for ($i=0;$i<$len;$i++) { | |
| 					imagecopy($this->data,$tmp[$i], | |
| 						$i*$block/2,($height-imagesy($tmp[$i]))/2,0,0, | |
| 						imagesx($tmp[$i]),imagesy($tmp[$i])); | |
| 					imagedestroy($tmp[$i]); | |
| 				} | |
| 				imagesavealpha($this->data,TRUE); | |
| 				if ($key) | |
| 					$fw->$key=$seed; | |
| 				return $this->save(); | |
| 			} | |
| 		user_error(self::E_Font,E_USER_ERROR); | |
| 		return FALSE; | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Return image width | |
| 	*	@return int | |
| 	**/ | |
| 	function width() { | |
| 		return imagesx($this->data); | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Return image height | |
| 	*	@return int | |
| 	**/ | |
| 	function height() { | |
| 		return imagesy($this->data); | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Send image to HTTP client | |
| 	*	@return NULL | |
| 	**/ | |
| 	function render() { | |
| 		$args=func_get_args(); | |
| 		$format=$args?array_shift($args):'png'; | |
| 		if (PHP_SAPI!='cli') { | |
| 			header('Content-Type: image/'.$format); | |
| 			header('X-Powered-By: '.Base::instance()->PACKAGE); | |
| 		} | |
| 		call_user_func_array( | |
| 			'image'.$format, | |
| 			array_merge([$this->data,NULL],$args) | |
| 		); | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Return image as a string | |
| 	*	@return string | |
| 	**/ | |
| 	function dump() { | |
| 		$args=func_get_args(); | |
| 		$format=$args?array_shift($args):'png'; | |
| 		ob_start(); | |
| 		call_user_func_array( | |
| 			'image'.$format, | |
| 			array_merge([$this->data,NULL],$args) | |
| 		); | |
| 		return ob_get_clean(); | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Return image resource | |
| 	*	@return resource | |
| 	**/ | |
| 	function data() { | |
| 		return $this->data; | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Save current state | |
| 	*	@return object | |
| 	**/ | |
| 	function save() { | |
| 		$fw=Base::instance(); | |
| 		if ($this->flag) { | |
| 			if (!is_dir($dir=$fw->TEMP)) | |
| 				mkdir($dir,Base::MODE,TRUE); | |
| 			$this->count++; | |
| 			$fw->write($dir.'/'.$fw->SEED.'.'. | |
| 				$fw->hash($this->file).'-'.$this->count.'.png', | |
| 				$this->dump()); | |
| 		} | |
| 		return $this; | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Revert to specified state | |
| 	*	@return object | |
| 	*	@param $state int | |
| 	**/ | |
| 	function restore($state=1) { | |
| 		$fw=Base::instance(); | |
| 		if ($this->flag && is_file($file=($path=$fw->TEMP. | |
| 			$fw->SEED.'.'.$fw->hash($this->file).'-').$state.'.png')) { | |
| 			if (is_resource($this->data)) | |
| 				imagedestroy($this->data); | |
| 			$this->data=imagecreatefromstring($fw->read($file)); | |
| 			imagesavealpha($this->data,TRUE); | |
| 			foreach (glob($path.'*.png',GLOB_NOSORT) as $match) | |
| 				if (preg_match('/-(\d+)\.png/',$match,$parts) && | |
| 					$parts[1]>$state) | |
| 					@unlink($match); | |
| 			$this->count=$state; | |
| 		} | |
| 		return $this; | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Undo most recently applied filter | |
| 	*	@return object | |
| 	**/ | |
| 	function undo() { | |
| 		if ($this->flag) { | |
| 			if ($this->count) | |
| 				$this->count--; | |
| 			return $this->restore($this->count); | |
| 		} | |
| 		return $this; | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Load string | |
| 	*	@return object|FALSE | |
| 	*	@param $str string | |
| 	**/ | |
| 	function load($str) { | |
| 		if (!$this->data=@imagecreatefromstring($str)) | |
| 			return FALSE; | |
| 		imagesavealpha($this->data,TRUE); | |
| 		$this->save(); | |
| 		return $this; | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Instantiate image | |
| 	*	@param $file string | |
| 	*	@param $flag bool | |
| 	*	@param $path string | |
| 	**/ | |
| 	function __construct($file=NULL,$flag=FALSE,$path=NULL) { | |
| 		$this->flag=$flag; | |
| 		if ($file) { | |
| 			$fw=Base::instance(); | |
| 			// Create image from file | |
| 			$this->file=$file; | |
| 			if (!isset($path)) | |
| 				$path=$fw->UI.';./'; | |
| 			foreach ($fw->split($path,FALSE) as $dir) | |
| 				if (is_file($dir.$file)) | |
| 					return $this->load($fw->read($dir.$file)); | |
| 			user_error(self::E_File,E_USER_ERROR); | |
| 		} | |
| 	} | |
| 
 | |
| 	/** | |
| 	*	Wrap-up | |
| 	*	@return NULL | |
| 	**/ | |
| 	function __destruct() { | |
| 		if (is_resource($this->data)) { | |
| 			imagedestroy($this->data); | |
| 			$fw=Base::instance(); | |
| 			$path=$fw->TEMP.$fw->SEED.'.'.$fw->hash($this->file); | |
| 			if ($glob=@glob($path.'*.png',GLOB_NOSORT)) | |
| 				foreach ($glob as $match) | |
| 					if (preg_match('/-(\d+)\.png/',$match)) | |
| 						@unlink($match); | |
| 		} | |
| 	} | |
| 
 | |
| }
 | |
| 
 |