微信公众号PHP生成二维码海报的几个小扩展

最近有一个小任务是生成海报 - 以供用户分享引流,无奈对GD库并不熟悉,只得网上找轮子,其中涉及到的问题有:

1、二维码添加到海报背景图之中

PHP操作图片使用GD库,添加文字以及图片:

 

<?php

/**
 * 生成宣传海报
 * @param array  参数,包括图片和文字
 * @param string  $filename 生成海报文件名,不传此参数则不生成文件,直接输出图片
 * @return [type] [description]
 */
function createPoster($config=array(),$filename=""){
    //如果要看报什么错,可以先注释调这个header
    if(empty($filename)) header("content-type: image/png");
    $imageDefault = array(
        'left'=>0,
        'top'=>0,
        'right'=>0,
        'bottom'=>0,
        'width'=>100,
        'height'=>100,
        'opacity'=>100
    );
    $textDefault = array(
        'text'=>'',
        'left'=>0,
        'top'=>0,
        'fontSize'=>32,       //字号
        'fontColor'=>'255,255,255', //字体颜色
        'fontPath' => 'arial.ttf',
        'angle'=>0,
    );
    $background = $config['background'];//海报最底层得背景
    //背景方法
    $backgroundInfo = getimagesize($background);
    $backgroundFun = 'imagecreatefrom'.image_type_to_extension($backgroundInfo[2], false);
    $background = $backgroundFun($background);
    $backgroundWidth = imagesx($background);  //背景宽度
    $backgroundHeight = imagesy($background);  //背景高度
    $imageRes = imageCreatetruecolor($backgroundWidth,$backgroundHeight);
    $color = imagecolorallocate($imageRes, 0, 0, 0);
    imagefill($imageRes, 0, 0, $color);
    // imageColorTransparent($imageRes, $color);  //颜色透明
    imagecopyresampled($imageRes,$background,0,0,0,0,imagesx($background),imagesy($background),imagesx($background),imagesy($background));
    //处理了图片
    if(!empty($config['image'])){
        foreach ($config['image'] as $key => $val) {
            $val = array_merge($imageDefault,$val);
            $info = getimagesize($val['url']);
            $function = 'imagecreatefrom'.image_type_to_extension($info[2], false);
            if($val['stream']){   //如果传的是字符串图像流
            $info = getimagesizefromstring($val['url']);
            $function = 'imagecreatefromstring';
            }
            $res = $function($val['url']);
            $resWidth = $info[0];
            $resHeight = $info[1];
            //建立画板 ,缩放图片至指定尺寸
            $canvas=imagecreatetruecolor($val['width'], $val['height']);
            imagefill($canvas, 0, 0, $color);
            //关键函数,参数(目标资源,源,目标资源的开始坐标x,y, 源资源的开始坐标x,y,目标资源的宽高w,h,源资源的宽高w,h)
            imagecopyresampled($canvas, $res, 0, 0, 0, 0, $val['width'], $val['height'],$resWidth,$resHeight);
            $val['left'] = $val['left']<0?$backgroundWidth- abs($val['left']) - $val['width']:$val['left'];
            $val['top'] = $val['top']<0?$backgroundHeight- abs($val['top']) - $val['height']:$val['top'];
            //放置图像
            imagecopymerge($imageRes,$canvas, $val['left'],$val['top'],$val['right'],$val['bottom'],$val['width'],$val['height'],$val['opacity']);//左,上,右,下,宽度,高度,透明度
        }
    }
    //处理文字
    if(!empty($config['text'])){
        foreach ($config['text'] as $key => $val) {
            $val = array_merge($textDefault,$val);
            list($R,$G,$B) = explode(',', $val['fontColor']);
            $fontColor = imagecolorallocate($imageRes, $R, $G, $B);
            $val['left'] = $val['left']<0?$backgroundWidth- abs($val['left']):$val['left'];
            $val['top'] = $val['top']<0?$backgroundHeight- abs($val['top']):$val['top'];
            imagettftext($imageRes,$val['fontSize'],$val['angle'],$val['left'],$val['top'],$fontColor,$val['fontPath'],$val['text']);
        }
    }
    //保存到本地
    $res = imagejpeg ($imageRes,$filename,90);
    imagedestroy($imageRes);
    if(!$res) return false;
    return $filename;
}

$config = array(
        'image'=>array(
            array(
                'url'=>'qrcode.png',     //二维码资源
                'stream'=>0,
                'left'=>264,
                'top'=>800,
                'right'=>0,
                'bottom'=>0,
                'width'=>225,
                'height'=>225,
                'opacity'=>100,
            ),
            array(
                'url'=>'top.jpg',     //用户头像
                'stream'=>0,
                'left'=>50,
                'top'=>50,
                'right'=>0,
                'bottom'=>0,
                'width'=>100,
                'height'=>100,
                'opacity'=>100,
            ),
        ),
        'text'=>array(
            array(
                'text'=> 'rookie',
                'left'=> 48,
                'top'=>183,
                'fontSize'=>22,       //字号
                'fontColor'=>'255,255,255', //字体颜色
                'angle'=>0,
                'fontPath'=> __DIR__.'/simsun.ttf',//当前文件下的字体,注意要支持中文哦,否则会乱码的
            )
        ),
        'background'=>'poster_bg.jpg'          //背景图
    );

// 开始生成图片
createPoster($config,'new.jpg');

2、将微信头像转为圆形

<?php
/**
    * 将图片转为圆形
    * @param [string] $img 原始图片地址
    * @param [string] $save_img 生成后的圆形图片存储路径
    * @author xu
    * @copyright 2018-11-14
*/
function circular_img($img,$save_img){
    $ext=pathinfo($img);
    $src_img = null;
    switch ($ext['extension']) {
        case 'jpg':
            $src_img=imagecreatefromjpeg($img);
            break;
        case 'png':
            $src_img=imagecreatefrompng($img);
            break;
    }
    $wh= getimagesize($img);
    $w=$wh[0];
    $h=$wh[1];
    $w=min($w,$h);
    $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; //圆半径
    $y_x = $r; //圆心X坐标
    $y_y = $r; //圆心Y坐标
    for ($x = 0; $x < $w; $x++) {
        for ($y = 0; $y < $h; $y++) {
            $rgbColor = imagecolorat($src_img, $x, $y);
            if (((($x - $r) * ($x - $r) + ($y - $r) * ($y - $r)) < ($r * $r))) {
                imagesetpixel($img, $x, $y, $rgbColor);
            }
        }
    }
    imagejpeg ($img,$save_img,90);
    imagedestroy($img);
    return true;
}

$res = circular_img('old.jpg','new.jpg');
var_dump($res);

3、往微信公众平台生成的二维码中间加入公众号logo

 

<?php

/**
    * 二维码内部新增LOGO
    * @param  [string] $QR 二维码地址 
    * @param  [string] $logo 公众号logo
    * @param  [string] $save_img 存储地址
    * @return 已订阅返回true 没有订阅返回false
*/
function createQRLogo($QR,$logo,$save_img) {
    $errorCorrectionLevel = 'L';//容错级别 
    $matrixPointSize = 6;//生成图片大小 
    $QR = imagecreatefromstring(file_get_contents($QR)); 
    $logo = imagecreatefromstring(file_get_contents($logo)); 
    $QR_width = imagesx($QR);//二维码图片宽度 
    $QR_height = imagesy($QR);//二维码图片高度 
    $logo_width = imagesx($logo);//logo图片宽度 
    $logo_height = imagesy($logo);//logo图片高度 
    $logo_qr_width = $QR_width / 5; 
    $scale = $logo_width/$logo_qr_width; 
    $logo_qr_height = $logo_height/$scale; 
    $from_width = ($QR_width - $logo_qr_width) / 2; 
    //重新组合图片并调整大小 
    imagecopyresampled($QR, $logo, $from_width, $from_width, 0, 0, $logo_qr_width, 
    $logo_qr_height, $logo_width, $logo_height); 
    //保存图片 
    imagejpeg ($QR,$save_img,90);
    imagedestroy($QR);
    return true;
}

createQRLogo('qrcode.png','logo.jpg','new.jpg');

4、远程下载图片到本地

/**
    * 下载远程文件到本地
    * @param [string] $url 文件远程地址
    * @param [string] $file_path 文件本地存储路径
    * @author xu
    * @copyright 2018-11-14
*/
function download($url, $file_path)
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    $file = curl_exec($ch);
    curl_close($ch);
    $handle = @fopen($file_path, 'a');
    fwrite($handle, $file);
    fclose($handle);
}
$images = [
  'http://thirdwx.qlogo.cn/mmopen/abc.png',
];

foreach ( $images as $url ) {
  download($url,'a.jpg');
}

5、PHP启用gzip输出 - 有时候输出的页面非常大会自动分块chunked不如压缩以后传输会更快,如果页面5m采用gzip的话可以变位1m左右

<?php
// 将文本gz压缩后缓存起来输出 - 静态化常用
$str = 'abc';
$gz = gzopen ('tmp.gz','w9' );
gzwrite ($gz,$str);
gzclose ($gz);
header("Content-Encoding: gzip");
header("Vary: Accept-Encoding");
echo file_get_contents('tmp.gz');
die;


// 字符串直接压缩后输出
$str = 'abc';
$str = gzencode($str,9);
header("Content-Encoding: gzip");
header("Vary: Accept-Encoding");
echo $str;

6、PHP提前输出结果 - 微信服务器在限定时间内未收到响应会重复发送请求 - 生成图片比较慢的话就要提前输出空字符串避免微信服务器重试

<?php

// 提前输出
ob_end_clean();
header("Connection: close");
header("HTTP/1.1 200 OK");
// 如果前端要的是json则添加,默认是返回的html/text
header("Content-Type: application/json;charset=utf-8");
ob_start();
echo 'hello world.';// 防止微信服务器重复请求
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush();
flush();
if (function_exists("fastcgi_finish_request")) { 
    fastcgi_finish_request(); 
}


// 在关闭连接后,继续运行php脚本
ignore_user_abort(true);
set_time_limit(0);

sleep(100);

 

posted @ 2018-11-14 10:15  许伟强  阅读(3461)  评论(0编辑  收藏  举报