<?php
namespace lib;
use Intervention\Image\ImageManager;

/**
 * php图像处理 class - WhileDo.com
 * @author HzqGhost admin@whiledo.com QQ:313143468
 * @version 1.2.0
 *
 */
class image
{
    /*错误信息*/
    protected $error_message = null;
    /*水印缓存*/
    protected $_mark_file = null;
    protected $_mark_img = null;

	protected $quality = 75;
	protected $lastResize = [];

	public function __construct($quality = 75)
	{	
		$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);
        }
        @chmod($dest, 0777);
        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;
        
        $manager = new ImageManager(array('driver' => 'imagick'));
        //$image = $manager->make($src);
		//使用二进制流加载
		if(!empty($this->lastResize) && $this->lastResize['src'] == $src){
			//加缓存
			$image = $this->lastResize['obj'];
		}else{
			$image = $manager->make(file_get_contents($src));
			$this->lastResize = ['src'=>$src, 'obj'=>$image];
		}
        $init_width = $image->getWidth();
        $init_height = $image->getHeight();
        $height = empty($height)? ceil($width*$init_height/$init_width): $height;
        if ($init_width > $width || $init_height > $height)
        {
            $ratio = $width / $height;
            $init_ratio = $init_width / $init_height;
            if ($init_ratio >= $ratio)
            {
                $image->resize($width, null, function ($constraint) {
                    $constraint->aspectRatio();
                    $constraint->upsize();
                });
            } else
            {
                $image->resize(null, $height, function ($constraint) {
                    $constraint->aspectRatio();
                    $constraint->upsize();
                });
            }
            $image->save($dest, 100);
    
            $src = $dest;
        }
        
        $manager->canvas($width, $height, '#FFFFFF')
            ->insert($src, 'center')
            ->save($dest, $this->quality);
        @chmod($dest, 0777);
        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($pos!='tile' && isset(\mvc::$cfg['watermarkModel'])){
            $pos=\mvc::$cfg['watermarkModel'];
        }*/
        if(empty($dest)) $dest = $src;
        if(strtolower(substr($src,-4))=='.png'){
            $src_img =  @imagecreatefrompng($src);
        }else{
            $src_img =  @imagecreatefromjpeg($src);
        }
        if(!$src_img){
            return $this->ErrorTo(-1,$src);
        }
        if($this->_mark_file != $watermark || $this->_mark_img == null){
            $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;
        }
        if($pos=='tile'){
            //循环平铺水印
            $watermarkMargin = -50;
            if(isset(\mvc::$cfg['watermarkMargin'])){
                $watermarkMargin=\mvc::$cfg['watermarkMargin'];
            }
            $left = $watermarkMargin;
            $top = $watermarkMargin;
            for ($x = 0; $x < $src_width+abs($watermarkMargin*2); $x) {
                for ($y = 0; $y < $src_height+abs($watermarkMargin*2); $y) {
                    imagecopy($src_img, $mark_img, $x+$left, $y+$top, 0, 0, $mark_width, $mark_height);
                    $y += $mark_height;
                }
                $x += $mark_width;
            }            
            
        }else{
            @imagecopy($src_img, $mark_img, $x, $y, 0, 0, $mark_width, $mark_height);
        }
        //@imagedestroy($mark_img);
		if(strtolower(substr($dest,-4))=='.png'){
			//目标图片是png图 soul 2022/11/10
			imagesavealpha($src_img, true);
			if(!@imagepng($src_img,$dest)){
				return $this->ErrorTo(-2,$dest);
			}
		}else if(!@imagejpeg($src_img,$dest, $this->quality)){
            return $this->ErrorTo(-2,$dest);
        }
        @chmod($dest, 0777);
        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';
        }
        
        $manager = new ImageManager(array('driver' => 'imagick'));
        $manager->make($src)->save($dest, $this->quality);
        @chmod($dest, 0777);
        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))
		{
			return $this->Watermark($dest, $dest, $watermark, $pos);
		}
		return false;
	}

    /**从中间位置指定宽高裁剪缩略图
     * @param $src [string] :源图片文件名
     * @param $dest [string] :目标图片文件名,为空时则为$src
	 * @param $width [int] : 宽度
     * @param $height [int] : 高度
     * @param $zoom [bool] : 是否按比例缩放原图
     * @return [bool]  成功: true, 失败 false
    */
	public function MiddleCut($src, $dest, $width, $height,$zoom=true)
    {
        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);
        if($zoom){
            $ratio = $width / $height;				   //改变后的图象的比例
            $init_ratio = $init_width / $init_height;  //实际图象的比例
            if($init_width < $width || $init_height < $height){
                $x = ($width - $init_width) / 2;
                $y = ($height - $init_height) / 2;
            }else{
                $x = 0; $y = 0;
            }
            if($init_ratio >= $ratio)
            {
                /*高度优先*/
                $des_width = ceil($height * $init_ratio);
                $zoom_img = @imagecreatetruecolor($des_width,$height);
                @imagecopyresampled($zoom_img, $src_img, $x, $y, 0, 0, $des_width, $height, $init_width, $init_height);
            }else{
                /*宽度优先*/
                $des_height = ceil($width / $init_ratio);
                $zoom_img = @imagecreatetruecolor($width,$des_height);
                @imagecopyresampled($zoom_img, $src_img, $x, $y, 0, 0, $width, $des_height, $init_width, $init_height);
            }
            $src_img = $zoom_img;
            $init_width = @imagesx($src_img);
            $init_height = @imagesy($src_img);
        }
        $mid_x = round($init_width/2);
        $mid_y = round($init_height/2);

        $x = $mid_x - round($width / 2);
        $y = $mid_y - round($height / 2);

        $dest_img = @imagecreatetruecolor($width,$height);
        @imagecopyresampled($dest_img, $src_img, 0, 0, $x, $y, $width, $height, $width, $height);
        @imagedestroy($src_img);
        if(!@imagejpeg($dest_img,$dest, $this->quality)){
            return $this->ErrorTo(-2,$dest);
        }
        @chmod($dest, 0777);
        return true;
    }
}