zoukankan      html  css  js  c++  java
  • PHP使用gd库做的图像处理

    大部分采用的是tp5.1框架的image处理类。因为一些小问题无法处理,故自己整理了一下think-image,简单实现了一下功能。

    主要问题是think-image不能直接获取远程图片,没有直接输出图片,添加图片水印时无法直接将水印图片处理成想要的宽高,而且think-image有个小问题,在添加完图片水印后,如果再添加文字水印,文字颜色就设置不上了,昨天刚发现的。

    <?php
    
    
    namespace work;
    
    
    class ImageTools
    {
        public $file;
        public $width;
        public $height;
        //常量,标识缩略图等比例缩放类型
        const THUMB_SCALING = 1;
        // //常量,标识缩略图缩放后填充类型
        const THUMB_FILLED = 2;
        // //常量,标识缩略图居中裁剪类型
        const THUMB_CENTER = 3;
        // //常量,标识缩略图左上角裁剪类型
        const THUMB_NORTHWEST = 4;
        // //常量,标识缩略图右下角裁剪类型
        const THUMB_SOUTHEAST = 5;
        // //常量,标识缩略图固定尺寸缩放类型
        const THUMB_FIXED = 6;
    
        /* 水印相关常量定义 */
        const WATER_NORTHWEST = 1; //常量,标识左上角水印
        const WATER_NORTH     = 2; //常量,标识上居中水印
        const WATER_NORTHEAST = 3; //常量,标识右上角水印
        const WATER_WEST      = 4; //常量,标识左居中水印
        const WATER_CENTER    = 5; //常量,标识居中水印
        const WATER_EAST      = 6; //常量,标识右居中水印
        const WATER_SOUTHWEST = 7; //常量,标识左下角水印
        const WATER_SOUTH     = 8; //常量,标识下居中水印
        const WATER_SOUTHEAST = 9; //常量,标识右下角水印
        /* 翻转相关常量定义 */
        const FLIP_X = 1; //X轴翻转
        const FLIP_Y = 2; //Y轴翻转
    
        public function __construct($file)
        {
            $this->file = $file;
            $this->width = imagesx($file);
            $this->height = imagesy($file);
        }
    
        /**
         * @title 打开一张图片
         * @description
         * @param name:page type:int require:1 default: other: desc:页数
         * @DateTime 2021/11/19 15:13
         * @author 尹纪松
         * @url ///open
         * @method get
         */
        public static function open($file)
        {
            $file = imagecreatefromstring(file_get_contents($file));
            return new self($file);
        }
    
        /**
         * 返回文件width
         */
        public function getWidth()
        {
            return $this->width();
        }
    
        /**
         * 返回文件高度
         */
        public function getHeight()
        {
            return $this->height();
        }
    
        /**
         * 旋转图像
         * @param int $degrees 顺时针旋转的度数
         * @return $this
         */
        public function rotate($degrees = 90)
        {
            $img = imagerotate($this->file, -$degrees, imagecolorallocatealpha($this->file, 0, 0, 0, 127));
            imagedestroy($this->file);
            $this->file = $img;
            $this->width  = imagesx($this->file);
            $this->height = imagesy($this->file);
            return $this;
        }
    
        /**
         * 翻转图像
         * @param integer $direction 翻转轴,X或者Y
         * @return $this
         */
        public function flip($direction = self::FLIP_X)
        {
            //原图宽度和高度
            $w = $this->width;
            $h = $this->height;
            $img = imagecreatetruecolor($w, $h);
            switch ($direction) {
                case self::FLIP_X:
                    for ($y = 0; $y < $h; $y++) {
                        imagecopy($img, $this->im, 0, $h - $y - 1, 0, $y, $w, 1);
                    }
                    break;
                case self::FLIP_Y:
                    for ($x = 0; $x < $w; $x++) {
                        imagecopy($img, $this->im, $w - $x - 1, 0, $x, 0, 1, $h);
                    }
                    break;
                default:
                    throw new \think\Exception('不支持的图像翻转类型', 201);
            }
            imagedestroy($this->file);
            $this->file = $img;
            $this->width = imagesx($this->file);
            $this->height = imagesy($this->file);
            return $this;
        }
        /**
         * 生成缩略图
         */
        public function thumb($width,$height,$type = self::THUMB_SCALING)
        {
            $w = $this->width;
            $h = $this->height;
            switch ($type) {
                /* 等比例缩放 */
                case self::THUMB_SCALING:
                    //原图尺寸小于缩略图尺寸则不进行缩略
                    if ($w < $width && $h < $height) {
                        return $this;
                    }
                    //计算缩放比例
                    $scale = min($width / $w, $height / $h);
                    //设置缩略图的坐标及宽度和高度
                    $x      = $y      = 0;
                    $width  = $w * $scale;
                    $height = $h * $scale;
                    break;
                /* 居中裁剪 */
                case self::THUMB_CENTER:
                    //计算缩放比例
                    $scale = max($width / $w, $height / $h);
                    //设置缩略图的坐标及宽度和高度
                    $w = $width / $scale;
                    $h = $height / $scale;
                    $x = ($this->info['width'] - $w) / 2;
                    $y = ($this->info['height'] - $h) / 2;
                    break;
                /* 左上角裁剪 */
                case self::THUMB_NORTHWEST:
                    //计算缩放比例
                    $scale = max($width / $w, $height / $h);
                    //设置缩略图的坐标及宽度和高度
                    $x = $y = 0;
                    $w = $width / $scale;
                    $h = $height / $scale;
                    break;
                /* 右下角裁剪 */
                case self::THUMB_SOUTHEAST:
                    //计算缩放比例
                    $scale = max($width / $w, $height / $h);
                    //设置缩略图的坐标及宽度和高度
                    $w = $width / $scale;
                    $h = $height / $scale;
                    $x = $this->info['width'] - $w;
                    $y = $this->info['height'] - $h;
                    break;
                /* 填充 */
                case self::THUMB_FILLED:
                    //计算缩放比例
                    if ($w < $width && $h < $height) {
                        $scale = 1;
                    } else {
                        $scale = min($width / $w, $height / $h);
                    }
                    //设置缩略图的坐标及宽度和高度
                    $neww = $w * $scale;
                    $newh = $h * $scale;
                    $x    = $this->info['width'] - $w;
                    $y    = $this->info['height'] - $h;
                    $posx = ($width - $w * $scale) / 2;
                    $posy = ($height - $h * $scale) / 2;
                    do {
                        //创建新图像
                        $img = imagecreatetruecolor($width, $height);
                        // 调整默认颜色
                        $color = imagecolorallocate($img, 255, 255, 255);
                        imagefill($img, 0, 0, $color);
                        //裁剪
                        imagecopyresampled($img, $this->im, $posx, $posy, $x, $y, $neww, $newh, $w, $h);
                        imagedestroy($this->im); //销毁原图
                        $this->im = $img;
                    } while (!empty($this->gif) && $this->gifNext());
                    $this->info['width']  = (int) $width;
                    $this->info['height'] = (int) $height;
                    return $this;
                /* 固定 */
                case self::THUMB_FIXED:
                    $x = $y = 0;
                    break;
                default:
                    throw new ImageException('不支持的缩略图裁剪类型');
            }
            return $this->crop($w,$h,$x,$y,$width,$height);
        }
    
        /**
         * 裁剪图像
         */
        public function crop($w,$h,$x=0,$y=0,$width=null,$height=null)
        {
            empty($width) && $width   = $w;
            empty($height) && $height = $h;
            $img = imagecreatetruecolor($width, $width);
            // 调整默认颜色
            $color = imagecolorallocate($img, 255, 255, 255);
            imagefill($img, 0, 0, $color);
            //裁剪
            imagecopyresampled($img, $this->file, 0, 0, 0, 0, $width, $height, $w, $h);
            imagedestroy($this->file);
            $this->file = $img;
            $this->width  = imagesx($this->file);
            $this->height = imagesy($this->file);
            return $this;
        }
    
        /**
         * 向图片中插入图片
         */
        public function water($source, $locate, $size=[],$alpha=100)
        {
            $waterPic = imagecreatefromstring(file_get_contents($source));
            if(empty($size)){
                $size[0] = imagesx($waterPic);
                $size[1] = imagesy($waterPic);
            }
            if(imagesx($waterPic) != $size[0] || imagesy($waterPic) != $size[1]){
                $scale = min($size[0] / imagesx($waterPic), $size[1] / imagesy($waterPic));
                $w = imagesx($waterPic);
                $h = imagesy($waterPic);
                $width = $w * $scale;
                $height = $h * $scale;
                $img = imagecreatetruecolor($width, $width);
                // 调整默认颜色
                $color = imagecolorallocate($img, 255, 255, 255);
                imagefill($img, 0, 0, $color);
                //裁剪
                imagecopyresampled($img, $waterPic, 0, 0, 0, 0, $width, $height, $w, $h);
                imagedestroy($waterPic);
                $waterPic = $img;
            }
            //创建真彩画布
            //imagecreatetruecolor(int $width, int $height)--新建一个真彩色图像
            $image_3 = imageCreatetruecolor($this->width,$this->height);
            //为真彩画布创建白色背景
            //imagecolorallocate(resource $image, int $red, int $green, int $blue)
            $color = imagecolorallocate($image_3, 255, 255, 255);
            //imagefill(resource $image ,int $x ,int $y ,int $color)
            //在 image 图像的坐标 x,y(图像左上角为 0, 0)处用 color 颜色执行区域填充(即与 x, y 点颜色相同且相邻的点都会被填充)
            imagefill($image_3, 0, 0, $color);
            //设置透明
            //imagecolortransparent(resource $image [,int $color])
            //将image图像中的透明色设定为 color
    //        imageColorTransparent($image_3, $color);
            //复制图片一到真彩画布中(重新取样-获取透明图片)
            //imagecopyresampled(resource $dst_image ,resource $src_image ,int $dst_x ,int $dst_y ,int $src_x , int $src_y ,int $dst_w ,int $dst_h ,int $src_w ,int $src_h)
            // dst_image:目标图象连接资源
            // src_image:源图象连接资源
            // dst_x:目标 X 坐标点
            // dst_y:目标 Y 坐标点
            // src_x:源的 X 坐标点
            // src_y:源的 Y 坐标点
            // dst_w:目标宽度
            // dst_h:目标高度
            // src_w:源图象的宽度
            // src_h:源图象的高度
            imagecopyresampled($image_3, $this->file, 0, 0, 0, 0, $this->width, $this->height, $this->width, $this->height);
    
            // 与图片二合成
            // imagecopymerge ( resource $dst_im , resource $src_im , int $dst_x , int $dst_y , int $src_x , int $src_y , int $src_w , int $src_h , int $pct )---拷贝并合并图像的一部分
            // 将 src_im 图像中坐标从 src_x,src_y 开始,宽度为 src_w,高度为 src_h 的一部分拷贝到 dst_im 图像中坐标为 dst_x 和 dst_y 的位置上。两图像将根据 pct 来决定合并程度,其值范围从 0 到 100。当 pct = 0 时,实际上什么也没做,当为 100 时对于调色板图像本函数和 imagecopy() 完全一样,它对真彩色图像实现了 alpha 透明。
    
            imagecopymerge($image_3, $waterPic, $locate[0], $locate[1], 0, 0, $size[0], $size[1], $alpha);
            $this->file = $image_3;
            return $this;
        }
    
        /**
         * 向图片中插入文字
         */
        public function text($text, $font, $size, $color = '#00000000', $locate, $offset = 0, $angle = 0)
        {
            //判断字体文件存在不存在
            if(!file_exists($font)){
                throw new \think\Exception('字体文件不存在', 201);
            }
            //获取文字信息
            $info = imagettfbbox($size, $angle, $font, $text);
            $minx = min($info[0], $info[2], $info[4], $info[6]);
            $maxx = max($info[0], $info[2], $info[4], $info[6]);
            $miny = min($info[1], $info[3], $info[5], $info[7]);
            $maxy = max($info[1], $info[3], $info[5], $info[7]);
            /* 计算文字初始坐标和尺寸 */
            $x = $minx;
            $y = abs($miny);
            $w = $maxx - $minx;
            $h = $maxy - $miny;
            list($posx, $posy) = $locate;
            $x += $posx;
            $y += $posy;
            /* 设置偏移量 */
            if (is_array($offset)) {
                $offset        = array_map('intval', $offset);
                list($ox, $oy) = $offset;
            } else {
                $offset = intval($offset);
                $ox     = $oy     = $offset;
            }
            /* 设置颜色 */
            if (is_string($color) && 0 === strpos($color, '#')) {
                $color = str_split(substr($color, 1), 2);
                $color = array_map('hexdec', $color);
                if (empty($color[3]) || $color[3] > 127) {
                    $color[3] = 0;
                }
            }else{
                throw new \think\Exception('字体颜色值不正确', 201);
            }
            $col = imagecolorallocatealpha($this->file, $color[0], $color[1], $color[2], $color[3]);
            imagettftext($this->file, $size, $angle, $x + $ox, $y + $oy, $col, $font, $text);
            return $this;
        }
    
        /**
         * 保存图像
         */
        public function save($pathname,$type = 'png',$quality=80,$interlace=true)
        {
            try {
                //保存图像
                if ('jpeg' == $type || 'jpg' == $type) {
                    //JPEG图像设置隔行扫描
                    imageinterlace($this->file, $interlace);
                    imagejpeg($this->file, $pathname, $quality);
                } elseif ('png' == $type) {
                    //设定保存完整的 alpha 通道信息
                    imagesavealpha($this->file, true);
                    //ImagePNG生成图像的质量范围从0到9的
                    imagepng($this->file, $pathname, min((int) ($quality / 10), 9));
                }
                return true;
            }catch (\Exception $e){
                throw new \think\Exception($e->getMessage(), 201);
            }
        }
    
        /**
         * 直接输出图像
         */
        public function output()
        {
            header('content-type:image/png');
            imagepng($this->file);
            imagedestroy($this->file);
            exit();
        }
    }

    直接拿来用就好了,参数跟think-image几乎一样,功能也是,多了一个直接输出功能,可以不保存在服务器上了。

  • 相关阅读:
    DNN SEO专题 (收集)
    DataTable或者DataSet匯出Excel
    用C#制作PDF文件全攻略(转)
    BlogEngine资料收集
    DNN架构解析(收集)
    Community Server:快速找到需要修改的文件[技巧]
    通用的分页存储过程
    DataTable/DataSet汇出Excel
    百试不爽的30条职场经验(转)
    等宽字体
  • 原文地址:https://www.cnblogs.com/dayin1/p/15667282.html
Copyright © 2011-2022 走看看