123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- <?php
- require_once(__DIR__.'/qrlib.php');
- /*
- //调用示例
- // include_once(APP_PATH.'/extend/phpqrcode/qrcode.php');
- // $qrcode=CreateQRCode('http://www.baidu.com/','400','D:\www\WhatPHPv2019\uploads\images\20190211\1549868835zDfBVGhpEC9893.jpg');
- */
- //创建一个二维码 $data:生成二维码包含的数据 $width:生成二维码的宽度 $title是否在二维码下方加文字 $logofile:生成二维码是否生成加入LOGO $savefile:保存到文件
- function CreateQRCode($data,$width,$title="",$logofile="",$issave=true,$savefile="")
- {
- //二维码图片保存路径(若不生成文件则设置为false)
- $filename = "qrcode_" . time() . ".png";
- //二维码容错率,默认L
- $level = "L";
- //二维码图片每个黑点的像素,默认4
- $size = get_qrcode_size($width);
- //二维码边框的间距,默认2
- $padding = 2;
- //保存二维码图片并显示出来,$filename必须传递文件路径
- $saveandprint = false;
- if($issave==true){
- if($savefile==""){
- $DIR1="/uploads/qrcode/".MyDate('Ymd',time())."/";
- $FILENAME="QR_".time().GetRandStr(20).".jpg";
- $path=ROOT_PATH.$DIR1;
- if(!file_exists($path)){
- mkdir($path,0777,true);
- }
- $savefile=$path.$FILENAME;
- $return_path=$DIR1.$FILENAME;
- }else{
- $return_path="";
- }
- //生成二维码图片
- \QRcode::png($data,$savefile,$level,$size,$padding,$saveandprint);
- if($logofile!=""){
- QRCodeLogo($savefile,$logofile);
- }
- if($title!=""){
- QRCodeTitle($savefile,$title);
- }
- return $return_path;
- }else{
- //生成二维码图片
- \QRcode::png($data,false,$level,$size,$padding,$saveandprint);
- }
- }
- //根据宽度计算二维码大小值
- function get_qrcode_size($w)
- {
- $size=floor($w/29*100)/100 + 0.01;
- return $size;
- }
- //给二维码中加入LOGO,并覆盖到二维码文件中
- function QRCodeLogo($Qrfile,$logofile)
- {
- $QR = imagecreatefromstring(file_get_contents($Qrfile)); //目标图象连接资源。
- $logo = imagecreatefromstring(file_get_contents($logofile)); //源图象连接资源。
- $QR_width = imagesx($QR); //二维码图片宽度
- $QR_height = imagesy($QR); //二维码图片高度
- $logo_width = imagesx($logo); //logo图片宽度
- $logo_height = imagesy($logo); //logo图片高度
- $logo_qr_width = $QR_width / 4; //组合之后logo的宽度(占二维码的1/5)
- $scale = $logo_width/$logo_qr_width; //logo的宽度缩放比(本身宽度/组合后的宽度)
- $logo_qr_height = $logo_height/$scale; //组合之后logo的高度
- $from_width = ($QR_width - $logo_qr_width) / 2; //组合之后logo左上角所在坐标点
- //重新组合图片并调整大小
- //imagecopyresampled() 将一幅图像(源图象)中的一块正方形区域拷贝到另一个图像中
- imagecopyresampled($QR, $logo, $from_width, $from_width, 0, 0, $logo_qr_width,$logo_qr_height, $logo_width, $logo_height);
- //输出图片
- imagejpeg($QR,$Qrfile);
- imagedestroy($QR);
- imagedestroy($logo);
- }
- //在二维码中加入文本
- function QRCodeTitle($Qrfile,$title=""){
- if(!file_exists($Qrfile)){
- return false;
- }
- $place = 40;//边距
- $line_height = 30;//行高
- $fileContent = file_get_contents($Qrfile);
- if(empty($fileContent)){
- return false;
- }
- $QR = imagecreatefromstring($fileContent); //目标图象连接资源。
- $QR_width = imagesx($QR); //二维码图片宽度
- $QR_height = imagesy($QR); //二维码图片高度
- $Img_width = $QR_width;//画布宽度
- $Img_height = $QR_height + $place*2 + $line_height + 20;//画布高度
- $Img = imagecreatetruecolor($QR_width,$QR_height + $place*2 + $line_height);
- //定义可能用到的颜色
- $black=imagecolorallocate($Img,3,3,3);
- $white=imagecolorallocate($Img,255,255,255);
- //用白色填充画布
- imagefill ($Img,0,0,$white);
- //将二维码写入画布
- imagecopyresampled($Img, $QR, 0, 0, 0, 0, $QR_width, $QR_height, $QR_width, $QR_height);
- $pos = [
- 'top' => $QR_height+ $place + 20,//顶部边距
- 'left' => 0,//左边距
- 'line_height'=> $line_height,//行高
- 'width' => $QR_width,//段落宽度
- 'pos' => 'C'//对齐方式
- ];
- //定义字体
- // $font = PathDS(public_path().'static'.DS.'font'.DS.'zh.ttf');
- $font = PathDS(public_path().'static'.DS.'font'.DS.'MSYH.TTC');
- $font = file_exists($font)?$font:__DIR__.DS.'MSYH.TTC';
- // $font = PathDS(public_path().'static'.DS.'font'.DS.'simfang.ttf');
- $txt = [];
- $strNum = 0;
- for($i=0;$i<mb_strlen($title,"UTF-8");$i++){
- $f = mb_substr($title,$i,1,"UTF-8");
- if(preg_match('/[\x{4e00}-\x{9fa5}]/u',$f)>0){
- $strNum+=1.5;//中文宽度是1.5倍字号
- }else{
- $strNum+=1;
- }
- }
- $fontSize = intval(($QR_width)/$strNum);//字号,里面的mb_strlen中文需要乘1.5,英文和数字不用
- $fontSize = $fontSize<=60?$fontSize:60;
- $txt[] = [
- 'content' => $title,//文本内容
- 'font' => $font,//字体
- 'color' => $black,//颜色
- 'fontsize' => $fontSize,// 字号
- 'blod' => false,//加粗
- 'underline' => false//下划线
- ];
- draw_txt_to($Img,$pos,$txt);
- ImageJpeg($Img,$Qrfile,80);
- ImageDestroy($Img);
- }
- /**
- * 文字自动换行算法
- * @param $card 画板
- * @param $pos 段落样式(数组),top顶端的边距,left左边距,line_height行高,widt段落宽度,pos对齐方式:L=左,C=居中,R=右
- * @param $txtArr 文本样式(数组),content文本内容,font字体文件,color颜色,fontsize字号,blod是否加粗,underline是否加下划线
- * @return int 返回段落底部距离画板顶部的高度
- */
- function draw_txt_to($card, $pos,$txtArr)
- {
- //取出段落样式
- $_str_h = $pos["top"];
- $width = $pos["width"];
- $margin_left = $pos["left"];
- $hang_size = $pos["line_height"];
- $pos = $pos['pos'];
- $tp = 0;//行标
- $allline = [];//整理后的行数组
- $all_temp_string = "";
- foreach($txtArr as $key => $sentence){
- $fontsize = $sentence["fontsize"];
- $fontcolor = $sentence['color'];
- $str = $sentence['content'];
- $font_file = $sentence['font']&&file_exists($sentence['font'])?$sentence['font']:'./MSYH.TTC';//解决缺少字体文件时报错的BUG
- $blod = $sentence['blod'];
- $underline = $sentence['underline'];
- $temp_string = "";
- //将文本按宽度分行
- for ($i = 0; $i < mb_strlen($str); $i++) {
- //计算每个文字写入前的宽度和高度:0=左下角X位置,1=左下角Y位置,2=右下角X位置,3=右下角Y位置,4=右上角X位置,5=右上角Y位置,6=左上角X位置,7=左上角Y位置
- $box = imagettfbbox($fontsize, 0, $font_file, $all_temp_string);
- //获得文本宽度
- $_string_length = $box[2] - $box[0];
- //获取下一个字符
- $temptext = mb_substr($str, $i, 1);
- //计算下一个字符写入后的宽度
- $temp = imagettfbbox($fontsize, 0, $font_file, $temptext);
- //字符写入后没有超过规定宽度
- if ($_string_length + $temp[2] - $temp[0] < $width) {
- $temp_string .= mb_substr($str, $i, 1);
- $all_temp_string .= mb_substr($str, $i, 1);
- //如果是最后一个字符
- if ($i == mb_strlen($str) - 1) {
- $allline[$tp][] = ['str'=>$temp_string,'top'=>$_str_h,'color'=>$fontcolor,'fontsize'=>$fontsize,'font_file'=>$font_file,'blod'=>$blod,'underline'=>$underline];
- }
- }
- //一行的字数超过了规定宽度,但字符还没写完;
- else{
- //剩余的开头第一个字;
- $texts = mb_substr($str, $i, 1);
- //判断剩余的开头第一个字是不是符号;
- $isfuhao = preg_match("/[\\\\pP]/u", $texts) ? true : false;
- //如果是标点符号,则添加在第一行的结尾
- if ($isfuhao) {
- $temp_string .= $texts;
- $all_temp_string .= $texts;
- //判断如果是连续两个字符出现,并且两个都是必须放在句末尾的,单独处理
- $f = mb_substr($str, $i + 1, 1);
- $fh = preg_match("/[\\\\pP]/u", $f) ? true : false;
- if ($fh) {
- $temp_string .= $f;
- $all_temp_string .= $f;
- $i++;
- }
- } else {
- $i--;
- }
- $tmp_str_len = mb_strlen($temp_string);
- $s = mb_substr($temp_string, $tmp_str_len-1, 1);//取剩余字符串最后一位字符
- if (is_firstfuhao($s)) {//判断剩余字符串的最后一个字符是不是可以放在前面
- //将最后一个字符用“_”代替。指针前移动一位。重新取被替换的字符。
- $temp_string=rtrim($temp_string,$s);
- $all_temp_string=rtrim($all_temp_string,$s);
- $i--;
- }
- $allline[$tp][] = ['str'=>$temp_string,'top'=>$_str_h,'color'=>$fontcolor,'fontsize'=>$fontsize,'font_file'=>$font_file,'blod'=>$blod,'underline'=>$underline];
- //换行
- $_str_h += ($hang_size - ($hang_size - $fontsize)/2);//计算整个文字换行后的高度。
- $tp++;//行数
- //写完了改行,置null该行的临时字符串。
- $temp_string = "";
- $all_temp_string = "";
- }
- }
- }
- foreach($allline as $hang=>$row){
- //此行的所有字符串
- $rowstr = implode(",",array_column($row,'str'));
- $tmp = imagettfbbox($fontsize, 0, $font_file, $rowstr);
- $marginleft = $margin_left;
- //计算首句左边距
- if($pos=='L'){
- $marginleft = $margin_left;
- }elseif($pos=='R'){
- $marginleft = $margin_left + $width - ($tmp[2] - $tmp[0]);
- }elseif($pos=='C'){
- $marginleft = $margin_left + ($width - ($tmp[2] - $tmp[0])) / 2;
- }
- foreach($row as $sub){
- $tmp = imagettftext($card, $sub['fontsize'], 0, $marginleft, $sub['top'], $sub['color'], $sub['font_file'], $sub['str']);
- if($sub['blod']){
- imagettftext($card, $sub['fontsize'], 0, $marginleft, $sub['top']+1, $sub['color'], $sub['font_file'], $sub['str']);
- imagettftext($card, $sub['fontsize'], 0, $marginleft, $sub['top']-1, $sub['color'], $sub['font_file'], $sub['str']);
- // imagettftext($card, $sub['fontsize'], 0, $marginleft+1, $sub['top'], $sub['color'], $sub['font_file'], $sub['str']);
- // imagettftext($card, $sub['fontsize'], 0, $marginleft-1, $sub['top'], $sub['color'], $sub['font_file'], $sub['str']);
- }
- if($sub['underline']){
- imagefilledrectangle($card,$tmp[0],$tmp[1]+1,$tmp[2],$tmp[3]+3,$sub['color']);
- }
- $marginleft += ($tmp[2] - $tmp[0]);
- }
- }
- return $sub['top'] + $hang_size;
- }
- function is_firstfuhao($str)
- {
- $fuhaos = array("\\", "“", "'", "<", "《",);
- return in_array($str, $fuhaos);
- }
- ?>
|