<?php 
 /** 
  * Image  
  * 
  * 提供图片的一些常用处理程序 
  *$img = new images();
  *$img->loadFile("test.gif")->crop(0,0,100,100)->resize(50,50)->waterMark("mark.png", 'left','center')->save("b.gif");
  */ 
  
 class images { 
         var $img;   //图像标识符 
         var $info;  //保存图片的一些信息 
  
         function images($file=null) { 
             if(!extension_loaded('gd')) {
				 	$this->exceptionFunc("GD库没有加载.");
				 }
             if($file) $this->loadFile($file); 
         } 
         
		 function exceptionFunc($msg){
		 	
		 }
		 
         function __destruct() { 
			if(is_resource($this->img)) {
				imagedestroy($this->img);
			}
         }
		 
		 /*
		 //返回图片信息  
         function __call($method, $arg) { 
                 if(substr($method, 0, 3) == 'get') { 
                         $attr = strtolower(substr($method, 3)); 
                         if(isset($this->info[$attr])) 
                                 return $this->info[$attr]; 
                         return null; 
                 } 
         } 
		  */

         //返回图片资源 
         function getResource() { 
             if(isset($this->img)) 
                     return $this->img; 
             return null; 
         }
  		
		 // 获取图片信息
		 function getImgInfo($key=false){
			if ($key){
				return  isset($this->info[$key]) ? $this->info[$key] : null ;
			}else {
				return $this->info;
			}
		 }
		 
         /** 
          * 保存到文件 
          *  
          * @param string $path 文件的绝对路径  
          */ 
         function save($path) { 
             return $this->_output($path); 
         } 
  
         /** 
          * 将图片输出到浏览器 
          * 
          * @param $type 格式 
          */ 
         function output($type='gif') {                
             return $this->_output('stream', $type); 
         } 
  
         /** 
          * 初始化，创建图像标识符 
          * 
          * @param $file 源文件 
          */ 
         function loadFile($file) { 
			 if(!file_exists($file)) {
					 $this->exceptionFunc("指定的文件不存在 => $file"); 
			 }
			 $string = file_get_contents($file); 
			 $key = array('width', 'height', 'type'); 
			 $this->info = array_combine($key, array_slice(getimagesize($file), 0, 3)); 
			 $this->info['file'] = $file; 
			 $this->img = imagecreatefromstring($string); 
			 return $this; 
         } 
  
         /** 
          * 图片缩放 
          * 
          * @param int $width 目标宽度 
          * @param int $height 目标高度 
          * @param boolean $keepScale，是否等比缩放 
          * @return array $wh 包含缩放后宽度和高度的数组 $wh[0]为宽度，$wh[1]为高度 
          */ 
         function resize($width, $height, $keepScale=true) { 
			 $srcw   = $this->getWidth(); 
			 $srch   = $this->getHeight(); 
			 if($keepScale) {                        
					 //原始宽高比大于目标宽高比,调整高度 
					 if((double)($srcw/$srch) > (double)($width/$height)) 
					 { 
							 $height = ceil($srch * $width / $srcw); 
					 }else{ 
							 ///原始宽高比小于目标宽高比,调整宽度 
							 $width = ceil($srcw * $height / $srch); 
					 } 
			 } 

			 //创建一个透明背景的图像 
			 $newimg = $this->_createAlphaImage($width, $height); 
			 //将原始重新采样复制到透明背景上 
			 imagecopyresampled($newimg, $this->img, 0, 0, 0, 0, $width, $height, $srcw, $srch); 
			 imagedestroy($this->img); 
			 $this->img = $newimg; 
			 $this->info['width'] = $width; 
			 $this->info['height'] = $height; 
			 return $this; 
         } 
  
         /** 
          * 创建一个透明图片,用于图像复制 
          * 
          * @param int $width 宽度 
          * @param int $height 高度 
          */ 
         function _createAlphaImage($width, $height){ 
			 $newimg = imagecreatetruecolor($width, $height); 
			 if($this->getType() == 1){ //gif图片 
					 $colorCount = imagecolorstotal($this->img); 
					 imagetruecolortopalette($newimg, true, $colorCount); 
					 imagepalettecopy($newimg,$this->img); 
					 $transparentcolor = imagecolortransparent($this->img); 
					 imagefill($newimg,0,0,$transparentcolor); 
					 imagecolortransparent($newimg,$transparentcolor);  
			 }elseif($this->getType() == 3){ //png图片 
					 imagealphablending($newimg,false); 
					 $col=imagecolorallocatealpha($newimg,255,255,255,127); 
					 imagefilledrectangle($newimg,0,0,$width,$height,$col); 
					 imagealphablending($newimg,true); 
			 } 
			 return $newimg; 
         } 
  
         /** 
          * 生成缩略图 
          * 
          * @param int $width 宽度 
          * @param int $height 高度 
          * @param boolean $crop 是否对超出部分进行裁剪,默认为是, 如果不裁剪,则缩图将等比缩放至小于目标尺寸 
          * @param boolean $center crop时是否在中间裁剪 
          * @param string $path 要生成的新文件名 
          */ 
         function thumbnail($width=128,$height=128, $crop=true, $center=true, $path=null) { 
  
			 $destw  = min($this->getWidth(), $width); 
			 $desth  = min($this->getHeight(), $height); 
			 if($crop){ 
					 $srcw = $this->getWidth(); 
					 $srch = $this->getHeight();                      
					 $x = $y = 0; 
					 if((double)($srcw/$srch) > (double)($width/$height)) 
					 { 
							 //计算应COPY的宽度 
							 $srcw = ceil($width * $srch/ $height); 
							 //计算起始的x坐标 
							 if($center) $x = ceil(($this->getWidth() - $srcw) / 2); 
					 }else{ 
							 //计算应COPY的高度 
							 $srch = ceil($height * $srcw / $width); 
							 //计算起始的y坐标 
							 if($center) $y = ceil(($this->getHeight() - $srch) / 2); 
					 } 
					 //创建一个透明背景的图像 
					 $newimg = $this->_createAlphaImage($width, $height); 
					 //将原始重新采样复制到透明背景上 
					 imagecopyresampled($newimg, $this->img, 0, 0, $x, $y, $width, $height, $srcw, $srch); 
					 imagedestroy($this->img); 
					 $this->img = $newimg; 
					 $this->info['width'] = $width; 
					 $this->info['height'] = $height; 
			 }else{ 
					 $this->resize($destw, $desth); 
			 } 
			 if($path) return $this->save($path); 
			 return $this; 
         } 
  
         /** 
          * 图片裁剪 
          * 
          * @param int $x x坐标 
          * @param int $y y坐标 
          * @param int $w 裁剪宽度 
          * @param int $h 裁剪高度 
          * @return resource 返回裁剪后的图片资源 
          */ 
         function crop($x, $y, $w, $h){ 
			 $w = min($w, $this->getWidth()); 
			 $h = min($h, $this->getHeight()); 
			 $newimg = $this->_createAlphaImage($w, $h); 
			 imagecopy($newimg, $this->img, 0, 0, $x, $y, $w, $h); 
			 imagedestroy($this->img); 
			 $this->img = $newimg; 
			 $this->info['width'] = $w; 
			 $this->info['height'] = $h; 
			 return $this; 
         } 
  
         /** 
          * 对图片进行波纹处理 
          * 
          * @param int $grade 弯曲度数,越大图片变形越厉害 
          * @param string $dir h=水平, v=垂直 
          */ 
         function wave($grade=5, $dir="h"){ 
			 $w = $this->getWidth(); 
			 $h = $this->getHeight(); 
			 if($dir=="h"){ 
					 for($i=0;$i<$w;$i+=2){ 
							 imagecopyresampled($this->img,$this->img, $i-2, sin($i/10)*$grade,$i,0,2,$h,2,$h); 
					 } 
			 }else{ 
					 for($i=0;$i<$h;$i+=2){ 
							 imagecopyresampled($this->img,$this->img, sin($i/10)*$grade,$i-2,0,$i,$w,2,$w,2); 
					 } 
			 } 
			 return $this; 
         } 
  
         /** 
          * 给图片加带背景的一行文字 
          * 
          * @param string $text 水印文字 
          * @param string $font 字体文件的路径 
          * @param $color 文字的颜色 16进制，默认为黑色 
          * @param int $size     文字的大小 
          * @param string $path 如果指定则生成图片到$path 
          * @return 生成的水印图片路径 
          */ 
         function textMark($text, $font, $color="#000000", $size=9, $path=null) { 
			 if(!file_exists($font)) 
					 $this->exceptionFunc("字体文件不可用 => $font"); 

			 //取得图片的高度和宽度 
			 $mwidth = $this->getWidth(); 
			 $mheight= $this->getHeight(); 
			  
			 $color = $this->_hexColor($color); 
			 $color = imagecolorallocate($this->img, $color['r'], $color['g'], $color['b']); 
			 $black = imagecolorallocate($this->img, 0, 0, 0); 
			 $alpha = imagecolorallocatealpha($this->img, 230, 230, 230, 40); 
			 //填充文字背景 
			 $box = imagettfbbox($size, 0, $font, $text); 
			 //文字补白 
			 $padding    = 6; 
			 $textheight = $box[1] - $box[7]; 
			 $bgheight   = $textheight + $padding * 2; 
			 //文字背景 
			 imagefilledrectangle($this->img, 0, $mheight-$bgheight, $mwidth, $mheight, $alpha); 
			 //小竖条 
			 imagefilledrectangle($this->img, 10, $mheight-$padding-$textheight, 15, $mheight-$padding, $color); 
			 //填充文字 
			 $texty = $mheight - $bgheight/2 + $textheight/2; 
			 imagettftext($this->img, $size, 0, 20, $texty, $color, $font, $text); 
			 if($path) return $this->save($path); 
			 return $this; 
         } 
  
         /** 
          * 用一张PNG图片给原始图片加水印，水印图片将自动调整到目标图片大小 
          * 
          * @param string $png png图片的路径 
          * @param string $hp 水平位置 left|center|right 
          * @param string $vp 垂直位置 top|center|bottom 
          * @param int    $pct 水印的透明度 0-100, 0为完全透明,100为完全不透明,只适用于非PNG图片水印 
          * @param string $path 如果指定则生成图片到$path 
          * @param  
          * @return 
          */ 
         function waterMark($markImg, $hp='center', $vp='center', $pct=50, $path=null) { 
             //原图信息 
             $srcw = $this->getWidth(); 
             $srch = $this->getHeight(); 
  
             //水印图信息 
             $mark = new self($markImg); 
             $markw = $mark->getWidth(); 
             $markh = $mark->getHeight(); 
  
             //水印图片大于目标图片，调整大小 
             if($markw > $srcw || $markh > $srch) { 
                     //先将水印图片调整到原始图片大小-10个像素 
                     $mark->resize($srcw-10, $srch-10, true); 
                     $markw = $mark->getWidth(); 
                     $markh = $mark->getHeight(); 
             } 
          
             //判断水印位置 
             $arrx = array('left' => 0, 'center' => floor(($srcw - $markw) / 2), 'right' => $srcw - $markw); 
             $arry = array('top'  => 0, 'center' => floor(($srch - $markh) / 2), 'bottom' => $srch - $markh); 
             $x = isset($arrx[$hp]) ? $arrx[$hp] : $arrx['center']; 
             $y = isset($arry[$vp]) ? $arry[$vp] : $arry['center']; 
              
             //png图片水印 
             if($mark->getType() == 3){ 
                     //打开混色模式 
                     imagealphablending($this->img, true); 
                     imagecopy($this->img, $mark->getResource(), $x, $y, 0, 0, $markw, $markh); 
             }else{ 
                     imagecopymerge($this->img, $mark->getResource(), $x, $y, 0, 0, $markw, $markh, $pct); 
             } 
             unset($mark); 
             if($path) return $this->save($path); 
             return $this; 
         } 
  
         //返回由16进制组成的颜色索引 
         function _hexColor($hex) { 
             $color = hexdec(substr($hex, 1)); 
         return array( 
             "r"     => ($color & 0xFF0000) >> 16, 
             "g" => ($color & 0xFF00) >> 8, 
             "b" => $color & 0xFF 
             );       
         } 
  
  
         //png的alpha校正 
         function _pngalpha($format) { 
             //PNG图像要保持alpha通道 
             if($format == 'png') { 
                     imagealphablending($this->img, false); 
                     imagesavealpha($this->img, true); 
             } 
         } 
  
         //输出函数，内部使用 
         function _output($path, $type=null) {                
             $toFile = false; 
             //输出到文件 
             if($path !='stream') { 
                     if(!is_dir(dirname($path))) 
                             $this->exceptionFunc('指定的路径不可用 =>'.$path); 
                     $type = pathinfo($path, PATHINFO_EXTENSION); 
                     $toFile = true; 
             } 
             //png的alpha校正 
             $this->_pngalpha($type); 
  
             if($type == "jpg") $type = "jpeg"; 
             $func = "image".$type; 
             if(!function_exists($func)) { 
                     $type = 'gif'; 
                     $func = 'imagegif'; 
             } 
             if($toFile) {                        
                     call_user_func($func, $this->img, $path); 
             } 
             else 
             { 
                     if(!headers_sent()) 
                             header("Content-type:image/".$type); 
                     call_user_func($func, $this->img); 
             } 
             return $this; 
         } 

		function getWidth() {
			if (isset($this->info['width'])) {
				return $this->info['width'];
			}
			return false;
		}

		function getHeight() {
			if (isset($this->info['height'])) {
				return $this->info['height'];
			}
			return false;
		}

		function getType() {
			if (isset($this->info['type'])) {
				return $this->info['type'];
			}
			return false;
		}
 } 
 ?>
