在node.js中,可以通过GraphicsMagic进行图片操作,那么,首先,我们就来安装GraphicsMagic:
参考资料:GraphicsMagick在mac系统上的用brew的装配
这里简单对安装方式进行一下说明
流程如下:
安装jpeg包 brew install libjpeg
安装jasper包 brew install jasper
安装libpng brew install libpng
安装freetype包 brew install freetype
安装GraphicsMagick 自动安装:brew install GraphicsMagick
如果想要重新安装,就把 install 命令换成 reinstall 即可 。
下面开始进行代码逻辑的编写:
首先,引用gm库,然后,定义一个背景图片,暂时就叫做bg.png吧,然后,找到几张图片,放到1个数组中,我这里随便找了一些图片,数据如下:
fileNames = [ '+.png',',.png', '-.png', '0.png', '1.png', '2.png', '3.png', '4.png', '5.png', '6.png', '7.png', '8.png', '9.png', 'W.png', '?.png' ];
这里可以随便设置,只要存在这个图片即可。
然说,找到一张背景图bg.png,我这里找到了一个大小是1x1的黑色图片,然后,通过这个bg.png生成一张bg1.png图片,再把fileNames对应的图片绘制到bg1.png上面。下面附上生成bg1.png的代码逻辑:
var gm = require("gm");
gm("bg.png")
.resize(1024, 1024, "!")
.noProfile()
.write("bg1.png", (error) => {
if (error) {
console.log("背景图生成失败" + error);
return;
}
});
这里的resize,就是说把读取的bg.png图片设置成1024x1024的大小,这个"!",表示强制设置大小,也就是说,原图片可能会被拉伸。noProfile是移出图片的配置文件,这个,我也说不太清楚。
当这些操作执行完了之后,再直接调用write方法,就可以在同级目录下,生成一张bg1.png图片了。
接下来,我们说一下,怎么把这些图片,合到bg1.png上面,这里,实际上要调用gm的一个draw方法。
如果我们要把1.png绘制到bg1.png上,就执行这个方法就行
var gm = require("gm");
gm("bg1.png")
.draw("image Over 0, 0, 80, 100,'1.png'")
.write("bg1.png", (error) => {
if (error) {
console.log("绘制合图失败");
return;
}
})
这里的.draw是进行绘制操作,然后,这个.write跟上面是一致的,表示生成bg1.png文件。此外,字符串中有5个参数,前面的2个0表示1.png的左上角相对于bg1.png的左上角的x、y坐标,第三个参数80表示图片宽度是80,第4个参数100表示1.png的高度,最后一个参数1.png就不用说了,就是我们要在bg1.png上绘制的那个图片。
如果我们想要把2个图片,绘制到bg1.png上,那么,我们可以按照如下方式操作:
var gm = require("gm");
gm("bg1.png")
.draw("image Over 0, 0, 80, 100,'1.png'")
.draw("image Over 80, 100, 30, 40,'2.png'")
.write("bg1.png", (error) => {
if (error) {
console.log("绘制合图失败");
return;
}
})
那么,有的时候,我们不可能只是想要绘制固定个图片,因此,我们要用下面的方式来实现:
var gm = require("gm");
let fileNames = [ '+.png',',.png', '-.png', '0.png', '1.png', '2.png', '3.png', '4.png', '5.png', '6.png', '7.png', '8.png', '9.png', 'W.png', '?.png' ];
let func = gm("bg1.png");
let x = 0;
let y = 0;
let sizeCount = 0;
let width = 80;
let height = 100;
for (let i = 0; i < fileNames.length; i++) {
let imageName = fileNames[i];
let str = "image Over " + x + ", " + y + ", " + i * width + ", " + i * height + ",'" + imageName + "'";
x += width;
y += height;
func.draw(str);
}
func.write("bg1.png", (error) => {
if (error) {
console.log("绘制合图失败");
return;
}
})
这样写的,就相当于是我们先获取了gm(“bg1.png”)这个方法,将他赋给func
let func = gm("bg1.png");
然后,再反复执行 func.draw(drawStr)方法,依次将图片绘制到bg1.png上,直到最后1个绘制完成之后,再执行func.write()方法。
到这里,基本上算是实现了我们的一个阶段性目标。但是,还有一个严重的问题,我们不可能每次在执行操作的时候,都提前知道图片的大小,所以,最好是能动态计算图片大小,然后动态填充,这样更合理一些。下面给出计算图片大小的处理方式:
gm("1.png")
.size((error, size) => {
console.log("w=" + size.width + " h=" + size.height);
});
这样就获取到了图片的宽度。但是,获取图片大小,是个异步回调,因此,这里考虑等待所有的图片的size都计算好了之后,才做合图操作。
var fileNames = [ '+.png',',.png', '-.png', '0.png', '1.png', '2.png', '3.png', '4.png', '5.png', '6.png', '7.png', '8.png', '9.png', 'W.png', '?.png' ];
var fileSizes = [];
// 计算图片的大小
function foreachDrawImage() {
let sizeCount = 0;
for (let i = 0; i < fileNames.length; i++) {
let imageName = fileDir + "/" + fileNames[i];
gm(imageName)
.size((error, size) => {
fileSizes[i] = size;
sizeCount += 1;
// 所有图片的大小都计算完了,才去绘制图片,并生成fnt文件
if (sizeCount == fileNames.length) {
drawImage();
}
});
}
}
// 绘制图片
function drawImage() {
let func = gm("bg1.png");
let x = 0;
let y = 0;
let sizeCount = 0;
for (let i = 0; i < fileNames.length; i++) {
let imageName = fileNames[i];
let size = fileSizes[i];
let str = "image Over " + x + ", " + y + ", " + size.width + ", " + size.height + ",'" + imageName + "'";
x += size.width;
y += size.height;
func.draw(str);
}
func.write("bg1.png", (error) => {
if (error) {
console.log("绘制合图失败");
return;
}
})
}
最后,生成的图片效果图如下: