欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

使用PHP的GD库生成报告图片

程序员文章站 2022-07-15 10:18:54
...

效果如图:

使用PHP的GD库生成报告图片

需求:1. 姓名,指标,评价文字 是由网页表单 提交给后端;右下角的签名是png 图片;背景是A4大小的图片;

涉及知识点:1.给图片加水印 (签名,对号);

                      2. gd库 输入文本生成图片;

                      3. 选择合适的字体 .ttf格式

难点:1. 文本换行;行末避免单词被拆分为两块(保证单词的完整性)

           2. 生成图片我想保存为 stream  ,而不是保存为图片文件,或输出到浏览器

代码如下:



class ImageHelper{


    /**
     *
//        $tplData = [
//            'id' => 73,
//            'realname' => '孟艳红',
//            'sign_image' => 'http://img.artsa.com/FoLLklIH913rD0shoju5AWuKdIy4',
//            'evaluation' => "a v c d e f \ng h i j k l m n o p q u s t u v x y z A B C D E In view of 中国 the characteristics of sobiglongfasthighwords, Dr. Limo, together with famous music educators of different majors from Eastman, Julia, New England and Berkeley, formed the LBM teaching and research team, jointly developed and formulated seven unique music educatin and study abroad systems, maximized the advantages of LBM overseas resources and guaranteed students. At the same time, we should improve our professional level and better integrate with international music education.",
//            'score' => [
//                ['id'=>1, 'score'=>'5'],
//                ['id'=>2, 'score'=>'4'],
//                ['id'=>3, 'score'=>'3'],
//                ['id'=>4, 'score'=>'2'],
//                ['id'=>5, 'score'=>'1'],
//            ]
//        ];
//        $tpl = 'piano';
     * @param $tpl
     * @param $data   ['score'=>[...], 'realname' => '', 'sign_image'=> '']
     * @param $signFile
     */
    public static function generateReport ($tpl, $data){

        $backgroundFile = Yii::$app->params['report.tpl.'.$tpl];
//        //$backgroundFile = "@common/helpers/FnKgePmQrm_HjCYB-m1QA-ZvI6h9.jpg";
        $signFile = $data['sign_image'];

        $rightFile = Yii::$app->params['report.tpl.rightSymbol'];

        $realnameTtfPath = __DIR__.'/苹方_中等.ttf';
        $ttfPath = __DIR__.'/yizhiqingshu.ttf';


        //指定图片路径
        $src = $backgroundFile;

        //获取图片信息
        $info = getimagesize($src);

        //获取图片扩展名
        $type = image_type_to_extension($info[2],false);

        //动态的把图片导入内存中
        $fun = "imagecreatefrom{$type}";

        $image = $fun($backgroundFile);

        //指定字体颜色
        $col = imagecolorallocatealpha($image,255,0,0,50);
        $textcolor = imagecolorallocate($image, 26, 26, 26);

        //指定字体内容
        $content = static ::autowrap2(24,0, $ttfPath ,$data['evaluation'],1092-19-30); //给右边框一点距离24


        //给图片添加文字
        //imagestring($image,5,20,30,$content,$col);
        // 2 :第一行文字距离边框顶部 4px;
        imagettftext($image, 24, 0, 71+19, Yii::$app->params['report.position'][$tpl]['evaluation_y'] + 24+4, $textcolor, $ttfPath, $content);

        //写 姓名 左下角为基准 6 :为距离底部线的间隙
        imagettftext($image, 28, 0, Yii::$app->params['report.position'][$tpl]['realname'][0], Yii::$app->params['report.position'][$tpl]['realname'][1]-10, $textcolor, $realnameTtfPath, $data['realname']);

        //签名水印
        //2、获取水印图片基本信息
        $signInfo = getimagesize($signFile);
        //3、获取水印图片类型
        $signType = image_type_to_extension($signInfo[2], false);
        //4、在内存创建图像
        $signCreateImageFunc = "imagecreatefrom{$signType}";
        //5、把水印图片复制到内存中
        $signWater = $signCreateImageFunc($signFile);

        //特别处理,设置透明
//        $color=imagecolorallocate($signWater,255,255,255);
//        imagefill($signWater,0,0,$color);
//        imagecolortransparent($signWater,$color);

        $signWidth = $signInfo[0];
        $signHeight = $signInfo[1];


        $standSignHeight = 95;
        $standSignWidth = $standSignHeight/$signHeight*$signWidth;

        //裁剪图片
        $standSign = imagecreatetruecolor($standSignWidth, $standSignHeight);
        imagecopyresampled($standSign, $signWater,0,0,0,0,$standSignWidth,$standSignHeight,$signWidth,$signHeight);


        //6、合并图片
        imagecopymerge($image, $standSign, Yii::$app->params['report.position'][$tpl]['sign'][0] - $standSignWidth, Yii::$app->params['report.position'][$tpl]['sign'][1]-$standSignHeight, 0, 0, $standSignWidth, $standSignHeight, 100);
        //7、销毁水印图片
        imagedestroy($signWater);
        imagedestroy($standSign);

        //对号处理:
        //2、获取水印图片基本信息
        $rightInfo = getimagesize($rightFile);

        //3、获取水印图片类型
        $rightType = image_type_to_extension($rightInfo[2], false);
        //4、在内存创建图像
        $rightCreateImageFunc = "imagecreatefrom{$rightType}";
        //5、把水印图片复制到内存中
        $rightWater = $rightCreateImageFunc($rightFile);

        $position = Yii::$app->params['report.position'];

        foreach($data['score'] as $item){
            if(isset($position[$tpl][$item['id']][$item['score']])){
                $y = $position[$tpl][$item['id']][$item['score']][1];
                $x = $position[$tpl][$item['id']][$item['score']][0];

                imagecopymerge($image, $rightWater, $x+3, $y+4, 0, 0, $rightInfo[0], $rightInfo[1], 100);
            }

        }

        //7、销毁水印图片
        imagedestroy($rightWater);
        ob_start();   //启用输出缓冲
        imagepng($image);    //输出图像
        $imagebin=ob_get_contents();    //将缓冲的数据存入变量
        ob_end_clean();    //结束并清空输出缓存

        imagedestroy($image);



        $res = UploadFromServerHelper::uploadImageFromStream($imagebin);

        //var_dump($res);
        return $res;



    }

    static function chararray($str,$charset="utf-8"){
        $re['utf-8']   = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
        $re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
        $re['gbk']    = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
        $re['big5']   = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
        preg_match_all($re[$charset], $str, $match);
        return $match[0];
    }


    static function charwidth($fontsize,$fontangle,$ttfpath,$char){
        $box = imagettfbbox($fontsize,$fontangle,$ttfpath,$char);
        $width = abs(max($box[2], $box[4]) - min($box[0], $box[6]));
        return $width;
    }


    //$fontsize字体大小 $fontangle字体角度 $ttfpath字体路径 $str字符串 $width指定宽度
    static function autowrap2($fontsize,$fontangle,$ttfpath,$str,$width,$charset='utf-8'){
        $_string_arr = [];
        $strArr = static::chararray($str);
        if(empty($strArr))
            return "";

        reset($strArr);
        do{
            $v = current($strArr);
            $_temp_arr[] = $v;
            $_string_arr[] = $v;
            $_temp = implode('',$_temp_arr);
            $w = static ::charwidth($fontsize,$fontangle,$ttfpath,$_temp);

            if ($w >= $width){

                $_temp_arr = [];

                $endv = $v;


                $word_end_char = "";
                if(next($strArr)){
                    $word_end_char = current($strArr);
                    prev($strArr);
                }
                while(ctype_alpha($endv)  && ctype_alpha($word_end_char)){   //并且不是单词的最后一个字母

                     array_pop($_string_arr);

                     prev($strArr);
                     $endv = current($strArr);
                }

                if(ctype_alpha($endv) && ctype_space($word_end_char)){  //刚好是一个单词结尾,去掉后面的一个空白字符
                    next($strArr);
                }

                $_string_arr[] = "\n";

                //var_dump($w);

            }


        }while(next($strArr));

        $_string = implode('',$_string_arr);
        $_string = mb_convert_encoding($_string, "html-entities","UTF-8" );
        return $_string;



    }





}