PHP中使用GD扩展库合成图片(文字、图片、LOGO)

[ PHP ] 2020-01-13 20:33:40 杨歆 397
<?php
/**
 * +--------------------------------------------------------------
 * | eLuoPHP
 * +--------------------------------------------------------------
 * | Copyright (c) 2016-2019 http://qxwoo.cn All rights reserved.
 * +--------------------------------------------------------------
 * | y139w [y139w@163.com]
 * +--------------------------------------------------------------
 * | 2019/12/26 16:24
 * +--------------------------------------------------------------
 * | Image.php
 * +--------------------------------------------------------------
 */


namespace gd;


class Image
{

    private static $_instance = null;

    /**
     * @var null
     */
    private static $_image = null;

    /**
     * @var
     */
    private $backgroundImage;

    /**
     * @var array
     */
    private $types = ['gif' => 1, 'jpg' => 2, 'png' => 3];

    /**
     * 保存图片路径
     * @var string
     */
    private $saveImagePath = '';

    public function __construct()
    {
        $this->saveImagePath = dirname($_SERVER['SCRIPT_FILENAME']);
    }

    /**
     * 设置背景图片
     * @param $img
     * @return $this
     */
    public function background($img){

        $this->backgroundImage = $this->imageHandle($img);
        self::$_image = $this->backgroundImage['object'];
        return $this;

    }

    /**
     * @return Image|null
     */
    public static function instance(){

        if(!(self::$_instance instanceof self)){
            self::$_instance = new self();
        }
        return self::$_instance;

    }

    public function merge($content, $options = []){

        $type = isset($options['type']) ? $options['type'] : 'text';
        switch ($type){
            case 'image':
                $this->copyImageHandle($content, $options);
                break;
            case 'text':
            default:
                $this->writeTextHandle($content, $options);
                break;
        }

        return $this;

    }

    /**
     * @param string $type
     * @param bool $save
     * @return string|void|null
     */
    public function output($type = 'png', $save = false){

        if($type == 'debug'){
            return ;
        }
        $savePath = null;
        if(!$save){
            header('Content-Type: image/' . $type . ';charset=utf-8');
        }
        if(is_string($save)){
            $savePath = $this->saveImagePath . '/' . $save;
        }
        switch ($type){
            case 'gif':
                imagegif(self::$_image, $savePath);
                break;
            case 'jpg':
                imagejpeg(self::$_image, $savePath);
                break;
            case 'png':
            default:
                imagepng(self::$_image, $savePath);
                break;
        }
        return $save;

    }

    private function filletHandle($srcImageInfo) {

        $width = $srcImageInfo['width'];
        $height = $srcImageInfo['height'];
        $w   = min($width, $height);
        $h   = $w;
        $img = imagecreatetruecolor($w, $h);
        //这一句一定要有
        imagesavealpha($img, true);
        //拾取一个完全透明的颜色,最后一个参数127为全透明
        $bg = imagecolorallocatealpha($img, 255, 255, 255, 127);
        imagefill($img, 0, 0, $bg);
        $r   = $w / 2; //圆半径
        for ($x = 0; $x < $w; $x++) {
            for ($y = 0; $y < $h; $y++) {
                $rgbColor = imagecolorat($srcImageInfo['object'], $x, $y);
                if (((($x - $r) * ($x - $r) + ($y - $r) * ($y - $r)) < ($r * $r))) {
                    imagesetpixel($img, $x, $y, $rgbColor);
                }
            }
        }
        return $img;
    }

    private function copyImageHandle($image, $options = []){

        $srcImageInfo = $this->imageHandle($image);
        $srcImg = $srcImageInfo['object'];
        $srcWidth = $srcImageInfo['width'];
        $srcHeight = $srcImageInfo['height'];
        $dstX = $options['x'];
        $dstY = $options['y'];
        if(isset($options['fillet']) && $options['fillet']){
            $srcImg = $this->filletHandle($srcImageInfo);
        }
        // 二维码等比例缩放
        $width = isset($options['width']) ? $options['width'] : $srcWidth;
        $height = isset($options['height']) ? $options['height'] : $srcHeight;
        $newImage = imagecreatetruecolor($width, $height);
        $color = imagecolorallocatealpha($newImage, 255, 255, 255, 127);
        imagecolortransparent($newImage, $color);
        imagefill($newImage, 0, 0, $color);
        imagecopyresampled($newImage, $srcImg, 0, 0, 0, 0, $width, $height, $srcWidth, $srcHeight);
        imagecopymerge ( self::$_image, $newImage, $dstX, $dstY, 0, 0, $width, $height, 100 );

    }

    /**
     * 向图片中写文字
     * @param $text
     * @param array $options
     */
    private function writeTextHandle($text, $options = []){

        $size = isset($options['size']) ? $options['size'] : 20;
        $angle = 0;
        $x = isset($options['x']) ? $options['x'] : $size;
        $y = isset($options['y']) ? $options['y'] : $size;
        $color = isset($options['color']) ? $options['color'] : 0;
        $hex2rgb = $this->hex2rgb($color);
        $color = imagecolorallocate(self::$_image, $hex2rgb->r, $hex2rgb->g, $hex2rgb->b);
        $weight = isset($options['weight']) ? $options['weight'] : 'Regular';
        $fontfile = dirname(__FILE__) . '/fonts/PingFang' . ucfirst($weight) . '.ttf'; //PingFangRegular
        $text = $this->toEntities($text);
        imagettftext( self::$_image, $size, $angle, $x, $y, $color, $fontfile, $text );

    }

    private function hex2rgb($hexColor) {

        $color = str_replace('#', '', $hexColor);
        if (strlen($color) > 3) {
            $rgb = [
                'r' => hexdec(substr($color, 0, 2)),
                'g' => hexdec(substr($color, 2, 2)),
                'b' => hexdec(substr($color, 4, 2))
            ];
        } else {
            $color = $hexColor;
            $r = substr($color, 0, 1) . substr($color, 0, 1);
            $g = substr($color, 1, 1) . substr($color, 1, 1);
            $b = substr($color, 2, 1) . substr($color, 2, 1);
            $rgb = ['r' => hexdec($r), 'g' => hexdec($g), 'b' => hexdec($b)];
        }
        $rgb = is_array($rgb) ? (object)$rgb : $rgb;
        return $rgb;

    }

    /**
     * 处理图片得到图片资源对象
     * @param $img
     * @return array
     */
    private function imageHandle($img){

        $object = false;
        $info = [];
        if(file_exists($img) && is_file($img)){
            // 获取背景图片信息
            list($width, $height, $type) = getimagesize($img);
            if(in_array($type, $this->types)){
                switch ($type){
                    case 1:
                        $object = imagecreatefromgif($img);
                        break;
                    case 2:
                        $object = imagecreatefromjpeg($img);
                        break;
                    case 3:
                        $object = imagecreatefrompng($img);
                        break;
                    default:
                        $object = imagecreatefromstring(file_get_contents($img));
                        break;
                }
            }
            $info = [
                'width'  => $width,
                'height' => $height,
                'type'   => $type,
                'object' => $object,
            ];
        }
        return $info;

    }

    /**
     * @param $string
     * @return string
     */
    private function toEntities($string){
        if(!is_string($string)){
            return $string;
        }
        $len = strlen($string);
        $buf = "";
        for($i = 0; $i < $len; $i++){
            if (ord($string[$i]) <= 127){
                $buf .= $string[$i];
            } else if (ord ($string[$i]) <192){
                //unexpected 2nd, 3rd or 4th byte
                $buf .= "&#xfffd";
            } else if (ord ($string[$i]) <224){
                //first byte of 2-byte seq
                $buf .= sprintf("&#%d;",
                    ((ord($string[$i + 0]) & 31) << 6) +
                    (ord($string[$i + 1]) & 63)
                );
                $i += 1;
            } else if (ord ($string[$i]) <240){
                //first byte of 3-byte seq
                $buf .= sprintf("&#%d;",
                    ((ord($string[$i + 0]) & 15) << 12) +
                    ((ord($string[$i + 1]) & 63) << 6) +
                    (ord($string[$i + 2]) & 63)
                );
                $i += 2;
            } else {
                //first byte of 4-byte seq
                $buf .= sprintf("&#%d;",
                    ((ord($string[$i + 0]) & 7) << 18) +
                    ((ord($string[$i + 1]) & 63) << 12) +
                    ((ord($string[$i + 2]) & 63) << 6) +
                    (ord($string[$i + 3]) & 63)
                );
                $i += 3;
            }
        }
        return $buf;
    }

    public function __destruct()
    {
        // TODO: Implement __destruct() method.
        if(self::$_image){
            imagedestroy(self::$_image);
        }
    }

}
支付宝支付
打赏
微信支付

联系我吧

有些人是会淡出你的生活的,有些人刻意不再联系,是因为你知道ta不需要你,或者从一开始就不是同一个初衷在一起度过,不主动联系很久也不见一次面,所有的感情也罢,都会败给时间和距离。因为时间是最无情,给你后悔的时刻却不会给你改过重来的机会。

位置

成都市 四川省 中国

联系电话

028-6406-0000

邮箱

y139w@163.com

企鹅

27572048

网址

https://www.weania.com