zxing二维码生成工具类
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了zxing二维码生成工具类相关的知识,希望对你有一定的参考价值。
图片生成工具生成
1.支持多中形式的图片,二维码,条形码
2.支持一张图片多个二维码
3.支持二维码图片上加logo
4.支持图片头部底部添加文字描述
public class ZxingEncoderUtil { private static final String CHARSET = "utf-8"; private static final String FORMAT = "JPG"; private static Font font = null; /** * 二维码生成,支持一张图上多个二维码,支持图片添加字体(上下位置),支持二维码中间加logo, * * @param content * @param qrWidth * @param qrHeight * @param barcodeFormat * @param logoPath * @param multiImgs * @param options key image_top_1 *** 表示图片要加的内容 * @return */ public static byte[] createImage(String content, int qrWidth, int qrHeight, BarcodeFormat barcodeFormat, String logoPath, Boolean multiImgs, Map<String, String> options) { //每个图片之间的间隔 int gap = 0; //每行的行距 int lineHeight = 0; //字符串的高度 int strHeight = 15; List<String> contents = new ArrayList<>(); try { HashMap<EncodeHintType, Object> hints = new HashMap<>(); if (StringUtils.isNotBlank(logoPath)) { hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); //容错等级 L、M、Q、H 其中 L 为最低, H 为最高 } else { hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M); //容错等级 L、M、Q、H 其中 L 为最低, H 为最高 } hints.put(EncodeHintType.CHARACTER_SET, CHARSET); // 字符编码 hints.put(EncodeHintType.MARGIN, 0); // 二维码与图片边距 if (multiImgs != null && multiImgs) { String[] str = content.split(","); contents = Arrays.asList(str); gap = 15; } else { contents.add(content); } //去重 ArrayList<String> result = new ArrayList<>(); for (String item : contents) { if (Collections.frequency(result, item) < 1) result.add(item); } Map<String, SortedMap<String, String>> addImage = addOnImage(options); SortedMap<String, String> topMap = addImage.get("top"); SortedMap<String, String> bottomMap = addImage.get("bottom"); //行距 if (topMap != null && !topMap.isEmpty() || bottomMap != null && !bottomMap.isEmpty()) { lineHeight = 5; } //画布的宽,高 int bWidth = qrWidth; int bHeight = qrHeight + gap + lineHeight * 2; //如果是条形码,需要增加源字符串在画布上 if (barcodeFormat.equals(BarcodeFormat.CODE_128)) { bHeight += strHeight; } //如果要加头文字,需要加上头部的高度 if (topMap != null && !topMap.isEmpty()) { bHeight += strHeight * topMap.size(); } //如果要加上底部描述,需要加上底部高度 if (bottomMap != null && !bottomMap.isEmpty()) { bHeight += strHeight * bottomMap.size(); } //整个画布的高度 bHeight = bHeight * result.size() - gap; //设置画布 BufferedImage source = new BufferedImage(bWidth, bHeight, BufferedImage.TYPE_INT_RGB); Graphics2D graph = source.createGraphics(); //设置背景颜色 graph.setBackground(Color.WHITE); graph.clearRect(0, 0, bWidth, bHeight); if (font == null) { FileInputStream inputStream = new FileInputStream(new File(ZxingEncoderUtil.class.getResource("/font/msyh.ttf").getFile())); font = Font.createFont(Font.TRUETYPE_FONT, inputStream).deriveFont(Font.BOLD, 14f); inputStream.close(); } graph.setFont(font); graph.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); graph.setColor(Color.BLACK); //下一次起始Y位置 int nextPosY = 0; //汇总一次的高度 int singleHeight; int topHeight; for (String item : result) { singleHeight = 0; topHeight = 0; BufferedImage image = printImage(item, barcodeFormat, qrWidth, qrHeight, logoPath, hints); //画图片上部分 if (topMap != null && !topMap.isEmpty()) { for (SortedMap.Entry<String, String> entry : topMap.entrySet()) { int strWidth = graph.getFontMetrics().stringWidth(entry.getValue()); int strX = (image.getWidth(null) - strWidth) / 2; int strY = strHeight * Integer.valueOf(entry.getKey()) + nextPosY; graph.drawString(entry.getValue(), strX, strY); } topHeight = strHeight * topMap.size(); } //图片坐标 int imageX = 0; int imageY = topHeight + lineHeight + nextPosY; //画图片 graph.drawImage(image, imageX, imageY, image.getWidth(null), image.getHeight(null), null); singleHeight += topHeight + lineHeight + image.getHeight(null); if (barcodeFormat.equals(BarcodeFormat.CODE_128)) { int strWidth = graph.getFontMetrics().stringWidth(item); int strX = (image.getWidth(null) - strWidth) / 2; int strY = imageY + strHeight + image.getHeight(null); graph.drawString(item, strX, strY); singleHeight += strHeight; } //画图片下部分 if (bottomMap != null && !bottomMap.isEmpty()) { for (SortedMap.Entry<String, String> entry : bottomMap.entrySet()) { int strWidth = graph.getFontMetrics().stringWidth(entry.getValue()); int strX = (image.getWidth(null) - strWidth) / 2; int strY = strHeight * Integer.valueOf(entry.getKey()) + nextPosY + singleHeight; graph.drawString(entry.getValue(), strX, strY); } singleHeight += strHeight * bottomMap.size(); } //设置下次画图的位置 int i = result.indexOf(item); nextPosY = (singleHeight + gap) * (i + 1); } graph.setStroke(new BasicStroke(3f)); graph.dispose(); return imageIO(source); } catch (Exception e) { } return null; } /** * BufferedImage 转字节流 * * @param source * @return */ private static byte[] imageIO(BufferedImage source) { try { ByteArrayOutputStream os = new ByteArrayOutputStream(); ImageIO.write(source, "jpg", os); return os.toByteArray(); } catch (Exception ex) { return null; } } /** * 插入LOGO * * @param source * @param logoPath * @throws Exception */ private static void insertImage(BufferedImage source, String logoPath) throws Exception { File file = new File(ZxingEncoderUtil.class.getResource(String.format("/image/%s", logoPath)).getFile()); if (!file.exists()) { throw new Exception("logo file not found."); } Image src = ImageIO.read(file); int width = src.getWidth(null); int height = src.getHeight(null); // 插入LOGO Graphics2D graph = source.createGraphics(); int x = (source.getWidth() - width) / 2; int y = (source.getHeight() - height) / 2; graph.drawImage(src, x, y, width, height, null); Shape shape = new RoundRectangle2D.Float(x, y, width, height, 6, 6); graph.setStroke(new BasicStroke(3f)); graph.draw(shape); graph.dispose(); } /** * zxing工具生成BufferedImage * * @param content * @param barcodeFormat * @param qrWidth * @param qrHeight * @param logoPath * @param hints * @return * @throws Exception */ private static BufferedImage printImage(String content, BarcodeFormat barcodeFormat, int qrWidth, int qrHeight, String logoPath, HashMap<EncodeHintType, Object> hints) throws Exception { BitMatrix bitMatrix = new MultiFormatWriter().encode(content, barcodeFormat, qrWidth, qrHeight, hints); int width = bitMatrix.getWidth(); int height = bitMatrix.getHeight(); BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF); } } if (StringUtils.isNotBlank(logoPath)) { insertImage(image, logoPath); } return image; } /** * 获取位置参数 * * @param options key image_AA_BB value *** AA位置(top,bottom) BB 排序 * @return */ private static Map<String, SortedMap<String, String>> addOnImage(Map<String, String> options) { Map<String, SortedMap<String, String>> result = Collections.synchronizedMap(new HashMap<String, SortedMap<String, String>>()); SortedMap<String, String> topMap = Collections.synchronizedSortedMap(new TreeMap<String, String>()); SortedMap<String, String> bottomMap = Collections.synchronizedSortedMap(new TreeMap<String, String>()); try { if (options != null && !options.isEmpty()) for (Map.Entry<String, String> entry : options.entrySet()) { if (StringUtils.isNotBlank(entry.getValue())) { //top if (entry.getKey().startsWith("image_top")) { topMap.put(entry.getKey().replace("image_top_", ""), entry.getValue()); } //bottom if (entry.getKey().startsWith("image_bottom")) { bottomMap.put(entry.getKey().replace("image_bottom_", ""), entry.getValue()); } ClogManager.info("内容", entry.getValue()); } } } catch (Exception e) { } result.put("top", topMap); result.put("bottom", bottomMap); return result; } }
在开发这个工具的途中遇到问题:在本地win系统上图片drawString时,中文显示正常,但是到linux系统时,中文就显示不出来,显示的是方框,造成这种问题是由于操作系统不支持中文字体导致,最终最佳的解决方案是,下载需要的字体,放根目录,通过读取文件的方式获得字体,
java.awt.Font类方法createFont获取文件的方式获得字体,从而改变drawString画中文不异常,此解决方案不必改动linux系统字体
以上是关于zxing二维码生成工具类的主要内容,如果未能解决你的问题,请参考以下文章