zxing生成、解析二维码,条形码

1、maven依赖

XML 复制代码
        <!--zxing依赖-->
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>core</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>javase</artifactId>
            <version>3.1.0</version>
        </dependency>

2、一些重要属性方法

BarcodeFormat (码类型)

设置生成条形码的类型。

如:二维码、EAN-13码、UPC-A码、Code-128码、Code-39码等等。

|---------------------------------------------------|
| 条形码类型 |
| BarcodeFormat.AZTEC 阿兹特克码 |
| BarcodeFormat.CODABAR Codabar码 |
| BarcodeFormat.CODE_39 CODE-30码 |
| BarcodeFormat.CODE_93 CODE-93码 |
| BarcodeFormat.CODE_128 CODE-128码 |
| BarcodeFormat.DATA_MATRIX 矩阵式二维条码 |
| BarcodeFormat.EAN_8 EAN-8码 |
| BarcodeFormat.EAN_13 EAN-13码 |
| BarcodeFormat.ITF 交插二五条码 |
| BarcodeFormat.MAXICODE MaxiCode二维条码 |
| BarcodeFormat.PDF_417 PDF417 |
| BarcodeFormat.QR_CODE 二维码 |
| BarcodeFormat.RSS_14 RSS 14 |
| BarcodeFormat.RSS_EXPANDED RSS EXPANDED |
| BarcodeFormat.UPC_A UPC A |
| BarcodeFormat.UPC_E UPC E |
| BarcodeFormat.UPC_EAN_EXTENSION UPC EAN EXTENSION |

EncodeHintType(自定义属性)

3、带logo得到二维码生成

java 复制代码
/**
 * @description: 二维码生成
 * @author: HK
 * @since: 2024/11/4 10:16
 */
public class Test3 {
    private static final Integer CODE_WIDTH = 300;                 // 基础属性:二维码宽度,单位像素
    private static final Integer CODE_HEIGHT = 300;                // 基础属性:二维码高度,单位像素
    private static final Integer FRONT_COLOR = 0x000000;           // 基础属性:二维码前景色,0x000000 表示黑色
    private static final Integer BACKGROUND_COLOR = 0xFFFFFF;      // 基础属性:二维码背景色,0xFFFFFF 表示白色
    public static void main(String[] args) throws Exception {
        //设置生成二维码的内容
        String qrMessage = "https://www.baidu.com";

        // EncodeHintType:编码提示类型,枚举类型
        //    EncodeHintType.CHARACTER_SET:设置字符编码类型
        //    EncodeHintType.ERROR_CORRECTION:设置误差校正
        //    ErrorCorrectionLevel:误差校正等级,
        //          L = ~7% correction、M = ~15% correction、
        //          Q = ~25% correction、H = ~30% correction
        //      不设置时,默认为 L 等级,等级不一样,生成的图案不同,但扫描的结果是一样的
        //    EncodeHintType.MARGIN:设置二维码边距,单位像素,值越小,二维码距离四周越近
        Map<EncodeHintType, Object> typeObjectHashMap = new HashMap<EncodeHintType, Object>();
        typeObjectHashMap.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        typeObjectHashMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
        typeObjectHashMap.put(EncodeHintType.MARGIN, 1);

        // MultiFormatWriter:多格式写入,这是一个工厂类,里面重载了两个 encode 方法,用于写入条形码或二维码
        // encode(String contents,BarcodeFormat format,int width, int height,Map<EncodeHintType,?> hints)
        //      参数1:contents:条形码/二维码内容
        //      参数2:format:编码类型,如 条形码,二维码 等
        //      参数3:width:码的宽度
        //      参数4:height:码的高度
        //      参数5:hints:码内容的编码类型
        // BarcodeFormat:枚举该程序包已知的条形码格式,即创建何种码,如 1 维的条形码,2 维的二维码 等
        // BitMatrix:位(比特)矩阵或叫2D矩阵,也就是需要的二维码
        MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
        BitMatrix bitMatrix = multiFormatWriter
                .encode(qrMessage, BarcodeFormat.QR_CODE, CODE_WIDTH, CODE_HEIGHT, typeObjectHashMap);

        // java.awt.image.BufferedImage:具有图像数据的可访问缓冲图像,实现了 RenderedImage 接口
        // BitMatrix 的 get(int x, int y) 获取比特矩阵内容,指定位置有值,则返回true,将其设置为前景色,否则设置为背景色
        // BufferedImage 的 setRGB(int x, int y, int rgb) 方法设置图像像素
        //      参数1 x:像素位置的横坐标,即列
        //      参数2 y:像素位置的纵坐标,即行
        //      参数3 rgb:像素的值,采用 16 进制,如 0xFFFFFF 白色
        BufferedImage bufferedImage = new BufferedImage(CODE_WIDTH, CODE_HEIGHT, BufferedImage.TYPE_INT_BGR);
        for (int x = 0; x < CODE_WIDTH; x++) {
            for (int y = 0; y < CODE_HEIGHT; y++) {
                bufferedImage.setRGB(x, y, bitMatrix.get(x, y) ? FRONT_COLOR : BACKGROUND_COLOR);
            }
        }

        // 把logo图片设置到二维码中间位置(若不想在二维码中间插入logo图片则不执行此条代码)
        insertLogoImage(bufferedImage, new FileInputStream("d://hello.jpg"));

        // javax.imageio.ImageIO java扩展的图像IO
        // write(RenderedImage im,String formatName,File output)
        //      im:待写入的图像
        //      formatName:图像写入的格式
        //      output:写入的图像文件,文件不存在时会自动创建
        // 即将保存的二维码图片文件
        ImageIO.write(bufferedImage, "png", new FileOutputStream("d://hello.png"));
    }

    /***
     * 为二维码插入中间的logo图片
     * @param bufferedImage 二维码图片信息
     * @param logoInput logo图片位置
     * @throws IOException  抛出IO异常
     */
    private static void insertLogoImage(BufferedImage bufferedImage, InputStream logoInput) throws IOException {
        // 加载Logo图片到Image对象
        Image logoImage = ImageIO.read(logoInput);
        // 设置二维码中间的Logo图片(设置logo图片的宽高需要保持和二维码宽高的一半宽高)
        int logoWidth = CODE_WIDTH / 5;
        int logoHeight = CODE_HEIGHT / 5;
        // 按照指定的宽高进行等比缩放(若设置的宽高比之前大则代表放大),并将缩放后的图片绘制到一个新的BufferedImage对象中
        Image image = logoImage.getScaledInstance(logoWidth, logoHeight, Image.SCALE_SMOOTH);
        BufferedImage logoBufferedImage = new BufferedImage(logoWidth, logoHeight, BufferedImage.TYPE_INT_RGB);
        // 获取图形上下文对象,用于后续将缩放后的图片绘制在 logoBufferedImage 对象上
        Graphics graphics = logoBufferedImage.getGraphics();
        // 绘制缩放后的图片到 logoBufferedImage 对象上,使其填满整个画布
        graphics.drawImage(image, 0, 0, null);
        // 释放图形上下文对象,避免内存泄漏
        graphics.dispose();
        // 把处理好的logo图片再次设置给之前的logo图片对象
        logoImage = image;

        // 开始把logo图片插入到二维码的中间位置
        // 获取 Graphics2D 对象,用于后续在 bufferedImage 上绘制二维码和 logo 图片
        Graphics2D graph = bufferedImage.createGraphics();
        // 计算出 logo 图片在二维码中间的坐标点 (x, y),以便后续将 logo 图片插入到正确的位置。
        int x = (CODE_WIDTH - logoWidth) / 2;
        int y = (CODE_HEIGHT - logoHeight) / 2;
        // 绘制缩放后的 logo 图片到二维码中间位置
        graph.drawImage(logoImage, x, y, logoWidth, logoHeight, null);
        // 设置边框的线条粗细为 3 像素,并且设置线条是一个圆角矩形,6表示圆角的半径。并关闭资源
        graph.setStroke(new BasicStroke(3f));
        graph.draw(new RoundRectangle2D.Float(x, y, logoWidth, logoHeight, 6, 6));
        graph.dispose();
    }
}

4、解析二维码

java 复制代码
/**
 * 二维码解析
 *
 * @author Anhui OuYang
 * @version 1.0
 **/
public class QRCodeParsing {

    public static void main(String[] args) throws Exception {
        System.out.println("=========================二维码解析 Start=========================");
        parsingQRCode(new File("d://222.png"));
        System.out.println("=========================二维码解析 End=========================");
    }

    /***
     * 二维码(QR_CODE)解析
     * @param file 文件路径信息
     */
    public static void parsingQRCode(File file) throws IOException, NotFoundException {
        //创建一个图像数据缓冲区类(并读取二维码图片)
        BufferedImage bufferedImage = ImageIO.read(file);

        // 对图片信息的图像处理和分析
        // 注意需要 zxing 库的版本 3.2.1 或更高版本才能使用,若没有则使用我下面定义的getRGBPixelData(BufferedImage image)
        BufferedImageLuminanceSource luminanceSource = new BufferedImageLuminanceSource(bufferedImage);
        // 若版本不够则使用这种方式
        // RGBLuminanceSource luminanceSource = new RGBLuminanceSource(bufferedImage.getWidth(),
        //         bufferedImage.getHeight(), getRGBPixelData(bufferedImage));

        // 创建BinaryBitmap对象
        // BinaryBitmap是二值化位图,将像素从RGB空间转换为黑白颜色空间
        BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(luminanceSource));

        // 设置解码参数
        Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();
        hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");   // 设置解析的字符集

        // 使用 MultiFormatReader 进行解码
        MultiFormatReader formatReader = new MultiFormatReader();
        formatReader.setHints(hints);                               // 设置解码一些参数
        Result result = formatReader.decode(binaryBitmap);          // 解码(解析binaryBitmap数据)

        // 打印一些信息
        System.out.println("二维码解析图片的路径:   " + file.getPath());
        System.out.println("二维码解析图片中格式:   " + result.getBarcodeFormat());
        System.out.println("二维码解析图片中内容:   " + result.getText());
    }

   
}

5、条形码

简单条形码(无文字)

java 复制代码
public class GenerateBarcode {

    private static final Integer CODE_WIDTH = 300;                 // 基础属性:二维码宽度,单位像素
    private static final Integer CODE_HEIGHT = 150;                // 基础属性:二维码高度,单位像素
    private static final Integer FRONT_COLOR = 0x000000;           // 基础属性:二维码前景色,0x000000 表示黑色
    private static final Integer BACKGROUND_COLOR = 0xFFFFFF;      // 基础属性:二维码背景色,0xFFFFFF 表示白色

    public static void main(String[] args) throws Exception {

        //设置生成条形码的内容(注:条形码信息一定要按照格式,如随便一个商品上的条形码都行,但必须是EAN_13格式)
        String qrMessage = "6971483746515";

        // EncodeHintType:指定和控制码生成器的一些参数的类
        Map<EncodeHintType, Object> typeObjectHashMap = new HashMap<EncodeHintType, Object>();
        // 设置编码
        typeObjectHashMap.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        // 设置容错等级
        typeObjectHashMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        // 设置边距,默认为5
        typeObjectHashMap.put(EncodeHintType.MARGIN, 3);

        // MultiFormatWriter:用于写入条形码或二维码
        MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
        BitMatrix bitMatrix = multiFormatWriter
                .encode(qrMessage, BarcodeFormat.EAN_13, CODE_WIDTH, CODE_HEIGHT, typeObjectHashMap);

        // java.awt.image.BufferedImage:把条形码信息转换为图像信息
        BufferedImage bufferedImage = new BufferedImage(CODE_WIDTH, CODE_HEIGHT, BufferedImage.TYPE_INT_BGR);
        for (int x = 0; x < CODE_WIDTH; x++) {
            for (int y = 0; y < CODE_HEIGHT; y++) {
                bufferedImage.setRGB(x, y, bitMatrix.get(x, y) ? FRONT_COLOR : BACKGROUND_COLOR);
            }
        }

        // javax.imageio.ImageIO 将图片信息写出到文件
        ImageIO.write(bufferedImage, "png", new FileOutputStream("d://222.png"));
    }

}

条形码(含文字)

java 复制代码
/**
 * 一个简单的条形码生成
 *
 * @author Anhui OuYang
 * @version 1.0
 **/
public class GenerateBarcode {

    private static final Integer CODE_WIDTH = 300;                 // 基础属性:二维码宽度,单位像素
    private static final Integer CODE_HEIGHT = 150;                // 基础属性:二维码高度,单位像素
    private static final Integer FRONT_COLOR = 0x000000;           // 基础属性:二维码前景色,0x000000 表示黑色
    private static final Integer BACKGROUND_COLOR = 0xFFFFFF;      // 基础属性:二维码背景色,0xFFFFFF 表示白色

    public static void main(String[] args) throws Exception {
        // 条形码底部内容
        String bottomStr = "123456";
        // 条形码左上角内容
        //String topLeftStr = name.length() < 11 ? name : name.substring(0, 11);
        String topLeftStr = "ceshi";
        // 条形码右上角内容
        String topRightStr = "2024-11-4";
        // 生成条形码
        BufferedImage barCodeImage = create(bottomStr, 250, 50);
        BufferedImage withWords = createWithWords(
                barCodeImage,
                bottomStr,
                topLeftStr,
                topRightStr,
                250,
                150,
                10,
                14);
        ImageIO.write(withWords, "png", new FileOutputStream("d://222.png"));

        barCodeImage = create(bottomStr, 350, 70);
        withWords = createWithWords(
                barCodeImage,
                bottomStr,
                topLeftStr,
                topRightStr,
                350,
                210,
                14,
                20);
        ImageIO.write(withWords, "png", new FileOutputStream("d://333.png"));

        barCodeImage = create(bottomStr, 500, 100);
        withWords = createWithWords(
                barCodeImage,
                bottomStr,
                topLeftStr,
                topRightStr,
                500,
                300,
                20,
                28);
        ImageIO.write(withWords, "png", new FileOutputStream("d://444.png"));
    }

    /**
     * 生成简单条形码(无文字)
     *
     * @param content
     * @param width
     * @param height
     * @return
     */
    public static BufferedImage create(String content, int width, int height) {
        // 定义位图矩阵BitMatrix
        BitMatrix matrix = null;

        try {
            // 定义二维码参数
            Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>(3);
            // 设置编码
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            // 设置容错等级
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
            // 设置边距,默认为5
            hints.put(EncodeHintType.MARGIN, 3);

            // 使用code_128格式进行编码生成条形码
            MultiFormatWriter writer = new MultiFormatWriter();
            matrix = writer.encode(content, BarcodeFormat.CODE_128, width, height, hints);
        } catch (WriterException e) {
            e.printStackTrace();
            //throw new RuntimeException("条形码内容写入失败");
        }

        return MatrixToImageWriter.toBufferedImage(matrix);
    }


    /**
     * 生成条形码(含文字)
     * ****************************************************
     * ----------------------------------------------
     * |                         2023-06-10 10:55   |
     * |                                            |
     * |            商品名称 /超出不显示/              |
     * |                                            |
     * |    | || ||| | || |||| | | | ||| | | ||     |
     * |    | || ||| | || |||| | | | ||| | | ||     |
     * |    | || ||| | || |||| | | | ||| | | ||     |
     * |    | || ||| | || |||| | | | ||| | | ||     |
     * |               13800000000                  |
     * ----------------------------------------------
     * ===================================================
     * 1、日期:顶部右侧
     * 2、商品名称:居中
     * 3、条形码:商品名称下方,且居中
     * 4、条码内容:条形码下方,且居中
     * *****************************************************
     *
     * @param codeImage     条形码图片
     * @param bottomStr     底部文字
     * @param titleStr      标题文字
     * @param topRightStr   右上角文字
     * @param pictureWidth  图片宽度
     * @param pictureHeight 图片高度
     * @param margin        边距
     * @param fontSize      字体大小
     * @return 条形码图片
     */
    private static BufferedImage createWithWords(
            BufferedImage codeImage,
            String bottomStr,
            String titleStr,
            String topRightStr,
            int pictureWidth,
            int pictureHeight,
            int margin,
            int fontSize) {
        BufferedImage picImage = new BufferedImage(pictureWidth, pictureHeight, BufferedImage.TYPE_INT_RGB);

        Graphics2D g2d = picImage.createGraphics();
        // 抗锯齿
        setGraphics2D(g2d);
        // 设置白色
        setColorWhite(g2d, picImage.getWidth(), picImage.getHeight());

        // 条形码默认居中显示
        int codeStartX = (pictureWidth - codeImage.getWidth()) / 2;
        int codeStartY = (pictureHeight - codeImage.getHeight()) / 2 + 2 * margin;
        // 画条形码到新的面板
        g2d.drawImage(codeImage, codeStartX, codeStartY, codeImage.getWidth(), codeImage.getHeight(), null);

        // 给条码上下各画一条线
        // 设置颜色
        g2d.setColor(Color.LIGHT_GRAY);
        int y1 = 2 * margin + codeImage.getHeight();
        int y2 = 2 * margin + 2 * codeImage.getHeight();
        g2d.drawLine(0, y1, pictureWidth, y1);
        g2d.drawLine(0, y2, pictureWidth, y2);

        // 画文字到新的面板
        g2d.setColor(Color.BLACK);
        // 字体、字型、字号
        g2d.setFont(new Font("微软雅黑", Font.PLAIN, fontSize));
        // 文字与条形码之间的间隔
        int wordAndCodeSpacing = 3;

        // 底部文字(居中)
        if (StringUtils.isNotEmpty(bottomStr)) {
            // 文字长度
            int strWidth = g2d.getFontMetrics().stringWidth(bottomStr);
            // 文字X轴开始坐标
            int strStartX = (pictureWidth - strWidth) / 2;
            if (strStartX < margin) {
                strStartX = margin;
            }
            // 文字Y轴开始坐标
            int strStartY = codeStartY + codeImage.getHeight() + fontSize + wordAndCodeSpacing;
            // 画文字
            g2d.drawString(bottomStr, strStartX, strStartY);
        }

        // 右上角文字
        if (StringUtils.isNotEmpty(topRightStr)) {
            // 文字长度
            int strWidth = g2d.getFontMetrics().stringWidth(topRightStr);
            // 文字X轴开始坐标
            int strStartX = pictureWidth - strWidth - margin;
            // 文字Y轴开始坐标
            int strStartY = margin + fontSize;
            // 画文字
            g2d.drawString(topRightStr, strStartX, strStartY);
        }

        // 标题文字(居中)
        if (StringUtils.isNotEmpty(titleStr)) {
            if (titleStr.length() > 11) {
                titleStr = titleStr.substring(0, 11);
            }
            // 字体、字型、字号
            int fs = (int) Math.ceil(fontSize * 1.5);
            g2d.setFont(new Font("微软雅黑", Font.PLAIN, fs));
            // 文字长度
            int strWidth = g2d.getFontMetrics().stringWidth(titleStr);
            // 文字X轴开始坐标
            int strStartX = (pictureWidth - strWidth) / 2;
            if (strStartX < margin) {
                strStartX = margin;
            }
            // 文字Y轴开始坐标
            int strStartY = codeStartY - margin;
            // 画文字
            g2d.drawString(titleStr, strStartX, strStartY);
        }

        g2d.dispose();
        picImage.flush();

        return picImage;
    }
    /**
     * 设置 Graphics2D 属性 (抗锯齿)
     *
     * @param g2d Graphics2D提供对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制
     */
    private static void setGraphics2D(Graphics2D g2d) {
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);
        Stroke s = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER);
        g2d.setStroke(s);
    }

    /**
     * 设置背景为白色
     *
     * @param g2d Graphics2D提供对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制
     */
    private static void setColorWhite(Graphics2D g2d, int width, int height) {
        g2d.setColor(Color.WHITE);
        // 填充整个屏幕
        g2d.fillRect(0, 0, width, height);
        // 设置笔刷
        g2d.setColor(Color.BLACK);
    }


}

解析条形码

java 复制代码
public static void main(String[] args) throws Exception {
        String text = "";
        try {
            BufferedImage image = ImageIO.read(new File("d://444.png"));
            if (image == null) {
                return;
            }
            LuminanceSource source = new BufferedImageLuminanceSource(image);
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

            Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>(3);
            hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
            hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
            hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
            Result result = new MultiFormatReader().decode(bitmap, hints);
            text = result.getText();
            System.out.println(text);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("无法识别");
        }
}
相关推荐
xlsw_3 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹3 小时前
基于java的改良版超级玛丽小游戏
java
远游客07134 小时前
centos stream 8下载安装遇到的坑
linux·服务器·centos
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭4 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
XH华4 小时前
初识C语言之二维数组(下)
c语言·算法
暮湫4 小时前
泛型(2)
java
超爱吃士力架4 小时前
邀请逻辑
java·linux·后端
南宫生4 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
转码的小石4 小时前
12/21java基础
java
不想当程序猿_4 小时前
【蓝桥杯每日一题】求和——前缀和
算法·前缀和·蓝桥杯