文档章节

nginx+graphicsmagick+lua动态处理图片

基督山伯爵
 基督山伯爵
发布于 2014/06/04 13:50
字数 830
阅读 227
收藏 2
点赞 0
评论 0

第一步,LUA版本目前不支持5.2,用系统自带的5.1就可以了。不过还是要安装下LUA的开发库

yum install lua-devel

第二步,安装 luajit,http://luajit.org/download.html到这里下载最新版,解压

make
make install

第三步,NGINX可以用淘宝出的tengine,已加载lua插件,编译参数如下

./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_gzip_static_module --with-http_concat_module --with-http_lua_module --with-luajit-inc=/usr/local/include/luajit-2.0 --with-luajit-lib=/usr/local/lib

nginx.conf配置如下:

        location ~ '/(.*)/(.*).(jpg|JPG|jpeg|png|gif|GIF)_([0-9]+)x([0-9]+).(jpg|jpeg|png|gif)$' {
                root /home/images;
                set $image_root /home/images;
                set $thumbnail_root /home/images/thumbnail_root;
#               set $uri $request_filename;
                if (!-e $request_filename){
                        rewrite_by_lua_file conf/image.lua;
                }
        }

image.lua文件内容如下:

-- Nginx thumbnail module by lua
-- last update: 2014/1/11
-- ver: 0.3

-- 是否记录日志
local is_log = true;
-- 允许默认图片
local enable_default_img = false;
-- graphicsmagick安装路径
local gm_path="/usr/local/GraphicsMagick/bin/gm";
-- 链接地址,如/goods/0007/541/001_328x328.jpg
local uri = ngx.var.uri;
-- 图片目录
local ngx_img_root = ngx.var.image_root
-- 缩略图目录
local ngx_thumbnail_root = ngx.var.thumbnail_root
-- img_width:缩略图宽度 img_width:缩略图高度  img_size:缩略图宽x高 img_crop_type:缩略图裁剪类型
local img_width,img_height,img_size,img_crop_type = 0;

-- 配置项,对目录、缩略图尺寸、裁剪类型进行配置,匹配后才进行缩略图处理
local cfg = {
    {dir="",sizes={"76x38!","100x100!","138x77!","232x135!","640x240^","180x105!","300x242!","320x88!","180x120!"}}
--    {dir="manage",sizes={"138x77!","232x135!","500x500$","800x800!"}}
}



-- 日志函数
-- log_level: ngx.STDERR , ngx.EMERG , ngx.ALERT , ngx.CRIT , ngx.ERR , ngx.WARN , ngx.NOTICE , ngx.INFO , ngx.DEBUG
-- 默认为ngx.NOTICE
function lua_log(msg,log_level)
    if (log_level == nil) then log_level =  ngx.NOTICE end;
    if(is_log) then ngx.log(log_level,msg) end;
end

-- 判断链接是否符合规则
function table.contains(table,element)
    -- 遍历table
    for _, value in pairs(cfg) do
        local dir = value["dir"];
        local sizes = value["sizes"];
        -- 根据正则匹配缩略图宽、高
        _,_,img_width,img_height = string.find(uri,""..dir.."_([0-9]+)x([0-9]+)");
        if(img_width ~= nil and img_height ~= nil) then
            -- 缩略图尺寸
            img_size = img_width.."x"..img_height;
            for _, value in pairs(sizes) do
                -- 1.保持原图比例,实际尺寸可能小于请求尺寸
                if (img_size == value) then
                    img_crop_type=1;
                return true;
                -- 2.拉伸,图片有可能变形
                elseif (img_size.."!" == value) then
                    img_crop_type=2;
                    return true;
                -- 3.保证大小与比例,但图有可能裁剪不完整
                elseif (img_size.."^" == value) then
                    img_crop_type=3;
                    return true;
                -- 4.只限制宽度
                elseif (img_size.."$" == value) then
                    img_crop_type=4;
                    img_size = img_width.."x";
                    return true;
                end
            end
        end
    end
    return false
end

-- 原图链接
local img_original_uri = string.gsub(uri, "_[0-9]+x[0-9]+.[jpg|png|gif]+","");
-- 判断原图是否存在
local img_exist=io.open(ngx_img_root .. img_original_uri);
if not img_exist then
    if not enable_default_img then
        lua_log(img_original_uri.." isn't exist!",ngx.ERR);
        ngx.exit(404);
    else
        local default_img_original_uri = "/empty/empty.jpg";
        img_exist=io.open(ngx_img_root ..  default_img_original_uri);
        if img_exist then
            lua_log(img_original_uri .. "isn't exist! crop image with default image");
            img_original_uri = default_img_original_uri;
        else
            lua_log(img_original_uri.." isn't exist!",ngx.ERR);
            ngx.exit(404);
        end
    end;
end;

if not table.contains(cfg, uri) then
    lua_log(uri.." don't match!",ngx.ERR);
    ngx.exit(404);
else
    -- 开始生成缩略图
    local gm_command;
    -- 缩略图文件路径
    local img_thumbnail_path = ngx_thumbnail_root .. uri;
    -- 原图文件路径
    local img_original_path = ngx_img_root .. img_original_uri;
    -- 执行gm命令
    if (img_crop_type == 1) then
        gm_command = gm_path .. " convert " .. img_original_path  .. " -thumbnail "  .. img_size .. " -background white -gravity center -strip +profile '*' -quality 90 -extent " .. img_size .. " " .. img_thumbnail_path
    elseif (img_crop_type == 2) then
        gm_command = gm_path .. " convert " .. img_original_path  .. " -thumbnail "  .. img_size .. "! -strip +profile '*' -quality 90 -extent ".. img_size .." " .. img_thumbnail_path;
    elseif (img_crop_type == 3) then
        gm_command = gm_path .. " convert " .. img_original_path  .. " -thumbnail "  .. img_size .. "^ -strip +profile '*' -quality 90 -extent ".. img_size .." " ..img_thumbnail_path;
    elseif (img_crop_type == 4) then
        gm_command = gm_path .. " convert " .. img_original_path  .. " -resize '"  .. img_size .. ">' -strip +profile '*' -quality 90 " ..img_thumbnail_path;
    else
        lua_log("img_crop_type error:"..img_crop_type,ngx.ERR);
        ngx.exit(404);
    end

-- 判断图是否存在
    local new_img_exist=io.open(img_thumbnail_path);
    --lua_log(img_thumbnail_path .. uri);
    -- 执行gm命令 and not new_img_exist
    if (gm_command ~= nil and not new_img_exist) then
        -- 获取缩略图路径及文件名
        _,_,img_thumbnail_dir,img__thumbnail_filename=string.find(img_thumbnail_path,'(.-)([^/]*)$')
        -- 先创建缩略图所在目录,避免报错
        os.execute("mkdir -p "..img_thumbnail_dir);
        -- 执行gm命令
        os.execute(gm_command);
        lua_log("gm_command======"..img_crop_type..gm_command);
    end
    -- 转发请求至缩略图
    ngx.req.set_uri("/thumbnail_root"..uri,true);
end


© 著作权归作者所有

共有 人打赏支持
基督山伯爵
粉丝 7
博文 17
码字总数 6779
作品 0
杭州
数据库管理员
Nginx与Tomcat实现请求动态数据与请求静态资源的分离

  上篇博客说明了Nginx在应用架构中的作用,以及负载均衡的思路。这篇实践一下其中的访问静态资源与访问动态资源的操作。 一、认识访问静态资源与访问动态资源的区别   静态资源:指存储...

左羽
07/12
0
0
【深入浅出MyBatis系列四】强大的动态SQL

深入浅出MyBatis系列 【深入浅出MyBatis系列一】MyBatis入门 【深入浅出MyBatis系列二】配置简介(MyBatis源码篇) 【深入浅出MyBatis系列三】Mapper映射文件配置 【深入浅出MyBatis系列四】...

陶邦仁
2015/12/22
1K
0
Nginx + Apache + Tomcat架构方式,为什么需要Apache?Apache的作用?

Nginx:一款能承受高并发的HTTP服务器,异步的,多个连接(万级别)可以对应一个进程,进行响应。基于事件驱动模型。 Nginx优点:负载均衡、反向代理、处理静态文件优势。 Apache:相对于Nginx...

Nathans
2014/11/06
8.6K
11
AlexGao/WSHttpHelper

轻量级Http请求框架。清晰明了的请求接口描述,灵活的扩展机制。 快捷接口: 支持同步调用; 支持异步调用,异步回调; 支持JSON自动转换为指定类型; 支持自定义输入参数验证; 支持自定义结果解...

AlexGao
2015/12/20
0
0
apiCloud中图片裁剪模块FNImageClip的使用

思路 1.获取需裁剪图片的地址 2.跳转到裁剪页面 3.裁剪成功返回新图片地址 4.替换原有图片地址 增加修饰和事件 上面是动态生成的图片html布局数据,增加一个id标识,增加一个点击事件 打开裁剪...

桃子红了呐
01/07
0
0
色情主播的天敌:AI 大牛为你解密人工智能鉴黄的那些事

目前多家人工智能公司已开始布局鉴黄业务,阿里巴巴和腾讯分别拥有阿里绿网、万象优图两大鉴黄系统。而在创业公司方面,较为知名的有图普科技、飞搜科技、深图智服等公司。 近期在线直播火爆...

亚峰
2016/11/09
0
0
iOS Ken Burns

实现Ken Burns effect 的图片切换效果。图片在切换之前,会缓慢在页面移动或者放大缩小,然后再慢慢切换过去。这样的效果使得每一张静止图片都有动态的效果感觉。类似的效果在电子相册,或者...

匿名
2012/09/15
705
0
微信小程序利用canvas生成海报分享图片

利用微信小程序canvas生成海报分享图片,这个生成图片排版和适配不同尺寸的手机是一个难点,特别是图片适应问题,我处理的方法是动态获取容器的宽度进行适应就是利用微信API wx.createSelect...

独孤久见
06/28
0
0
分享一个jQuery动态网格布局插件:Masonry

日期:2011/12/01 来源:GBin1.com 在线演示 Masonry是 一款非常强大的jQuery动态网格布局插件,可以帮助开发人员快速开发类似剪贴画的界面效果。和CSS中float的效果不太一样的地方在 于,f...

gbin1
2011/12/08
0
0
图片存储系统--TngouFS

TngouFS是天狗网(www.tngou.net) 用于 该网站的图片存储。动态图片请求流程,如下图: 主要功能 上传图片 基于URL直接下载图片 在线剪切图片 支持百度的UEditor后台处理 网站功能 独有的图...

tngou
2015/07/21
1K
2

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Kafka设计解析(一)- Kafka背景及架构介绍

原创文章,转载请务必将下面这段话置于文章开头处。(已授权InfoQ中文站发布) 本文转发自技术世界,原文链接 http://www.jasongj.com/2015/03/10/KafkaColumn1 摘要   Kafka是由LinkedI...

mskk
5分钟前
0
0
使用Service Mesh整合您的微服务架构

在微服务架构的世界中,它正在达到这样的程度,即管理系统的复杂性对于利用它带来的好处变得至关重要。 目前,如何实现这些微服务不再是一个问题,因为有很多可用的框架(Spring Boot,Vert....

xiaomin0322
8分钟前
0
0
看看 LinkedList Java 9

终于迎来了 LinkedList 类,实现的接口就有点多了 Serializable, Cloneable, Iterable<E>, Collection<E>, Deque<E>, List<E>, Queue<E>。LinkedList是一个实现了List接口和Deque接口的双端链......

woshixin
27分钟前
0
0
算法 - 冒泡排序 C++

大家好,我是ChungZH。今天我给大家讲一下最基础的排序算法:冒泡排序(BubbleSort)。 冒泡排序算法的原理如下: 比较相邻的元素。如果第一个比第二个大(可以相反),就交换他们两个。 对每...

ChungZH
29分钟前
0
0
jquery ajax request payload和fromData请求方式

请求头的不同 fromData var data = { name : 'yiifaa'};// 提交数据$.ajax('app/', { method:'POST', // 将数据编码为表单模式 contentType:'application/x-ww...

lsy999
31分钟前
0
0
阿里P7架构师,带你点亮程序员蜕变之路

前言: Java是现阶段中国互联网公司中,覆盖度最广的研发语言。 掌握了Java技术体系,不管在成熟的大公司,快速发展的公司,还是创业阶段的公司,都能有立足之地。 有不少朋友问,成为Java架...

Java大蜗牛
33分钟前
1
0
Ecstore 在没有后台管理界面(维护)的情况如何更新表的字段

window 系统: 切换到:app\base 目录下: C:\Users\qimh>d: D:\>cd D:\WWW\huaqh\app\base 执行:D:\WWW\huaqh\app\base>cmd update linux 系统: 1># cd /alidata/www.novoeshop.com/app/......

qimh
37分钟前
0
0
设计模式-策略模式

策略模式 解释 对工厂模式的再次封装,使用参数控制上下文信息(将工厂返回的实例赋值给context field) 不会返回bean实例,只是设置对应的条件 调用context的方法(调用field的方法) 用户只...

郭里奥
40分钟前
0
0
python使用有序字典

python自带的collections包中有很多有用的数据结构可供使用,其中有个叫OrderedDict类,它可以在使用的时候记录元素插入顺序,在遍历使用的时候就可以按照原顺序遍历。 a = {"a":1,"b"...

芝麻糖人
今天
0
0
RestTemplate HttpMessageConverter

RestTemplate 微信接口 text/plain HttpMessageConverter

微小宝
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部