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

海报效果图:

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

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

  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. 摄像头ISP系统原理(上)
  2. HDU2544(Dijstra算法)
  3. [转载]MVC、MVP以及Model2(上)
  4. 有助于建立使用者对套件的信任 GitHub释出管理服务
  5. MFC中显示一张位图
  6. 大家推荐一下开源的博客和论坛整合在一起的.net系统
  7. 南昌大学c语言程序设计,南昌大学C语言程序设计试卷C语言2.doc
  8. 六问阿里云计算安全,全面解析阿里云ECS服务器的计算安全进化之路
  9. 一般的病毒通过注册表自启动的方式不断完善中。。。。
  10. Unity3D设置天空盒skybox
  11. PR短视频转场预设 60个摇晃抖动效果过渡合集
  12. Power BI的基本操作
  13. function func() { for(var i=0; i<3; i++) { setTimeout(()=>{ consol
  14. iphone应用隐私政策_如何在iPhone上“隐藏”联系人以获得更大的隐私
  15. java 虚函数_Java的虚方法
  16. 一键体验安全快捷外贸收款服务,PingPong福贸满足你的个性化需求
  17. 计算机重启后桌面文件全部丢失,蓝屏后桌面文件丢失,电脑蓝屏桌面文件丢失...
  18. 2022年湖北省大学生电子设计竞赛A题(单项交流电子负载)赛后总结
  19. 如何批量提取文件名到excel表
  20. u盘数据丢失可以恢复吗?教你3种轻松把u盘数据恢复的方法

热门文章

  1. 英文版 vs2010 做安装包
  2. 全国(不包括港澳台)行政区划代码爬取
  3. Android技术点增长
  4. AI取代人类作战还为时尚早
  5. 弗洛伊德算法学习(Java)
  6. mysql学习之旅途(六)
  7. Grafana Labs线上交流问卷调查
  8. 大灰狼的故事-坚持刷牙的大灰狼
  9. 五到十分钟java演讲_TED演讲 | 一切只需要十分钟的专注
  10. 3.3 设银行定期存款的年利率rate为2.25%,已知存款期为n年,存款本金为capital元,试编程计算并输出n年后的本利之和deposit