整体思路:引入zxing成熟的二维码生成接口,生成标准二维码文件,通过java图形图像处理api为二维码添加相关文字描述,根据需要,可以为合成后的图片添加相关背景。示例如下图所示:
1.先拿点位图来说,生成二维码图片核心代码如下
/** * 定义二维码的参数 */ hashmap<encodehinttype, object> hints = new hashmap(); //指定字符编码为“utf-8” hints.put(encodehinttype.character_set, "utf-8"); //指定二维码的纠错等级为中级 hints.put(encodehinttype.error_correction, errorcorrectionlevel.h); //设置图片的边距 hints.put(encodehinttype.margin, 1); /** * 生成二维码 */ try { bitmatrix bitmatrix = new multiformatwriter().encode(content, barcodeformat.qr_code, qrcode_width, qrcode_height, hints); path file = new file(filepath).topath(); matrixtoimagewriter.writetopath(bitmatrix, format, file); } catch (exception e) { log.error("二维码生成出错:/permitdownload: error", e); }
2.给二维码添加文字
/** * 给二维码下方添加说明文字 * * @param image 原二维码 * @param toptext 顶部说明文字 * @param downtext 底部说明文字 * @return 带说明文字的二维码 */ private static bufferedimage addnote(bufferedimage image, string toptext, string downtext) { image src = image.getscaledinstance(qrcode_width, qrcode_height, image.scale_default); bufferedimage tag = new bufferedimage(qrcode_width, image_height, bufferedimage.type_int_rgb); graphics2d g2 = tag.creategraphics();//设置文字 g2.setcolor(color.black); g2.setbackground(color.white); g2.clearrect(0,0,qrcode_width, image_height); //设置顶部文本并计算坐标 // 保证操作系统包含“宋体”字体,如果没有上传字体至java_home/jre/lib/fonts下 fontmetrics fm = getfontbywidth(new font("宋体", font.plain, default_font_size), toptext, g2); //文字的宽度 int fontwidth = fm.stringwidth(toptext); //文字高度 int fontheight = fm.getheight(); /** * 顶部添加文字并居中 */ g2.drawstring(toptext, (qrcode_width - fontwidth) / 2, (text_default_height - fontheight) / 2 + fm.getfont().getsize()); /** * 绘制二维码 */ g2.drawimage(src, 0, text_default_height, null); // 设置底部文字字体并计算坐标 // 保证操作系统包含“宋体”字体,如果没有上传字体至java_home/jre/lib/fonts下 fm = getfontbywidth(new font("宋体", font.plain, default_font_size), downtext, g2); //文字的宽度 fontwidth = fm.stringwidth(downtext); //文字高度 fontheight = fm.getheight(); /** * 添加底部文字 */ g2.drawstring(downtext, (qrcode_width - fontwidth) / 2, qrcode_height + text_default_height+(text_default_height - fontheight) / 2 + fm.getfont().getsize()); g2.dispose(); image = tag; image.flush(); return image; }
知识点 : 底部文字长度会变,目前设计只放一行文字,所以根据字数多少会动态改变文字大小在一个合理区间(不至于太小无法识别),使用fontmetrics 对象,这个点会对多数同学有帮助
3.动态修改字体及大小
/** * 根据文字长度改变文字大小 * * @param font 默认字体 * @param note 文字内容 * @param g2 图像画布 * @return 处理后的字体封装 */ private static fontmetrics getfontbywidth(font font, string note, graphics2d g2) { fontmetrics fm = g2.getfontmetrics(font); int textwidth = fm.stringwidth(note);//文字的宽度 if (textwidth > qrcode_width) { int fontsize = (int) ((temp_param / textwidth) * font.getsize()); font = new font(font.getname(), font.getstyle(), fontsize); } g2.setfont(font); return g2.getfontmetrics(font); }
4.最后一步将蓝色底图与二维码图片合成,就可以了。
图片合成四部曲第一步:创建画布,需要设置画布的宽、高,单位应该是像素
bufferedimage tag = new bufferedimage(qrcode_width, image_height, bufferedimage.type_int_rgb);
第二步: 在画布上创建图形对象graphics2d,可以根据你对图像知识点的了解设置如背景、前景、边框、宽度等信息
graphics2d g2 = tag.creategraphics();//设置文字
第三步: 合成图片,过程中的图片添加顺序、图片大小、坐标位置会影响最终的呈现效果,如果最终效果没有达到设计需求,调整这三个参数一定会有所帮助
image src = image.getscaledinstance(qrcode_width, qrcode_height, image.scale_default);... /*** 绘制二维码 */g2.drawimage(src, 0, text_default_height, null);
第四步: 生成最终的新图片
/** * 给二维码图片添加背景图片 * * @param qrpic 二维码 * @param backimage 背景图片 */ private static void createnewpng(file qrpic, bufferedimage backimage) { try { if (!qrpic.isfile()) { log.error("二维码临时路径不存在!"); } /** * 读取背景图片,并构建绘图对象--画布 */ graphics2d g = backimage.creategraphics(); /** * 读取二维码图片 */ bufferedimage qrcodeimage = imageio.read(qrpic); //开始绘制图片 g.drawimage(qrcodeimage, 48, 120, qrcodeimage.getwidth(), qrcodeimage.getheight(), null); g.dispose(); imageio.write(backimage, "png", qrpic); } catch (exception e) { log.error("绘制二维码出错!"); } }
第二张图片和第一张图片生成过程相同,只是将文中 【2. 给二维码添加文字】中的顺序由上、中、下变为 左、右即可
踩过的坑背景图片像素、大小需要和二维码匹配,否则会出现二维码与背景比例严重失调或二维码显示不完整
二维码添加文字乱码 开发环境(windows),测试环境(centos 服务器版)。本地开发测试没有任何问题,打包部署至服务器后所有中文字符出现乱码(各种转码,字体设置,调试整了很久),问题仍然没有任何变化。最终灵光一现怀疑是系统字体问题,查了测试环境(centos)字体信息确实没有“宋体”,设置成系统自有或默认的字体,问题还在。最终从(c:\windows\fonts\simsun.ttc)开发系统中copy字体至测试系统(java_home/jre/libs/fonts)中后重启应用,问题得到完美解决。系统安装部署需要准备字体有点麻烦,不知道还有没有更好的办法,字体有逻辑字体和物理字体,爱、先这样吧。
背景图片加载问题 项目为springboot项目,背景图片存放在resources文件夹下,本地开发测试未见异常,打包部署至服务器后背景图片无法找到,原始代码如下
string backfilepath = "template/down.png"; classpathresource resource = new classpathresource(backfilepath); file file = resource.getfile();
在网上找加载图片的方法都使用过,没有效果,最后修改为输入流,图片合成正常,代码如下
/** * 必须通过流方式,否则不同操作系统无法拿到背景图片信息 */ string backfilepath = "template/down.png"; classpathresource resource = new classpathresource(backfilepath); bufferedimage bi = imageio.read(resource.getinputstream());
以上就是java zxing怎么合成复杂二维码图片的详细内容。
