使用Tengine+Lua+GraphicsMagick实现图片自动裁剪缩放
—爱旅行项目
随着互联网的快速发展、需求频繁变更、内容数量的俱增、时间的持续增长,图片数量也会越来越多。在实际需求中,会出现在若干个页面或同一个页面不同位置,展示同一条信息以及其缩略图。此时若使用CSS 控制图片显示的大小,对于一些与该位置不成比例的图片,缩小后就会出现图片变形,并且也不可能让 UI 对所有的图片进行 PS,特别是当一张图需要多种比例尺寸,这样会产生巨大的工作量。基于这种情况就产生了强烈的自动化裁剪、缩放图片的需求,来适应不同规格的缩略图。那么针对作为一个旅游电商类网站:爱旅行项目,页面中有大量的图片加载,图片也是非常重要的一项页面内容,并且随之移动端的加入,考虑页面的响应速度,图片的加载速度,以及节省用户流量等等系统性能方面,都需要页面初始加载不再使用原图,而是根据不同比例需求等比缩放的小图。所以要实现该非功能性需
求,我们的解决方案是使用 Tengine+Lua+GraphicsMagick 来实现图片自动裁剪缩放。 补充说明:Nginx 虽然有自带的image filter module 也可实现此功能,但是存有弊端,所以我们不推荐。
1> image filter module 使用的是 GD,但是 GD 性能、效率以及处理后的图片质量都不
如 GraphicsMagick
2> image filter module 没法真正生成裁剪/缩放后的图片,而是通过 Nginx 直接输出的,
这样每次请求或缓存过期后都需要重新裁剪/缩放,这样无疑会增加Nginx 负担。
1. Tengine
1>淘宝的 Nginx,集成了lua 模块,若要是使用官方的 Nginx,默认安装没有 lua 模块,自己安装配置较为麻烦,所以我们选择 Tengine。Tengine 主要负责展示图片和调度 Lua 脚本
2>安装包:tengine-master.zip
3>下载地址:https://github.com/alibaba/tengine
2. Lua
1>脚本语言,可以方便的嵌入到应用程序中,提供灵活的扩展和定制功能。具体运用主要是嵌入到Tengine 中,方便 Tengine 通过 Lua 实现对 GM 操作,并通过 Lua脚本控制裁剪、缩放规格。
2>安装包:lua-5.3.1.tar.gz、LuaJIT-2.0.4.tar.gz(Lua 依赖包)
3>下载地址:http://www.lua.org/ftp/
http://luajit.org/download.html
3. GraphicsMagick
1>强大的图片处理工具,没有 UI 的 PS,动态的生成图片,特别适用于互联网的应用。GM 负责对图片的处理(裁剪、等比缩放、增加特效等等)
2>安装包:GraphicsMagick-1.3.18.tar.gz
3>下载地址:https://sourceforge.net/projects/graphicsmagick/files/graphicsmagick/
4. 依赖包和类库,可 yum 安装
1>libjpeg、libjpeg-devel
2>libpng、libpng-devel
3>giflib、giflib-devel
4>freetype、freetype-devel
安装过程不再赘述,安装后的路径:
1>/usr/local/Tengine 2> /usr/local/GraphicsMagick
安装过程强调两点:
1. 安装顺序: 1、GraphicsMagick 2、Lua 3、Tengine
2. 安装 Tengine 时,进入 Tengine 源码目录,使用 configure配置安装路径以及需要安装的模块:
1> ./configure --prefix=/usr/local/Tengine --dso-path=/usr/local/Tengine/modules
--with-http_realip_module--with-http_gzip_static_module --with-http_stub_status_module--with-http_concat_module
--with-http_lua_module --http-proxy-temp-path=/var/tmp/Tengine/proxy_temp
--http-fastcgi-temp-path=/var/tmp/Tengine/fastcgi_temp--http-uwsgi-temp-path=/var/tmp/Tengine/uwsgi_temp
--http-scgi-temp-path=/var/tmp/Tengine/cgi_temp
--http-client-body-temp-path=/var/tmp/Tengine/client_body_temp
--http-log-path=/var/log/Tengine/access.log
--error-log-path=/var/log/Tengine/error.log
2>make&make install
1. 负责处理图片(裁剪、缩放)的 Lua 脚本(/usr/local/Tengine/lua/ImageResizer.lua),注意:ImageResizer.lua文件需要可执行权限 local command = "/usr/local/GraphicsMagick/bin/gm convert" .. ngx.var.request_filepath .. " -resize " .. ngx.var.width .."x" .. ngx.var.height .. " +profile \"*\" " ..ngx.var.request_filepath .. "_" .. ngx.var.width .. "x" ..ngx.var.height .. "." ..
ngx.var.ext; os.execute(command);ngx.exec(ngx.var.request_uri);
2. Nginx 配置user root; # 裁剪、缩放图片需要 root 权限server { listen 80; server_name img.itrip.project.bdqn.cn;
root /data/itrip/uploadimg; location / {
root /data/itrip/uploadimg; # 站点根目录 expires 1h; # 缓存时间 add_header Cache-Control max-age=3600; # 缓存时间 access_log /var/log/Tengine/host_access.log;
}
#如果 url 格式如:xxxx.gif_数字 x 数字.gif
location ~*^(.+\.(jpg|jpeg|gif|png))_(\d+)x(\d+)\.(jpg|jpeg|gif|png)$ {
root /data1/uploadimg; #这里必须设置,否则根目录,即 $document_root 会是 Nginx 默认的 Nginx Root/html,在 Lua 中会得不到期望的值 if (!-f $request_filename){ #如果文件不存在时才需要裁剪 add_header X-Powered-By'Lua GraphicsMagick'; #此 HTTPHeader 无实际意
义,用于测试
add_header file-path $request_filename; #此 HTTP Header 无实际意义,用于测试
lua_code_cache on; #在编写外部Lua 脚本时,设置为 off Nginx 不会缓存 Lua,方便调试
set $request_filepath /data1/uploadimg$1; #设置原始图片路径,如:
/document_root/1.gif
set $width $3; # 设置裁剪/缩放的宽度 set $height $4; # 设置裁剪/缩放的高度 set $ext $5; # 图片文件格式后缀
content_by_lua_file /usr/local/Tengine/lua/ImageResizer.lua; #加载外部 Lua 文件
}
}
…}
在进行爱旅行项目实际业务操作时,就可以实现按需自动等比缩放,系统中的所有的上传图片,都只须上传原始图即可,有效的省去切图的工作量。具体示例如下:
目前服务器上有一张原始图(8-3566787986543-7654678.jpg),如下图 1 所示:
图 1
访 问 该 原 始 图 (8-3566787986543-7654678.jpg) 的 URL 为 :
http://192.68.9.44/comment/8-3566787986543-7654678.jpg,如图 2 所示:
图 2
若根据需求,页面需要展现该图片的小图(300x300),那么前端只需访问:
http://192.168.9.44/comment/8-3566787986543-7654678.jpg_300x300.jpg(如图 3 所示)即可,
即:根据用户的访问请求,Lua 会自动进行图片缩放,生成相应尺寸的小图。
图 3
服务器上自动生成 8-3566787986543-7654678.jpg_300x300.jpg,如下图 4 所示:
图 4