web实时长图实践--摘抄( 三 )


是从5.5.2 分支出来的,据说它变得更稳定和优秀,更多详情可在官网查看 。
看起来是更好的选择,但是由于node gm这个库没有实现的半透明和圆角支持,而且针对专辑的大事件长图做了一些性能对比两者差异不大,所以选择使用 。
node gm切换的方式非常简单,只要加以下设置:
var gm = require('gm');var imageMagick = gm.subClass({ imageMagick: true });
不可避免的,使用也遇到一些坑:
1.半透明遮罩
设计:专辑封面背景使用白透明遮罩,遮罩的颜色根据封面图来定,深色封面图用白色文字,浅色封面图用黑色文字 。
开发:OK,先获取封面图颜色信息,再判断颜色深浅
//RGB与YUV互转,Y>=128 为浅色Y'= 0.299*R' + 0.587*G' + 0.114*B'U'= -0.147*R' - 0.289*G' + 0.436*B' = 0.492*(B'- Y')V'= 0.615*R' - 0.515*G' - 0.100*B' = 0.877*(R'- Y')R' = Y' + 1.140*V'G' = Y' - 0.394*U' - 0.581*V'B' = Y' + 2.032*U'//ImageMagick设置透明色.fill("rgba(0,0,0,.5)")
2.头像圆角
设计:这些头像要用圆角哦 。
开发:OK(还好支持圆角)
.fill("avatar.jpg").drawCircle(80,120,30,120)
圆角图片实现方式与类似,画一个圆,然后用头像图片去填充来实现头像圆角 。
3.昵称emoji表情
绘制昵称中的表情图比较麻烦,使用支持emoji的字体,尝试过的彩色emoji字体,但是有BUG,不能还原为彩色的 。
最终解决方案:
1)使用等宽字体,方便计算精确的emoji位置
2)绘制昵称中的表情图片
.draw("image Over " + size + " " + url)
性能优化:
优化前:

web实时长图实践--摘抄

文章插图
优化后:
web实时长图实践--摘抄

文章插图
生成单张图片耗时100ms左右,但是并发请求多了平均耗时就暴涨到3S+,这个速度显然是不能接受的,经过一番优化后将平均耗时降到1S左右,主要优化点如下:
1.gm代码拼接,VM中执行
多次调用gm多次操作图片,严重影响性能,将图片操作代码拼接成字符串,在VM中执行,只调用一次gm,核心代码如下:
let sandbox = {gm : imageMagick,start : Date.now()}//计算图片高度let offset = getOffset();let qrcodeStr = getQrcodeStr();let titleStr = (function(){return ['.fontSize(24)','.fill("gray")','.drawText(164,152,"我是标题")'];})();let str = 'gm(828,'+ offset.height +',"#fff").font("'+ FONTS +'",48)'+ titleStr + qrcodeStr +'.quality(90).write("test.jpg",function(err){console.log(err || Date.now() - start)})';let script = new vm.Script(str);let context = vm.createContext(sandbox);script.runInContext(context);
2.mpc格式
mpc是提供的一种持久高速缓存格式,减少对图像格式进行解码和编码像素的开销 。
mpc生成两个文件:
1)一个扩展名.mpc保留了与图像或图像序列相关的所有属性(例如宽度,高度,色彩空间等) 。
2)一个扩展名.cache,是本地原始格式的像素缓存 。
读取mpc图像文件时,读取图像属性,并将内存映射到磁盘上的像素缓存,无需解码图像像素,不过mpc的文件大小比其他图像格式大 。
mpc图像文件适用于一次写入,多次读取模式,使用mpc将图像直接映射到内存,而不是每次重新读取和解压源图像 。
3.Q8版本
Q16版本允许在不缩放的情况下读写16位图像,但像素缓存消耗的资源是Q8版本的两倍,Q8版本的执行速度通常比Q16版本要快 。