使用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;



    }





}

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章