<?php


namespace servers\image;


use \Exception;

/**
 * Class image
 * @author hzq
 * @package servers\image
 * @version 1.0.0
 */
class image
{
    /**
     * 水印缓存
     * @var null
     */
    protected $_MarkFile = null;

    /**
     * @var null
     */
    protected $_MarkImg = null;

    /**
     * @var int|mixed
     */
    private $quality = 75;


    /**
     * 错误代码
     * @var string[]
     */
    private $errorArr = array(
        '-1' => '%s 不存在或者不是一个JPG图片',
        '-2' => '%s 文件夹不存在',
        '-3' => '%s 不存在或者不是一个PNG图片',
        '-4' => '%s 不存在或者不是一个有效的图片(jpg, gif, png, bmp)',
    );

    /**
     * 设置图片的质量
     * @param $quality
     * @return $this
     */
    public function quality($quality)
    {
        $this->quality = $quality;
        return $this;
    }

    /**
     * 获取错误信息
     * @param $code
     * @param $target
     * @return string
     */
    public function errorMssage($code, $target)
    {
        return sprintf($this->errorArr[$code], $target);
    }

    /**
     * 根据图片地址获取文件资源
     * @param $src
     * @return false|\GdImage|resource
     */
    private function getImageFromSrc($src)
    {
        return imagecreatefromstring(file_get_contents($src));
    }

    /**
     * 创建JPG缩略图
     * @param string $src 源图片文件名
     * @param string $dest 目标图片文件名,为空时则为$src
     * @param int $width 缩略宽度
     * @param int $height 缩略高度
     * @return bool 成功: true, 失败 string
     */
    public function cut($src, $dest, $width = 150, $height = 150)
    {
        try {
            if (empty($dest)) $dest = $src;
            $srcImg = $this->getImageFromSrc($src);
            if(!is_resource($srcImg)) return $this->errorMssage(-1, $src);
            $initWidth = imagesx($srcImg);
            $initHeight = imagesy($srcImg);
            //实际图象的比例
            $initRatio = $initWidth / $initHeight;
            //改变后的图象的比例
            $ratio = $width / $height;

            if ($initRatio >= $ratio) {
                //宽度优先
                $desHeight = ceil($width / $initRatio);
                $destImg = imagecreatetruecolor($width, $desHeight);
                imagecopyresampled($destImg, $srcImg, 0, 0, 0, 0, $width, $desHeight, $initWidth, $initHeight);
            } else {
                //高度优先
                $desWidth = ceil($height * $initRatio);
                $destImg = imagecreatetruecolor($desWidth, $height);
                imagecopyresampled($destImg, $srcImg, 0, 0, 0, 0, $desWidth, $height, $initWidth, $initHeight);
            }
            imagedestroy($srcImg);
            $result = imagejpeg($destImg,$dest,$this->quality);
            if($result === false){
                return $this->errorMssage(-2, $dest);
            }
            return true;
        }catch (\Exception $e){
            return $e->getMessage();
        }
    }

    /**
     * 将图片修改成指定大小，图片不够大的用空白真补
     * @param string $src 源图片文件名
     * @param string $dest 目标图片文件名,为空时则为$src
     * @param int $width 宽度
     * @param int $height 高度
     * @return bool
     */
    public function resize($src, $dest, $width, $height)
    {
        try {
            if (empty($dest)) $dest = $src;

            if (($info = getimagesize($src)) === false) {
                return $this->errorMssage(-1, $src);
            }

            $initWidth = $info[0];
            $initHeight = $info[1];
            $height = empty($height) ? ceil($width * $initHeight / $initWidth) : $height;
            if ($initWidth > $width || $initHeight > $height) {
                if ($this->cut($src, $dest, $width, $height)) {
                    return $this->resize($dest, null, $width, $height);
                } else {
                    return false;
                }
            } else if ($initWidth < $width || $initHeight < $height) {
                $destImg = imagecreatetruecolor($width, $height);
                $white = imagecolorallocate($destImg, 255, 255, 255);
                imagefilledrectangle($destImg, 0, 0, $width, $height, $white);
                $srcImg = $this->getImageFromSrc($src);
                $x = ($width - $initWidth) / 2;
                $y = ($height - $initHeight) / 2;
                imagecopy($destImg, $srcImg, $x, $y, 0, 0, $initWidth, $initHeight);
                imagedestroy($srcImg);
                if (!imagejpeg($destImg, $dest, $this->quality)) {
                    return $this->errorMssage(-2, $dest);
                }
            } else if ($src != $dest) {
                //update by Soul 2013-5-25
                copy($src, $dest);
            }
            return true;
        }catch (Exception $e)
        {
            return $e->getMessage();
        }


    }

    /**
     * 给图片加PNG水印
     * @param string $src 源图片文件名
     * @param string $dest 目标图片文件名,为空时则为$src
     * @param string $watermark 印图片文件名(png格式)
     * @param string $pos 加载位置
     * @return bool
     */
    public function watermark($src, $dest, $watermark, $pos = "center")
    {
        try {
            if (empty($dest)) $dest = $src;
            $srcImg = $this->getImageFromSrc($src);
            if (!is_resource($srcImg)) return $this->errorMssage(-1, $src);

            if ($this->_MarkFile != $watermark) {
                $markImg = imagecreatefrompng($watermark);
                if (!is_resource($markImg)) return $this->errorMssage(-3, $watermark);
                $this->_MarkFile = $watermark;
                $this->_MarkImg = $markImg;
            } else {
                $markImg = $this->_MarkImg;
            }


            $srcWidth = @imagesx($srcImg);
            $srcHeight = @imagesy($srcImg);
            $markWidth = @imagesx($markImg);
            $markHeight = @imagesy($markImg);


            if ($srcWidth < $markWidth || $srcHeight < $markHeight)
            {
                //当图片小于水印图时，修改水印自适应
                $markRatio = $markWidth / $markHeight;  //水印图象的比例
                if ($srcWidth < $markWidth) {
                    $tmpWidth = $srcWidth - 20;
                    $tmpHeight = ceil($tmpWidth / $markRatio);
                } elseif ($srcHeight < $markHeight) {
                    $tmpHeight = $srcHeight - 20;
                    $tmpWidth = ceil($tmpHeight * $markRatio);
                }
                $tmpImg = imageCreate($tmpWidth, $tmpHeight);
                $black = imagecolorallocate($tmpImg, 0, 0, 0);
                imageColorTransparent($tmpImg, $black);
                imagecopyresampled($tmpImg, $markImg, 0, 0, 0, 0, $tmpWidth, $tmpHeight, $markWidth, $markHeight);
                $markImg = $tmpImg;
                $markWidth = $tmpWidth;
                $markHeight = $tmpHeight;
            }
            switch ($pos) {
                //中央
                case 'center':
                    $x = ($srcWidth - $markWidth) / 2;
                    $y = ($srcHeight - $markHeight) / 2;
                    break;
                //右下
                case 'right-bottom':
                    $x = $srcWidth - $markWidth;
                    $y = $srcHeight - $markHeight;
                    break;
                //右上
                case 'right-top':
                    $x = $srcWidth - $markWidth;
                    $y = 0;
                    break;
                //左上
                case 'left-top':
                    $x = 0;
                    $y = 0;
                    break;
                //左下
                case 'left-bottom':
                    $x = 0;
                    $y = $srcHeight - $markHeight;
                    break;
                //随机
                case 'rand':
                    $x = rand(0, $srcWidth - $markWidth);
                    $y = rand(0, $srcHeight - $markHeight);
                    break;
                default:
                    $x = ($srcWidth - $markWidth) / 2;
                    $y = ($srcHeight - $markHeight) / 2;
                    break;
            }
            @imagecopy($srcImg, $markImg, $x, $y, 0, 0, $markWidth, $markHeight);
            @imagedestroy($markImg);
            if (!imagejpeg($srcImg, $dest, $this->quality)) {
                return $this->errorMssage(-2, $dest);
            }
            return true;
        }catch (Exception $e) {
            return $e->getMessage();
        }

    }

    /**
     * 图片转JPG
     * @param string $src 源图片文件名
     * @param string $dest 目标图片文件名,为空时则为 $src.jpg
     * @param false $isDel 转换后是否删除源图片
     * @return bool
     */
    public function toJpg($src, $dest, $isDel = false)
    {
        try {
            if (($info = getimagesize($src)) == false) {
                return $this->errorMssage(-4, $src);
            }
            if (empty($dest)) {
                $dest = basename($src);
                $p = strrpos($dest, '.');
                $dest = substr($dest, 0, $p) . '.jpg';
            }
            switch ($info['mime']) {
                case 'image/gif':
                    $srcImg = imagecreatefromgif($src);
                    break;
                case 'image/jpeg':
                    $srcImg = imagecreatefromjpeg($src);
                    break;
                case 'image/png':
                    $srcImg = imagecreatefrompng($src);
                    break;
                case 'image/vnd.wap.wbmp':
                    $srcImg = imagecreatefromwbmp($src);
                    break;
                case 'image/xbm':
                    $srcImg = imagecreatefromxbm($src);
                    break;
                case 'image/xpm':
                    $srcImg = imagecreatefromxpm($src);
                    break;
            }
            if(!is_resource($srcImg)) $this->getImageFromSrc($src);
            if(!is_resource($srcImg)) return $this->errorMssage('-1',$src);

            $width = imagesx($srcImg);
            $height = imagesy($srcImg);
            $destImg = imagecreatetruecolor($width, $height);
            $white = imagecolorallocate($destImg, 255, 255, 255);
            imagefilledrectangle($destImg, 0, 0, $width, $height, $white);
            imagecopy($destImg, $srcImg, 0, 0, 0, 0, $width, $height);
            imagedestroy($srcImg);
            if (!imagejpeg($destImg, $dest, $this->quality)) {
                return $this->errorMssage(-2, $dest);
            }
            if ($isDel) unlink($src);
            return true;
        }catch (Exception $e){
            return $e->getMessage();
        }

    }

    /**
     * 给图片修改大小、加PNG水印
     * @param $src
     * @param $dest
     * @param $width
     * @param $height
     * @param $watermark
     * @param string $pos
     * @return bool
     */
    public function resizeWatermark($src, $dest, $width, $height, $watermark, $pos = "center")
    {
        try {
            if ($this->resize($src, $dest, $width, $height)) {
                if ($this->watermark($dest, $dest, $watermark, $pos)) {
                    return true;
                }
            }
            return false;
        }catch (Exception $e){
            return $e->getMessage();
        }
    }
}
