Lianer

Dependencies

这个项目的主要两大功臣:

ImageMagick

ImageMagick是一套功能强大、稳定而且开源的软件,可以用来读、写和处理超过89种基本格式的图片文件,包括流行的TIFF、JPEG、GIF、 PNG、PDF以及PhotoCD等格式。

ImageMagick通过命令行处理图片,使用方法 http://www.imagemagick.org/script/convert.php

ImageMagick在PHP,JAVA,Nodejs等服务中应用广泛。

在Ubuntu中安装

sudo apt install imagemagick

在Windows中安装

从官网下载安装 http://imagemagick.org/script/binary-releases.php#windows

安装在D:/ImageMagick-7.0.3-Q16

ImageMagick 7.0 以上版本需要勾选 Install legacy utilities

gm

在nodejs中,我们通过gm来操作ImageMagick

安装gm

npm install gm

新建一个演示文件 convert-demo.js

var path = require('path')
var gm = require('gm').subClass({
	imageMagick: true,  // 使用imageMagick,默认使用GraphicsMagick(imageMagick的分支)
	appPath: 'D:/ImageMagick-7.0.3-Q16/',  // Linux下省略,Windows下需指定ImageMagick路径,与系统自带的命令有冲突,以/结尾
})

gm(300, 300, '#ccc')  // 画布大小、背景色
	.gravity('Center')  // 文字上下、左右居中
	.pointSize(40)  // 文字大小
	.fill('#666')  // 填充颜色
	.drawText(0, 0, 'Hello Lianer')
	.write('a.png', function (err, stdout, stderr, command) {
		if(err){
			throw err
		}
		console.log(command)
	})

执行。windows下需要使用管理员权限启动命令行工具,否则ImageMagick可能会抛异常

node ./convert-demo.js

这时,一张漂亮的图片就生成了。

Express

ImageMagick配置成功后,我们就可以开始部署应用了。

使用Express生成一个项目,这里贴一段路由中的代码。

router.get(/^\/(?:(\d{1,4})x(\d{1,4}))\/?/i, function (req, res, next) {
	var width = req.params[0]
	var height = req.params[1]
	var bg = req.query.bg || 'ccc'
	var fg = req.query.fg || '666'

	// 目标文件位置
	var outputPath = path.join(CACHE_ROOT, `${width}x${height}_${bg}_${fg}.png`)

	fs.exists(outputPath, function (exists) {
		// 如果已经存在该文件,则直接响应文件
		if (exists) {
			res.header('Content-Type', 'image/png')
			fs.createReadStream(outputPath).pipe(res)
			return
		}
		convert(width, height, bg, fg, function (err, stdout, stderr, command) {
			if(err){
				return next(err)
			}

			// 写入文件到目标位置
			var cacheStream = fs.createWriteStream(outputPath)
			stdout.pipe(cacheStream)

			res.header('Content-Type', 'image/png')
			// Pipe image data stream to the response
			stdout.pipe(res)

			// Pipe any stdout data to the process.stdout
			// so that it can be retrieved in the logs
			stderr.pipe(process.stdout)
		})
	})
})

Nginx Cache

服务部署到服务器上后,还可以做一层Nginx缓存,减小Nodejs的压力。