微信公众号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);
I can see a bigger world.