如题 JSON参数画图生成图片的一个工具 , 场景: 用于卡片制作, 学生证, 毕业证等各种证书的下载打印等业务, 以及礼品卡的制作, 小程序页等转图片后 分享朋友圈等等....
不多说, 直接上石马 :
DrawingRender.java 去年写的工具...今天被同事用到了, 并且根据他提了一个居中的需求, 我做了一下增强支持ElKit.eval表达式了
package com.momathink.common.plugin.draw; import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.awt.image.ImageObserver; import java.io.FileInputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import javax.imageio.ImageIO; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.jfinal.kit.ElKit; import com.jfinal.kit.Kv; import com.jfinal.kit.PathKit; import com.jfinal.kit.StrKit; import com.jfinal.render.Render; import com.jfinal.render.RenderException; /** * 卡片制作 * * @author 杜福忠 2017-9-5 */ public class DrawingRender extends Render { protected BufferedImage image = null; protected String cardName = null; public DrawingRender(String json) { imageByJson(JSON.parseObject(json)); } @Override public void render() { response.setHeader("Content-Disposition", getFilename(request)); response.setHeader("Pragma","no-cache"); response.setHeader("Cache-Control","no-cache"); response.setDateHeader("Expires", 0); response.setContentType("image/jpeg"); ServletOutputStream sos = null; try { sos = response.getOutputStream(); ImageIO.write(image, "jpeg", sos); } catch (IOException e) { if (getDevMode()) { throw new RenderException(e); } } catch (Exception e) { throw new RenderException(e); } finally { if (sos != null) { try {sos.close();} catch (IOException e) {e.printStackTrace();} } } } /** * 解析 卡片 * * <pre> { "name":"卡片生成后的名称" "path":"背景图片地址" "list":[{ "type":"image", "path" : "图片地址" "x" : "50", "y" : "50" },{ "type":"word", "value" : "字体内容", "x" : "100", "y" : "100" "font" : { "name" : "Dialog、DialogInput、Monospaced、Serif 或 SansSerif,空为默认字体", "style" : "0,1,2", "size" : "1-70" }, "color" : { "r":"0到255", "g":"0到255", "b":"0到255", } } ] } * </pre> * */ protected BufferedImage imageByJson(JSONObject configure) { String basepath = PathKit.getWebRootPath(); BufferedImage background = getImage(basepath + configure.getString("path")); if (background == null) { throw new NullPointerException("没有找到 背景图片"); } cardName = isNull(configure.getString("name"), "Card"); // 默认的验证码大小 Integer width = background.getWidth(); Integer height = background.getHeight(); image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 获取图形上下文 Graphics2D g = image.createGraphics(); //呈现质量和总时间/质量折衷的控制 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); // 图形抗锯齿 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // 字体抗锯齿 g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); // 设定默认背景色 //g.setColor(new Color(255, 255, 255)); //g.fillRect(0, 0, width, height); //背景图 g.drawImage(background, 0, 0, width, height, imageobserver); //字符内容处理 //设定字体颜色 g.setColor(new Color(0, 0 , 0)); // 处理单元素 try { setList(configure, basepath, g); } catch (Exception e) { print(e); } // 销毁图像 g.dispose(); return image; } /** * @param configure * @param basepath * @param g */ protected void setList(JSONObject configure, String basepath, Graphics2D g) { // list JSONArray jsonArray = configure.getJSONArray("list"); for (Integer i = 0; i < jsonArray.size(); i++) { JSONObject element = jsonArray.getJSONObject(i); String type = element.getString("type"); if ("word".equals(type)) { // 文字 String value = element.getString("value"); if (StrKit.isBlank(value)) { continue; } String x = element.getString("x"); String y = element.getString("y"); // 文字 JSONObject color = element.getJSONObject("color"); Integer cr = color.getInteger("r"); Integer cg = color.getIntValue("g"); Integer cb = color.getIntValue("b"); // 字体样式 JSONObject font = element.getJSONObject("font"); String fontname = font.getString("name"); Integer fontStyle = font.getIntValue("style"); String fontSize = font.getString("size"); // 渲染 setStr(g, cr, cg, cb, fontname, fontStyle, fontSize, value, x, y); } else if ("image".equals(type)) { // 图片 String path = element.getString("path"); if (StrKit.isBlank(path)) { continue; } String x = element.getString("x"); String y = element.getString("y"); // 渲染 setImage(g, basepath + path, x, y); } } } /** * //设定字体 //设定字体颜色 //设定字 */ protected void setStr(Graphics2D g, Integer colorR, Integer colorG, Integer colorB, String fontname, Integer fontStyle, String fontSize, String v, String x, String y) { colorR = isNull(colorR, 0); colorG = isNull(colorG, 0); colorB = isNull(colorB, 0); fontname = isNull(fontname, null); fontStyle = isNull(fontStyle, 1); fontSize = isNull(fontSize, "24"); int centerX = image.getWidth() / 2; x = isNull(x, "0"); y = isNull(y, "0"); try { Integer fontSizei = ElKit.eval(fontSize, Kv.by("length", v.length()).set("centerX", centerX)); Font font = new Font(fontname, fontStyle, fontSizei); FontMetrics fontMetrics = g.getFontMetrics(font); int textWidth = fontMetrics.stringWidth(v); Kv data = Kv.by("length", v.length()).set("fontSize", fontSizei).set("str", v) .set("centerX", centerX).set("textWidth", textWidth) .set("center", centerX - textWidth / 2); Integer xi = ElKit.eval(x, data); Integer yi = ElKit.eval(y, data); g.setColor(new Color(colorR, colorG, colorB)); g.setFont(font); g.drawString(v, xi, yi); } catch (Exception e) { print(e); } } /** * 画图片 * * @param g * @param path * @param x * @param y */ protected void setImage(Graphics2D g, String path, String x, String y) { x = isNull(x, "0"); y = isNull(y, "0"); int centerX = image.getWidth() / 2; try { BufferedImage img = getImage(path); Kv data = Kv.by("img", img).set("context", image).set("center", centerX - img.getWidth() / 2); Integer xi = ElKit.eval(x, data); Integer yi = ElKit.eval(y, data); g.drawImage(img, xi, yi, imageobserver); } catch (Exception e) { print(e); } } protected Integer isNull(Integer val, Integer df) { return val != null ? val : df; } protected String isNull(String val, String df) { return StrKit.notBlank(val) ? val : df; } protected BufferedImage getImage(String imgPath) { try { return ImageIO.read(new FileInputStream(imgPath)); } catch (IOException e) { print(e); } return null; } protected ImageObserver imageobserver = new ImageObserver() { @Override public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) { return true; } }; protected String getFilename(HttpServletRequest request) { try { String agent = request.getHeader("USER-AGENT"); if (agent.toLowerCase().indexOf("firefox") > 0) { cardName = new String(cardName.getBytes("utf-8"), "iso-8859-1"); } else { cardName = URLEncoder.encode(cardName, "UTF-8"); } } catch (UnsupportedEncodingException e) { print(e); } return "attachment; filename=" + cardName + ".jpg"; } protected void print(Exception e) { e.printStackTrace(); } }
上面依赖的JAR包 有fastjson解析工具
工具完成, 开始使用:
/** * 工具 * * @author 杜福忠 2018-09-07 14:02:52 * */ @Clear() public class KitController extends Controller { /** * 画板 /api/kit/drawing?data=JSON * 也可使用 cache=key */ public void drawing() { String data = getPara("data"); if (data == null) { data = ConfigKit.getCache().get("apiKitCache", getPara("cache")); } render(new DrawingRender(data)); } /** * 画板缓存参数 /api/kit/cache?data=JSON * 返回缓存key */ public void cache() { String data = getPara("data"); String key = StrKit.getRandomUUID(); ConfigKit.getCache().put("apiKitCache", key, data); renderJson(key); } }
上面依赖的JAR包 有ehcacheh缓存工具
用法:
如调试参数时使用的例子drawing.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>JSON画图工具</title> <style type="text/css"> .container { display: table; width: 80%; } .container .left, .container .right { display: table-cell; } .container .left { width: 20%; } .container .right { width: 80%; } </style> </head> <body> <div class="container"> <div class="left"> <textarea rows="40" cols="80"> { "name":"卡片生成后的名称" "path":"/背景图片地址" "list":[{ "type":"image", "path" : "/图片地址" "x" : "50", "y" : "50" },{ "type":"word", "value" : "字体内容", "x" : "100 center是居中", "y" : "100" "font" : { "name" : "Dialog、DialogInput、Monospaced、Serif 或 SansSerif,空为默认字体", "style" : "0,1,2", "size" : "1-70" }, "color" : { "r":"0到255", "g":"0到255", "b":"0到255", } } ] } </textarea> </div> <div class="right"> <img alt="预览图" src="" > </div> </div> <script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script> <script type="text/javascript"> $("textarea").keyup(function(){ var json = $("textarea").val(); $("img").attr("src", "/api/kit/drawing?data=" + json); }); </script> </body> </html>
上面例子需要 自己调整一下参数 根据自己情况来写, 有说用canvas画的, 我反手就是一下兼容性, 易用性, 普适性啦... 23333 喜欢就好~
再比如小程序中的调用方式:
var jsonData = ` JSON 参数此处 省略 `; wx.request({ url: 域名+'/api/kit/cache', //仅为示例,并非真实的接口地址 data: {data:jsonData},success: function(res) { // 此处 修改一下 IMG 的 SRC=域名+"/api/kit/drawing?cache="+res.data 即可 // 或者调用下载API } })
预览一下:
点个赞呗~