通用文字内容生成图片方案
需求背景
\
为了防止用户很容易的采集到客户的联系方式信息,需要将用户的联系方式用图片显示。
类似于以下情况:
1.公司名片
2.求职招聘
3.旺铺
4.求购
\
\
技术方案
\
整体技术实现方案采用cdn+nginx+lua-gd来实现。利用CDN缓存生成的图片减少服务器的请求次数提高响应速度。
为了提高生成图片服务的灵活性和简单易用好维护,采用lua-gd模块生成图片。
lua-gd官网文档:Lua-GD Reference Manual (ittner.com.br)
\
简单使用lua-gd
im = gd.create(140, 80) -- 创建宽高画布
white = im:colorAllocate(255, 255, 255) -- 白色底
black = im:colorAllocate(0, 0, 0) -- 黑色字
im:string(gd.FONT_TINY, 10, 20, "TINY", black) -- 写入黑色文字指定位置
im:string(gd.FONT_SMALL, 10, 30, "SMALL", black)
im:string(gd.FONT_MEDIUM, 10, 45, "MEDIUM", black)
im:string(gd.FONT_LARGE, 10, 58, "LARGE", black)
im:png("out.png") -- 输出图片
图:out.png
nginx配置lua脚本
nginx接入lua需要按照好对应模块,然后在conf文件中配置写好的lua脚本
\
整体流程
根据输入的参数内容,尺寸,和颜色信息生成Url,请求nginx服务器,由lua解析参数信息lua-gd模块生成图片响应图片信息,相同Url链接地址会被cdn缓存。
流程图:
参数信息主要是三部分:content,size,color
参数说明:
content:自定义文本内容
size:定义高度宽度(WxH)W宽,H高;例子:30x20
color: 颜色为RGB值:如:(255,255,255) 白色
\
URL生成规则
\
Lua Url编码样例代码:
local function decode(text)
--
local ts = string.split(text, "@")
local length = tonumber(ts[2])
local str = ts[1] .. ""
-- 固定slat
local slat = 10
-- 定长数组4个
local size = 4
local b64 = require("base64")
local res, err = b64.decode_base64url(str)
-- 反转字符串提取文本内容
local content = string.split(string.reverse(res), ",")
local pl = #content / size;
local m = 0
if (#content ~= pl * size) then
m = m + 1
end
local chars = {}
-- 初始化数组
for i = 1, (pl + m) do
chars[i] = {}
for j = 1, size do
chars[i][j] = -1
end
end
-- 填充内容
local index = 1;
for i = 1, #content do
local x = tonumber(content[i])
local pi = (index - 1) % (pl + m);
if (i % size) == 0 then
index = index + 1
end
chars[pi + 1][((i - 1) % (size)) + 1] = x;
end
-- 数值转化
local idx = 0
for i = 1, (pl + m) do
for j = 1, size do
idx = idx + 1
local value = chars[i][j]
chars[i][j] = (value - flag + idx);
end
end
--位置替换
for i = 1, (pl + m) do
if i == (pl + m) then
else
if i % 2 == 1 then
local c1 = chars[i]
local c2 = chars[i + 1]
chars[i] = c2
chars[i + 1] = c1
end
end
end
--解出字符串
local rs_str = "";
local ti = 0;
for i = 1, (pl + m) do
for j = 1, size do
ti = ti + 1
if ti <= length then
rs_str = rs_str .. toUnicode(chars[i][j])
end
end
end
return rs_str
end
local request_uri = ngx.var.request_uri
local args = ngx.req.get_uri_args()
local size = args['size']
local color = args['color']
local path = string.match(request_uri, "path/(.*)?")
--高宽
local wh = string.split(size, "x")
--颜色RGB值
local colors = string.split(color, ",")
--内容结果
local dval = decode(path)
--gd 模块
local gd = require "gd"
gd.useFontConfig(true)
im = gd.create(tonumber(wh[1]), tonumber(wh[2]))
white = im:colorAllocate(255, 255, 255)
im:colorTransparent(white)
local black = im:colorAllocate(tonumber(colors[1]), tonumber(colors[2]), tonumber(colors[3]))
-- 颜色 字体 字体高度 x ,y(底部)
im:stringFT(black, "Arial", tonumber(wh[2])*0.5, 0, 1, tonumber(wh[2])*0.7, dval)
--响应图片
ngx.say(im:pngStr())
\
样例:
\
\