<?php
/**
 * php图像处理 class - WhileDo.com
 * @author HzqGhost admin@whiledo.com QQ:313143468
 * @version 1.2.0
 *
 */
class LibImage
{
    /*错误信息*/
    protected $error_message = null;
    /*水印缓存*/
    protected $_mark_file = null;
    protected $_mark_img = null;

	protected $quality = 90;
	public function __construct($quality = 90)
	{	
		$this->quality = $quality;
		$this->error_message = null;
	}

    /**记录错误
     * @param $code [int] :错误代码
     * @param $target [string] :目标名称
     * @return [bool]  false
     */
    protected function ErrorTo($code,$target)
    {
        $errorArr = array(
            '-1' => '%s 不存在或者不是一个JPG图片',
            '-2' => '%s 文件夹不存在',
            '-3' => '%s 不存在或者不是一个PNG图片',
            '-4' => '%s 不存在或者不是一个有效的图片(jpg, gif, png, bmp)',
        );
        $this->error_message = sprintf($errorArr[$code],$target);
        return false;
    }
    /**返回错误
     * @return [string]  返回错误信息
     */
    public function Error()
    {
        return $this->error_message;
    }
    /**创建JPG缩略图
     * @param $src [string] :源图片文件名
     * @param $dest [string] :目标图片文件名,为空时则为$src
     * @param $width [int] : 缩略宽度
     * @param $height [int] :缩略高度
     * @return [bool]  成功: true, 失败 false
     */
    public function Cut($src, $dest, $width = 150, $height = 150)
    {
        if(empty($dest)) $dest = $src;
        $src_img = @imagecreatefromjpeg($src);
        if(!$src_img){
            return $this->ErrorTo(-1,$src);
        }
        $init_width = @imagesx($src_img);
        $init_height = @imagesy($src_img);
        $ratio = $width / $height;				   //改变后的图象的比例
        $init_ratio = $init_width / $init_height;  //实际图象的比例
        if($init_ratio >= $ratio)
        {
            /*宽度优先*/
            $des_height = ceil($width / $init_ratio);
            $dest_img = @imagecreatetruecolor($width,$des_height);
            @imagecopyresampled($dest_img, $src_img, 0, 0, 0, 0, $width, $des_height, $init_width, $init_height);
        }else{
            /*高度优先*/
            $des_width = ceil($height * $init_ratio);
            $dest_img = @imagecreatetruecolor($des_width,$height);
            @imagecopyresampled($dest_img, $src_img, 0, 0, 0, 0, $des_width, $height, $init_width, $init_height);
        }
        @imagedestroy($src_img);
        if(!@imagejpeg($dest_img,$dest, $this->quality)){
            return $this->ErrorTo(-2,$dest);
        }
        return true;
    }
    /**将图片修改成指定大小，图片不够大的用空白真补
     * @param $src [string] :源图片文件名
     * @param $dest [string] :目标图片文件名,为空时则为$src
     * @param $width [int] : 宽度
     * @param $height [int] : 高度
     * @return [bool]  成功: true, 失败 false
     */
    public function Resize($src, $dest ,$width, $height)
    {
        if(empty($dest)) $dest = $src;
        if( ($info = @getimagesize($src)) === false){
            return $this->ErrorTo(-1,$src);
        }
        $init_width = $info[0];
        $init_height = $info[1];
		$height = empty($height)? ceil($width*$init_height/$init_width): $height;
        if($init_width > $width || $init_height > $height)
        {
            if($this->Cut($src, $dest, $width, $height)){
                return $this->Resize($dest, null, $width, $height);
            }else{
                return false;
            }
        }
        else if($init_width < $width || $init_height < $height)
        {
            $dest_img = @imagecreatetruecolor($width,$height);
            $white = imagecolorallocate($dest_img,255,255,255);
            @imagefilledrectangle($dest_img, 0, 0, $width, $height, $white);
            $src_img = @imagecreatefromjpeg($src);
            $x = ($width - $init_width) / 2;
            $y = ($height - $init_height) / 2;
            @imagecopy($dest_img,$src_img, $x, $y, 0, 0, $init_width, $init_height);
            @imagedestroy($src_img);
            if(!@imagejpeg($dest_img,$dest, $this->quality)){
                return $this->ErrorTo(-2,$dest);
            }
        }
		else if($src != $dest)
		{
			//update by Soul 2013-5-25
			@copy($src, $dest);
		}
        return true;
    }
    /**给图片加PNG水印
     * @param $src [string] :源图片文件名
     * @param $dest [string] :目标图片文件名,为空时则为$src
     * @param $watermark [string] :水印图片文件名(png格式)
     * @param $pos [string] : 加载位置
     * @return [bool]  成功: true, 失败 false
     */
    public function Watermark($src, $dest, $watermark, $pos="center")
    {
        if(empty($dest)) $dest = $src;
        $src_img =  @imagecreatefromjpeg($src);
        if(!$src_img){
            return $this->ErrorTo(-1,$src);
        }
        if($this->_mark_file != $watermark){
            $mark_img =  @imagecreatefrompng($watermark);
            if(!$mark_img){
                return $this->ErrorTo(-3,$watermark);
            }
            $this->_mark_file = $watermark;
            $this->_mark_img = $mark_img;
        }else{
            $mark_img = $this->_mark_img;
        }
        $src_width   = @imagesx($src_img);
        $src_height  = @imagesy($src_img);
        $mark_width  = @imagesx($mark_img);
        $mark_height = @imagesy($mark_img);
        if($src_width < $mark_width || $src_height < $mark_height){
            /*当图片小于水印图时，修改水印自适应*/
            $mark_ratio = $mark_width / $mark_height;  //水印图象的比例
            if($src_width < $mark_width){
                $tmp_width = $src_width - 20;
                $tmp_height = ceil($tmp_width / $mark_ratio);
            }elseif($src_height < $mark_height){
                $tmp_height = $src_height - 20;
                $tmp_width = ceil($tmp_height * $mark_ratio);
            }
            $tmp_img = @ImageCreate($tmp_width,$tmp_height);
            $black = imagecolorallocate($tmp_img,0,0,0);
            $bgcolortrans = ImageColorTransparent($tmp_img,$black);
            @imagecopyresampled($tmp_img, $mark_img, 0, 0, 0, 0, $tmp_width, $tmp_height, $mark_width, $mark_height);
            $mark_img = $tmp_img;
            $mark_width = $tmp_width;
            $mark_height = $tmp_height;
        }
        switch($pos)
        {
            //中央
            case 'center':
                $x = ($src_width - $mark_width) / 2;
                $y = ($src_height - $mark_height) / 2;
                break;
            //右下
            case 'right-bottom':
                $x = $src_width - $mark_width;
                $y = $src_height - $mark_height;
                break;
            //右上
            case 'right-top':
                $x = $src_width - $mark_width;
                $y = 0;
                break;
            //左上
            case 'left-top':
                $x = 0;
                $y = 0;
                break;
            //左下
            case 'left-bottom':
                $x = 0;
                $y = $src_height - $mark_height;
                break;
            //随机
            case 'rand':
                $x = rand(0, $src_width - $mark_width);
                $y = rand(0, $src_height - $mark_height);
                break;
            default:
                $x = ($src_width - $mark_width) / 2;
                $y = ($src_height - $mark_height) / 2;
                break;
        }
        @imagecopy($src_img, $mark_img, $x, $y, 0, 0, $mark_width, $mark_height);
        @imagedestroy($mark_img);
        if(!@imagejpeg($src_img,$dest, $this->quality)){
            return $this->ErrorTo(-2,$dest);
        }
        return true;
    }
    /**图片转JPG
     * @param $src [string] :源图片文件名
     * @param $dest [string] :目标图片文件名,为空时则为 $src.jpg
     * @param $isDel [bool] :转换后是否删除源图片
     * @return [bool]  成功: true, 失败 false
     */
    public function ToJPG($src, $dest, $isDel = false)
    {
        if( ($info = @getimagesize($src)) == false){
            return $this->ErrorTo(-4,$src);
        }
        if(empty($dest)){
            $dest = basename($src);
            $p = strrpos($dest,'.');
            $dest = substr($dest,0,$p).'.jpg';
        }
        switch($info['mime']){
            case 'image/gif':
                $src_img = imagecreatefromgif($src);
                break;
            case 'image/jpeg':
                $src_img = imagecreatefromjpeg($src);
                break;
            case 'image/png':
                $src_img = imagecreatefrompng($src);
                break;
            case 'image/bmp':
                if(!function_exists('imagecreatefrombmp')) {
                    require_once 'php_bmp.php';
                }
                $src_img = imagecreatefrombmp($src);
                break;
            case 'image/vnd.wap.wbmp':
                $src_img = imagecreatefromwbmp($src);
                break;
            case 'image/xbm':
                $src_img = imagecreatefromxbm($src);
                break;
            case 'image/xpm':
                $src_img = imagecreatefromxpm($src);
                break;
        }
        $width   = @imagesx($src_img);
        $height  = @imagesy($src_img);
        $dest_img = @imagecreatetruecolor($width,$height);
        $white = @imagecolorallocate($dest_img,255,255,255);
        @imagefilledrectangle($dest_img, 0, 0, $width, $height, $white);
        @imagecopy($dest_img,$src_img, 0, 0, 0, 0, $width, $height);
        @imagedestroy($src_img);
        if(!@imagejpeg($dest_img,$dest, $this->quality)){
            return $this->ErrorTo(-2,$dest);
        }
        if($isDel) @unlink($src);
        return true;
    }
	
	/**给图片修改大小、加PNG水印
     * @param $src [string] :源图片文件名
     * @param $dest [string] :目标图片文件名,为空时则为$src
	 * @param $width [int] : 宽度
     * @param $height [int] : 高度
     * @param $watermark [string] :水印图片文件名(png格式)
     * @param $pos [string] : 加载位置
     * @return [bool]  成功: true, 失败 false
     */
	public function ResizeWatermark($src, $dest, $width, $height,  $watermark, $pos="center")
	{
		if($this->Resize($src, $dest ,$width, $height))
		{
			if($this->Watermark($dest, $dest, $watermark, $pos))
			{
				return true;
			}
		}
		return false;
	}


   /**
     * 裁剪文件
     * @param $srcFile string 源文件
     * @param $sizeArr [
			[$x1, $x2, $y1, $y2],
			...
		]$x1 int|float 像素int|不超过1的小数
     * @param $x2 int|float 像素int|不超过1的小数
     * @param $y1 int|float 像素int|不超过1的小数
     * @param $y2 int|float 像素int|不超过1的小数
     * @param $padh int 裁剪图之间的空隙
     * @param $newFile string 裁剪后的文件
     * @return bool false|true 成功|失败
     */
	public function thumb($orgFile,$sizeArr,$toFile, $padh = 0)
	{
		if(!file_exists($orgFile)) return '源文件图片不存在';
		if(count($sizeArr) <= 0) return '裁剪图片不可为空';
		$imageType = strtolower(pathinfo($orgFile,PATHINFO_EXTENSION));
		switch ($imageType)
		{
			case 'jpg': //扩展命为jpg
				//TODO 解决图片资源和后缀名不一致问题
				if(@!($srcImg = imagecreatefromjpeg($orgFile)))
				{
					if(@!($srcImg = imagecreatefrompng($orgFile)))
					{
						$srcImg = imagecreatefromgif($orgFile);
					}
				}
				break;
			case 'png':
				if(@!($srcImg = imagecreatefrompng($orgFile)))
				{
					if(@!($srcImg = imagecreatefromjpeg($orgFile)))
					{
						$srcImg = imagecreatefromgif($orgFile);
					}
				}
				break;
			case 'gif':
				if(@!($srcImg = imagecreatefromgif($orgFile)))
				{
					if(@!($srcImg = imagecreatefrompng($orgFile)))
					{
						$srcImg = imagecreatefromjpeg($orgFile);
					}
				}
				break;
			default:
				return '图片格式不支持';
		}
		//原图片的宽度
		$srcWidth = imagesx($srcImg);
		//原图的高度
		$srcHeight = imagesy($srcImg);

		$temp = [];
		//百分比转换,并计算裁剪图片的宽高
		foreach ($sizeArr as $key => $value)
		{
			 if(!is_int($value['0'])) $value['0'] = ceil($srcWidth * $value['0']);
			 if(!is_int($value['1'])) $value['1'] = ceil($srcWidth * $value['1']);
			 if(!is_int($value['2'])) $value['2'] = ceil($srcHeight * $value['2']);
			 if(!is_int($value['3'])) $value['3'] = ceil($srcHeight * $value['3']);
			 $value['width'] = $value['1'] - $value['0'];
			 $value['height'] = $value['3'] - $value['2'];
			 if($value['width'] <= 0) return '裁剪后的图片宽度错误';
			 if($value['height'] <= 0) return '裁剪后的图片高度错误';
			 unset($sizeArr[$key]);
			 $temp[] = $value;
		}

		unset($value,$sizeArr);

		//计算新图片的高度为和
		$newHeight = array_sum(array_column($temp,'height'));
		//计算新图片的宽度为最大
		$newWidth = max(array_column($temp,'width'));

		//创建画布
		$midImg = imagecreatetruecolor($newWidth,$newHeight+(count($temp)-1)*$padh);

		//填充白色，宽度不一直
		$color = imagecolorAllocate($midImg,0xFF,0xFF,0xFF);
		imagefill($midImg,0,0,$color) ;

		$height = 0;

		$i = 0;

		//宽度从0开始，第一张为0,高度取上一张图片的高度
		foreach ($temp as $key => $value)
		{
			if($i != 0){
				//第二张图片合并时是第一张图的高度
				$height += $temp[$key-1]['height'];
			}
			$result = imagecopy($midImg, $srcImg, 0, $height, $value['0'], $value['2'], $value['width'], $value['height']);
			if(!$result){
				return '第'.($key+1).'张图片合并失败';
			}
			$height += $padh;
			$i++ ;
		}
		unset($temp,$i,$value,$key);

		//保存图片
		switch ($imageType)
		{
			case 'jpg':
				$result = imagejpeg($midImg, $toFile, 100);
				break;
			case 'png':
				$result = imagepng($midImg, $toFile, 9);
				break;
			case 'gif':
				$result = imagegif($midImg,$toFile, 100);
				break;
			default:
				return '保存图片错误';
				break;
		}
		if(!$result){
			return '保存图片错误';
		}
		return true;
	}
	
	/**
     * 旋转图片
     * @param $src string 源文件
     * @param $dest string 目标文件 为空返回base64
     * @param $angle int 0~360
     * @param $bgcolor 颜色值
     */
	public function rotate($src, $dest = '', $angle, $bgcolor = 16777215)
	{
		if( ($info = @getimagesize($src)) == false)
            return $this->ErrorTo(-4,$src);
        switch($info['mime'])
		{
            case 'image/jpeg':
                $src_img = imagecreatefromjpeg($src);
				$img = imagerotate($src_img, $angle, $bgcolor);
				if(empty($dest)){
					ob_start();
					imagejpeg($img, null, $this->quality);
					$imgdata = base64_encode(ob_get_contents());
					ob_end_clean();
					imagedestroy($img);
					return ['status'=>true,'data'=>$imgdata];
				}else{
					imagejpeg($img, $dest, $this->quality);
					imagedestroy($img);
					return ['status'=>true, 'data'=>''];
				}
                break;
            case 'image/png':
                $src_img = imagecreatefrompng($src);
				$img = imagerotate($src_img, $angle, $bgcolor); 
				if(empty($dest)){
					ob_clean();
					ob_start();
					imagepng($img, null, $this->quality);
					$imgdata = base64_encode(ob_get_contents());
					ob_end_clean();
					imagedestroy($img);
					return ['status'=>true,'data'=>$imgdata];
				}else{
					imagepng($img, $dest, $this->quality);
					imagedestroy($img);
					return ['status'=>true, 'data'=>''];
				}
                break;
			default:
				return ['status'=>false, 'data'=>'不支持'.$info['mime'].'图片旋转'];
			break;
        }
		return ['status'=>false, 'data'=>'图片旋转失败'];
	}
}