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系统字体
时间: 2024-08-05 23:06:44

zxing二维码生成工具类的相关文章

二维码生成工具类

1 package com.ideal.common.util; 2 3 import java.awt.image.BufferedImage; 4 import java.io.File; 5 import java.io.FileInputStream; 6 import java.io.FileNotFoundException; 7 import java.io.FileOutputStream; 8 import java.util.UUID; 9 10 import net.glx

二维码生成工具类java版

注意:这里我不提供所需jar包的路径,我会把所有引用的jar包显示出来,大家自行Google package com.net.util; import java.awt.BasicStroke; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Shape; import java.awt.geom.RoundRectangle2D; import java.a

Java版本logo 名片二维码生成工具类

 package com.zzq; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Shape; import java.awt.font.FontRenderContext; import java.awt.ge

Java 二维码生成工具类

public class QRcodeUtils { /** * 容错率等级 L */ public static final char CORRECT_L = 'L'; /** * 容错率等级 M */ public static final char CORRECT_M = 'M'; /** * 容错率等级 Q */ public static final char CORRECT_Q = 'Q'; /** * 容错率等级 H */ public static final char CORR

google的zxing二维码生成

二维码生成有很多sdk,但本人认为zxing包最好用,以下就是二维码生成的类 import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO;

vue项目条形码和二维码生成工具试用

项目开发需要,优惠券分不同类型,简单的使用id生成条形码供店铺使用,麻烦点的需要多个字段的就需要使用二维码来展示了,对应的效果如下 条形码(一维码)使用工具code128 需引入code128.js 和对应的 code123.css, 具体代码可以看 https://www.jb51.net/article/103472.htm 由于项目是vue开发,所以code128.js 稍微改一下,export 出createBarcode接口 export default function create

python3调用NowAPI接口实现二维码生成工具

本人python学习菜鸟一枚,随着对python的学习,感觉python越来越好玩了,上次用接口查询IP地址后,又看到有道词典查询.二维码生成等接口相关的方法,并对其做了简单的尝试,确实是挺好玩的.所以将整个过程记录下来.分享在此,供大家一起交流学习. 1.基本环境 系统:windows 7 开发环境:pycharm python3 相关的模块和库  urlib  urllib.parse 2.NowAPI简单的介绍 NowAPI是一家 数据服务公司,提供大量的数据接口,对于我们这种学习的菜鸟来

java基于谷歌开发的zxing包开发的二维码生成工具

不得不说,二维码的应用越来越广泛了.废话不多说了.. 此处采用的jar不多,只用zxing包里面的core.jar包即可,大家自行下载, 如果是百度云盘,地址为:http://pan.baidu.com/s/1eQeWFaq 以后很多的博客资源将会更新到这个地址中,大家尽量把资源转移自己的盘,防止链接某天突然挂了. 实例: genQRCode(String content,String url),其中url绝对路径,就是这个类的调用方法,返回值二维码文件名,生成png格式(如需其他,自行更改),

java二维码生成工具

import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.Hashtable; import java.util.Map; import javax.imageio.ImageIO; import com.google.zxing.BarcodeFormat; import com.google.zxing.BinaryBitmap; import