需求背景:
在小程序上生成海报图,但在保存图片时,只能保存其中的小程序码图片,保存下来的图片过于单调,且无法确认该图片的作用性,所以需要调整为保存一整张海报图。

海报效果图:

需求分析:
在海报图中,背景图、头像、文字、还有小程序码都是各自独立的部分,我们需要把这些图片合并起来,然后输出为一整张图片,这样就可以直接长按保存图片了。

合并图片可以用以下方法:

  1. 在前端合成,使用画布canvas,把各个元素“画”进去;
  2. 在后端合成,使用插件Grafika,把各个组成部分合并在一起;

因为当前是在小程序开发这个需求,考虑到未来可能会替换海报上的一些文字、图片等情况,而每次修改小程序代码都需要提交版本审核,耗时耗力,所以决定在后端进行图片合成,输出图片到前端。

注意:若背景图片有透明的部分,处理过后,透明部分会变成黑色,在Grafika中暂未找到能合并透明图片的方法,感觉有点坑,不过有搜到说可以直接用gd来合成,有空再研究研究吧。(目前的解决方法是换张白色背景的图片)

使用Grafika

安装:

composer require kosinix/grafika:dev-master --prefer-dist

生成方法

function create($slogan, $avatar, $qr){// 背景图片$bg_img = 'images/qr_code_bg.png';// 实例化图像编辑器$editor = Grafika::createEditor(['Gd']);// 打开海报背景图$editor->open($backdropImage, $bg_img);$bgWidth = $backdropImage->getWidth();// 生成圆形用户头像$avatarUrlName = 'temp/avatar.png';$this->circular($avatar_url, $avatarUrlName);// 打开用户头像$editor->open($avatarImage, $avatarUrlName);// 重设用户头像宽高$avatarWidth = 310;$editor->resizeExact($avatarImage, $avatarWidth, $avatarWidth);// 用户头像添加到背景图$avatarX = 401;$avatarY = 36;$editor->blend($backdropImage, $avatarImage, 'normal', 1.0, 'top-left', $avatarX, $avatarY);// 打开小程序码$editor->open($qrcodeImage, $qr);// 重设小程序码宽高$qrcodeWidth = 430;$editor->resizeExact($qrcodeImage, $qrcodeWidth, $qrcodeWidth);// 小程序码添加到背景图$qrcodeX = 340;$qrcodeY = 720;$editor->blend($backdropImage, $qrcodeImage, 'normal', 1.0, 'top-left', $qrcodeX, $qrcodeY);// 处理文字$color = new Color('#FFFFFF');$fontPath = Grafika::fontsDir() . '/st-heiti-light.ttc';$fontSize = 50;// 处理用户昵称$nicknameBox = $this->get_text_box($nickname, $fontSize, $fontPath);$fontY = 410;$fontX = ($bgWidth / 2) - ($nicknameBox[0] / 2);$editor->text($backdropImage, $nickname, $fontSize, $fontX, $fontY, $color, $fontPath);$str1 = "邀请您注册成为分销员";$strBox1 = $this->get_text_box($str1, $fontSize, $fontPath);$str1x = ($bgWidth / 2) - ($strBox1[0] / 2);$editor->text($backdropImage, "邀请您注册成为分销员", $fontSize, $str1x, $fontY + 100, $color, $fontPath);$str2 = "一起赚佣金";$strBox2 = $this->get_text_box($str2, $fontSize, $fontPath);$str2x = ($bgWidth / 2) - ($strBox2[0] / 2);$editor->text($backdropImage,'一起赚佣金', $fontSize, $str2x, 1220, $color, $fontPath);// 保存图片$editor->save($backdropImage, $qr);
}
  • 使用open()打开图片并获得该图片对象,使用blend()依次合并图片。
  • 在处理头像图片时,需要先指定临时的头像文件,便于后续使用。
  • 添加文字到图片上时text(),Grafika默认的字体不兼容中文,所以需要指定字体文件路径。
// 生成圆形用户头像
function circular($imgpath, $saveName = ''){$ext = pathinfo($imgpath);$srcImg = null;switch ($ext['extension']) {case 'jpg':case 'jpeg':$srcImg = imagecreatefromjpeg($imgpath);break;case 'png':$srcImg = imagecreatefrompng($imgpath);break;}// 获取图片尺寸$w = imagesx($srcImg);$h = imagesy($srcImg);// 设定图片宽高(正方形)$w = $h = min($w, $h);$newImg = imagecreatetruecolor($w, $h);// 必须imagesavealpha($newImg, true);// 拾取一个完全透明的颜色,最后一个参数127为全透明$bg = imagecolorallocatealpha($newImg, 255, 255, 255, 127);imagefill($newImg, 0, 0, $bg);$r = $w / 2; //圆半径for ($x = 0; $x < $w; $x++) {for ($y = 0; $y < $h; $y++) {$rgbColor = imagecolorat($srcImg, $x, $y);if (((($x - $r) * ($x - $r) + ($y - $r) * ($y - $r)) < ($r * $r))) {imagesetpixel($newImg, $x, $y, $rgbColor);}}}// 输出图片到文件imagepng($newImg, $saveName);// 释放空间imagedestroy($srcImg);imagedestroy($newImg);
}
  • 方法的大概思路是:创建一个正方形的透明图片,通过循环,把透明图片上的圆形部分的像素点画上(替换)头像图片对应的像素点,此时得到的图片就是一个圆形的头像图片。
  • 方法中使用了imagecreatetruecolor(),创建真彩图像。此时需要保证使用的图片位数>24(图片文件>属性>详细信息>位深度),否则无法渲染图像成功,结果得到的图片是黑色的。
  • 除了使用php内置函数实现圆形图片外,还可以安装Imagick扩展,更方便。
// 获取字符串宽高
function get_text_box($text, $size, $font){$point = imagettfbbox($size, 0, $font, $text);$width = $point[4] - $point[6];$height = $point[1] - $point[7];return [$width, $height];
}
  • 使用imagettfbbox()来获取字符串所在的坐标轴,从而可以拿到字符串文本框的宽高,把字符串居中合并到背景图上。

因为目前无法生成用于前端展示的透明背景的图片,所以改成前端展示的还是一个弹窗,弹窗上添加一个长按事件,触发下载合成海报图片到用户相册

// 长按点击事件
downloadQrCode(){wx.showLoading({title: "加载中",mask: true});if(this.data.download_qr_code){this.downloadSaveImage(this.data.download_qr_code);}else{        App._get("user/download_agent_qr_code", {}, (result) => {if(!result.res){wx.showToast({ icon: 'none', title: result.msg });return false;}this.setData({download_qr_code: result.data.url});this.downloadSaveImage(result.data.url);}, null, (res) => {wx.hideLoading();});}
},
/*** 下载图片,并保存到用户相册* @param {string} url 图片地址*/
downloadSaveImage(url){wx.getImageInfo({src: url,success: function (ret) {var path = ret.path;wx.saveImageToPhotosAlbum({filePath: path,success(result) {wx.hideLoading();wx.showToast({ icon: 'none', title: "已保存图片到相册" });},fail(result) {wx.hideLoading();if(result.errMsg.indexOf("saveImageToPhotosAlbum:fail auth deny") !== -1){wx.showToast({ icon: 'none', title: "请允许小程序“保存图片到相册”" });}console.log(result)}});},fail: function(result){wx.hideLoading();console.log(result)}});
},
  • App._get() 为发送get请求公共方法

参考:
Grafika官方文档
PHP 将图片切成圆角

PHP使用Grafika合成图片,生成海报图相关推荐

  1. 前端生成海报图:html2canvas 生成海报图/网页html转图片

    html2canvas 生成海报图 <html><head> <title>生成海报图Demo</title> </head><bod ...

  2. html2canvas手机黑屏,html2canvas 生成海报图 开发中遇到的问题

    ios里,生成的图片不显示 canvas.toDataURL('image/jpeg', 1.0) 使用image/jpeg格式,在指定图片格式为 image/jpeg 或 image/webp的情况 ...

  3. uniapp app端使用html2canvas和renderjs实现生成海报图

    uniapp app端使用html2canvas和renderjs实现生成海报图 原本app端是无法使用html2canvas的因为,app端不支持浏览器js. 不过我在uniapp里面看到了rend ...

  4. tp5.0 FAST 生成海报图

    推销部门的海报,大致类容都差不多,经常会修改一些简介,诊疗范围,擅长病种等等,刚开始想到的是利用扩展截图然后去下载,网上的例子倒是不多,目前有两个例子 zyan/url2pic-sdk CSDN地址 ...

  5. android 照片拼接长图_Android拼接合并图片生成长图-阿里云开发者社区

    Android拼接合并图片生成长图 代码实现合并两张图片,以第一张图片的宽度为标准,如果被合并的第二张图片宽度和第一张不同,那么就以第一张图片的宽度为准线,对第二张图片进行缩放. 假设根目录的Pict ...

  6. 微信小程序canvas合成图片(海报),生成的图片展示不出来,或者空白。

    背景: 1.用户点击分享朋友圈,将二维码与一张背景图合成一张图片,然后将其显示. 2.用户点击保存图片将图片保存到手机相册里面. 问题: 用户点击分享盆友圈合成后的图片显示空白.控制台可以打印出来链接 ...

  7. vue- canvas生成海报图

    此图为生成的海报图. git链接:https://github.com/sunniejs/vue_canvas_poster 1.通过cnpm安装 cnpm i vue-canvas-poster - ...

  8. 在微信小程序中实现生成海报图并保存到相册

    效果图镇楼: 技术依赖: 弹窗 (vant-weapp 提供的 van-popup 组件) 海报图 (wx-canvas-2d 工具) 弹窗组件的使用方式可以点击上面链接查看,本篇主要讲解海报图绘制方 ...

  9. vue-canvas生成海报图

    此图为生成的海报图. git链接:https://github.com/sunniejs/vue_canvas_poster 文档:https://sunniejs.github.io/vue-can ...

最新文章

  1. 转:C#使用Log4Net记录日志
  2. 【造轮子】打造一个简单的万能Excel读写工具
  3. git rebase -i 修改提交
  4. 1135 Is It A Red-Black Tree (30 分)【难度: 难 / 知识点: 红黑树 未完成】
  5. 没有bug队——加贝——Python 练习实例 35,36
  6. 她,18岁,李飞飞三度公开表扬,高中时NIPS获奖,创造「AI手术教练」
  7. JavaScript:如何将消息打印到错误控制台?
  8. zabbix---agent安装
  9. python行业中性_燃爆!17行Python代码做情感分析?你也可以的
  10. 计算机定时关机命令,电脑定时关机怎么设置_电脑定时关机命令
  11. 操作系统(1) 操作系统概念
  12. ANSYS APDL入门教程
  13. ch2 gpio应用:Buzzer封装
  14. mac关闭和开启启动声
  15. .podSpec文件相关知识整理
  16. echarts3.0 markline 最大值 最小值 均值 方差 标准差 包络 正态分布
  17. Oracle算老几?敢用甲骨文这个名字自居?
  18. SRC小技巧:批量查询网站权重
  19. MacOS XPC的使用入门
  20. 基于Tiny-51操作系统的51单片机温度测控系统设计

热门文章

  1. wordpress 主机_好的WordPress主机的10个基本功能
  2. Python+opencv学习记录6:模糊操作
  3. App inventor小画板
  4. 三分钟热度的人,无法过上自律的生活
  5. CSDN和MSDN名字分析
  6. 算法图解第一章——算法简介
  7. python小波分析,频率普分析——代码修改
  8. 分享一个web旋转正方体动画及源码
  9. 猿创征文|OpenCV编程——计算机视觉的登堂入室
  10. comsol圆柱形永磁体_几组特殊形状永磁体的磁场及梯度COMSOL分析