Node图片编辑工具gm和sharp
source link: https://www.daguanren.cc/post/Node-tu-pian-bian-ji-gong-ju-gm-he-sharp.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Node图片编辑工具gm和sharp
我们经常会在微信上生成一些个性化的海报,海报中嵌入用户的微信头像和昵称,以及应用的二维码,如下两张海报:
下面先与大家分享如何在后台使用nodejs生成海报。
ps:在后台生成海报有好处也有坏处。相对于前端生成,好处是:由于服务器的配置统一,生成出的海报的尺寸一致,不会有变形的情况;坏处是:由于后台生成需要引入文字包,一般来说普遍不支持emoji表情符号。
先安装gm和sharp这两个图片处理包。
gm和sharp在linux上安装会有权限问题,需要手动创建文件夹。
或者使用如下命令安装:
npm install --unsafe-perm
安装部署方式参考之前的博客
https://www.daguanren.cc/post/promise_graphicsmagick.html
gm的下载地址:
https://sourceforge.net/projects/graphicsmagick/files/graphicsmagick/
以第一张海报图为例,我们讲解代码如何实现。
思路如下:
- 先来直观的看下最终实现的效果图和所需的背景图,就可以大致知道我们要在哪些区域写入文字和拼接图片
- 需要在背景图上拼接一个头像和一个二维码,以及写入昵称(姓名)、手机号、过期日期这些白色文字。由于昵称的长度不固定,所以如果采用上下排布的方式需要对昵称进行居中,比较麻烦,所以稍作调整,采用左右排布的方式。最终效果如本文第一张海报所示
- 接下来各个击破,微信头像可以用通过微信公众号或小程序的api获取,例如公众号的获取用户基本信息
- 获取的头像通常为一个远程的url,例如http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0 我们需要将远程头像下载到本地临时文件夹,以便后续使用sharp和gm进行拼接
- 带参二维码的获取方式也类似,参照生成带参数的二维码api。生成后通过ticket换取二维码的url
// 引入用到的npm包,没安装的先npm install 安装const rp =require('request-promise');const gm = require('gm');const sharp = require('sharp');const fs = require('fs');// 定义请求参数const options = { method: 'GET', uri: img_url, // 头像或二维码地址 encoding: 'binary' // 或者也可以是 null// 发送请求let res = await rp(options);// 生成一串字符串来标记该头像是谁的let variable = think.uuid();// 将图片存到本地临时文件,存在了根目录下的tmp/img/文件夹下await fs.writeFileSync('tmp/img/avatar_'+variable +'.png', res, 'binary');// 头像和二维码均使用此方式存储到本地// 省略.....// 头像存储好了后,由于头像是正方形的,我们要将其改成圆形,并且调整其大小// 使用sharp将头像转成圆角 const roundedCorners = Buffer.from( '<svg><rect x="0" y="0" width="130" height="130" rx="65" ry="65"/></svg>' let sharpStream2 = sharp('tmp/img/avatar_'+ variable +'.png') .resize(130,130) .composite([{input:roundedCorners, blend: 'dest-in'}]) .png()// 将异步的sharpStream2.toFile函数封装下,改成同步let sharpWrite2 = think.promisify(sharpStream2.toFile, sharpStream2);// 将圆形头像存储到临时文件夹await sharpWrite2('tmp/img/circleAvatar_'+ variable +'.png');// 同理,可以对二维码做类似处理// 缩小二维码 let sharpStream = sharp(qrcode_local_path) .resize(193,193) .png() let sharpWrite1 = think.promisify(sharpStream.toFile, sharpStream); await sharpWrite1(qrcode_local_path_output);// 拼接图片和根据坐标点预估位置写入文字let stream = await gm() // 在(0,0)位置处放入背景图 .in('-page', '+0+0') .in(think.ROOT_PATH + '/www/static/image/poster/coupon_template.jpg') // 在(240,138)位置处放入圆形头像 .in('-page', '+240+138') .in('tmp/img/circleAvatar_'+ variable +'.png') // 在(327,987)位置处放入二维码 .in('-page', '+327+987') .in(qrcode_local_path_output) .mosaic() //写完赛日期 .fill('#ffffff') // 加载指定字体 .font("msyh.ttf") .fontSize(30) // 在指定位置写入名字 .drawText(387, 195, decodeURI(name)) // 写手机号 .fill('#ffffff') .font("msyh.ttf") .fontSize(30) .drawText(387, 240, decodeURI(phone)) // 写有效期 .fill('#ffffff') .font("msyh.ttf") .fontSize(20) .drawText(405, 887, decodeURI(coupon.validto.split(" ")[0])) // 保存最终的海报 let gmWrite = think.promisify(stream.write, stream); await gmWrite(qrcode_local_path_output);javascript
至此大功告成,当然代码并不是完整的,这里只是大致介绍。后面还有很多可以优化,例如可以将生成的海报保存下来,以便下次直接使用。下次生成海报的时候可以先判断之前是否已经生成了海报,如果已经生成了,那么直接从数据库把海报的url读取出来。
头像转圆形
https://zhuanlan.zhihu.com/p/137131729
带参二维码
在线免费生成条码:
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK