请在这里查看示例☞ gm示例
安装
GraphicsMagick和ImageMagick的区别
- GraphicsMagick是从ImageMagick中分离出来的,推荐下载ImageMagick
加载GraphicsMagick(大小4.72 MB)
var gm = require('gm')
加载ImageMagick(大小23.8 MB)
var gm = require('gm').subClass({imageMagick: true})// 注意使用的区别
- 除了加载有区别,其他使用方式完全一样
window版本
- 下载imagemagick的window版本(在页面靠下方),如图:
- 双击exe文件,进行安装,安装过程中要注意勾选以下选项
linux版本(ubuntu 16.04)
要点
图片水印
var gm = require('gm').subClass({imageMagick: true})
gm('./public/images/a.png')// 原图路径
.font('./fonts/zhulangyingxingti.ttf')// 配置逐浪硬行体字库路径
.drawText(10, 10, '水印')
.write('./public/images/b.png', function (e) {// 输出的图片路径
if(e) {
console.log(e.message)
}else {
console.log('done')
}
})
drawText()中文乱码
- 字体文件使用中文名称命名,运行时会报错,所以不要使用中文命名
- 如果确保字库引入正确,还出现中文乱码,那一定是字库文件本身有问题,换一种字库就可以了
- 尝试过字库格式ttf、otf均支持
详见:
字库ttf和otf格式有什么区别?
图片验证码
- 准备一张背景杂乱的图片和艺术字体的英文字库
index.html
<img src="/gm/captchaAdd"><!-- 前端通过img标签请求验证码 -->
app.js
var express = require('express') var session = require('express-session') ... var cap = {// 通过函数随机出一个验证码对象,包括文字和在杂乱背景上的位置(这里假如如下) text: 'ab12', pos: [20, 50], } // 生成验证码 app.all('/gm/captchaAdd', function(req, res, next) { var url = './public/images/'+(''+Math.cap()).replace('.', '')+'.png'// 设置验证码的输出路径,且给一个随机文件名 gm('./lib/images/captchaBg.png')// 一张背景杂乱的图片作为验证码的背景 .font('./lib/src/SelfRighteousness-Regular.ttf')// 一种略艺术的英文字库 .fontSize(50)// 设置字体大小 .drawText(cap.pos[0], cap.pos[1], cap.text)// 写入随机的验证码 .crop(100, 40, cap.pos[0], cap.pos[1])// 将相应的文字部分裁剪出来,作为验证码 .noise(1)// 加入噪点 .write(url, function (e) {// 随机一个文件名,并输出验证码 if(e) { console.log(e.message) }else { req.session.captcha = cap// 将验证码对象写入session,用来登录时跟用户输入的作比较 res.download(url)// 这里用download方法发送图片,前端千万不能用ajax方式请求 } }) }) // 用户登录 app.all('/user/login', function(req, res, next) { if(req.body.captcha.toLocaleLowerCase() != req.session.captcha.text.toLocaleLowerCase()) { res.send({message: '验证码不正确'}) }else { ... } })
- 效果如下
- 2. 3.
- 最后可以通过AI开放平台提供的文字识别技术来测试机器识别的效果
- 升级版验证码(参考慕课网)
- 用户使用某个用户名尝试登陆,如果错误,将给该用户名在数据库记录一次错误
- 该用户名错误次数达到3次,要求需等待半小时后才能再次尝试登录该用户名,且必须输入验证码
- 所以当用户来到登录页面时,在输入用户名之后(或从cookie拿到记录的用户名),需要发送一个请求去验证此用户名是否需要输入验证码,如需要,将验证码输入框显示出来
- 这个有个问题就是,其他用户可以通过故意错误的登录某些用户名,来使这些用户名永远处于等半小时的状态,导致永远无法登陆(不过为了用户安全,牺牲一点用户体验也是值得的)
头像裁剪
- 下面我给出4种方式的思路
- 方式1(本篇提供的demo即使用此方法)
- 前端使用上传插件Webuploader来提供上传图片的功能
- 前端使用Jcrop来提供裁剪的位置
- 后端使用gm根据给出的裁剪位置对上传的图片进行裁剪
- 方式2(可以借助jquery-plugins/h5Crop/插件,该插件我会继续完成)
- 前端利用canvas实现裁剪和压缩,将处理后的base64传给后端
- 后端将base64转化成图片,返回给前端进行展示
- 方式3
- 前端把图片传给后端
- 后端压缩处理过之后,返回给前端(附带图片唯一标识)
- 前端使用Jcrop获取图片的裁剪位置,将裁剪位置和图片唯一标识传给后端
- 后端对对应的图片进行裁剪
- 方式4(这个需要借助我的另一个裁剪插件,提供了2种方式进行裁剪,效果跟qq裁剪头像一样,以后会开源)
- 前端裁剪
- 前端通过js对图片进行平移、缩放操作
- 再通过canvas的drawImage方法绘制操作后的图片
- 再通过canvas的toDataURL进行压缩同时获取最终的base64
- 传base64到后端,后端转为图片,返回图片路径,前端进行展示
- 后端裁剪
- 前端通过js对图片进行平移、缩放操作
- 将操作后获取的裁剪参数(裁剪框的大小、缩放的比率、压缩的比率)和图片文件一同传给后端
- 后端对上传的文件进行裁剪,返回图片路径,前端进行展示
- 需使用到的ImageMagick小细节
- 读取本地图片资源
gm('upload\\temp\\crop\\20180601\\49076530-6584-11e8-9542-0d60dcc7daa8.jpg')
) - 读取外链图片资源
gm('http://localhost:3000/upload/temp/crop/20180601/49076530-6584-11e8-9542-0d60dcc7daa8.jpg')
) - 读取base64图片资源
'inline:' + 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBD...'
)(注意不适用超过5000个字符的base64字符串,否则会转换失败) - 为了解决base64过长时ImageMagick处理会失败,我们使用node来转换base64为图片
- 缩放图片传入百分比
gm('xxx.png').resize('50%')
) - 压缩图片传入值
gm('xxx.png').quality(50)
) - 不管是前端canvas压缩还是后端ImageMagick压缩,最后的输出的格式都要是jpeg或jpg,否则压缩后的大小很可能会变大
- 读取本地图片资源
- 效果展示(动图较大,请耐心等待)
- 前端裁剪
- 优缺点对比
- 方式1:后端只要写1个接口(Webuploader对图片可以进行压缩)
- 方式2:兼容性IE>=10,减少后端工作量
- 方式3:适中,后端需要写2个接口(上传图片接口和裁剪图片接口)
- 方式4:编写复杂,但是扩展性好,可自由选择一种方式