Java 利用ZXing生成二维码与解析

生成二维码的方式有多种,这里使用 Google的 Zxing 架包。在maven项目中添加依赖

        <!-- 二维码相关:添加Zxing的依赖-->
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>core</artifactId>
            <version>3.3.3</version>
        </dependency>
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>javase</artifactId>
            <version>3.3.3</version>
        </dependency>

二维码主要包括两各方面:

1)将信息生成二维码展示(图片,字节数组),中文信息慎用,注意乱码问题

2)解析二维码读取其字符串信息。

     参数传入二维码文件或者 InputStream流都可以,将二维码加载都内存中(BufferedImage),然后根据Zing的API解析

 

1、生成简单二维码并解析


import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

/**
 * 生成二维码工具类
 */
public class QRCodeUtil {
    private static final String CHARSET = "UTF-8";
    private static final String FORMAT_NAME = "JPG";

    private QRCodeUtil(){}

    /**
     * 生成二维码图片,传文件流
     * @param content 内容
     * @param width 宽度
     * @param height 高度
     * @param outputStream 输出流
     * @throws IOException
     * @throws WriterException
     */
    public static void generateQRCodeImage(String content, int width, int height, OutputStream outputStream) throws IOException, WriterException {
        // 用于设置QR二维码参数
        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
        // 设置QR二维码的纠错级别——这里选择最高H级别
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        // 设置编码方式
        hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height,hints);
        MatrixToImageWriter.writeToStream(bitMatrix,FORMAT_NAME,outputStream);
    }
    /**
     * 生成二维码图片,传文件path
     * @param content 内容
     * @param width 宽度
     * @param height 高度
     * @param filePath 文件路径
     * @throws IOException
     * @throws WriterException
     */
    public static void generateQRCodeImage(String content, int width, int height, String filePath) throws IOException,
            WriterException {
        // 用于设置QR二维码参数
        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
        // 设置QR二维码的纠错级别——这里选择最高H级别
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        // 设置编码方式
        hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
        BitMatrix bitMatrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, width, height,hints);
        Path path = FileSystems.getDefault().getPath(filePath);
        MatrixToImageWriter.writeToPath(bitMatrix,FORMAT_NAME,path);
    }

    /**
     * 生成二维码返回byte数组
     * @param content 内容
     * @param width 宽度
     * @param height 高度
     * @return 二维码的byte数组
     */
    public static byte[] getQRCodeImage(String content, int width, int height) throws IOException, WriterException {
        ByteArrayOutputStream pngOutputStream = new ByteArrayOutputStream();
        // 用于设置QR二维码参数
        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
        // 设置QR二维码的纠错级别——这里选择最高H级别
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        // 设置编码方式
        hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
        BitMatrix bitMatrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, width, height,hints);
        MatrixToImageWriter.writeToStream(bitMatrix, FORMAT_NAME, pngOutputStream);
        return pngOutputStream.toByteArray();
    }

    /**
     *  解析二维码获取内容
     * @param file 二维码文件,或定义InputStream
     * @return 二维码包含的字符串信息
     * @throws Exception
     */
    public static String decodeQRCodeImage(File file) throws Exception {
        if (!file.exists()) {
            return null;
        }
        BufferedImage image = ImageIO.read(file);
        BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

        Map hints = new HashMap<DecodeHintType, Object>();
        hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
        Result result = new MultiFormatReader().decode(bitmap, hints);
        return result.getText();
    }

    public static void main(String[] args) throws Exception {
        // 生成二维码都OK
        /*String filePath = "E:/java/as1234.jpg";
        //QRCodeUtil.generateQRCodeImage("https://www.baidu.com",550,550,filePath);

        FileOutputStream outputStream = new FileOutputStream(filePath);
        //QRCodeUtil.generateQRCodeImage("asdaklj123112abc",550,550,outputStream);

        byte[] data = QRCodeUtil.getQRCodeImage("发送端sadds12312", 550, 500);
        outputStream.write(data);
        outputStream.close();*/

        // 解析二维码
        String resultStr = QRCodeUtil.decodeQRCodeImage(new File("E:/java/as1234.jpg"));
        System.out.println(resultStr);
    }
}

             

2、生成二维码中间带logo,底部带文字说明


import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

/**
 * 生成二维码工具类
 */
public class QRCodeUtil {
    private static final String CHARSET = "UTF-8";
    private static final String FORMAT_NAME = "JPG";

    private QRCodeUtil(){}

    /**
     * 生成二维码图片,传文件流
     * @param content 内容
     * @param width 宽度
     * @param height 高度
     * @param outputStream 输出流
     * @throws IOException
     * @throws WriterException
     */
    public static void generateQRCodeImage(String content, int width, int height, OutputStream outputStream) throws IOException, WriterException {
        // 用于设置QR二维码参数
        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
        // 设置QR二维码的纠错级别——这里选择最高H级别
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        // 设置编码方式
        hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height,hints);
        MatrixToImageWriter.writeToStream(bitMatrix,FORMAT_NAME,outputStream);
    }
    /**
     * 生成二维码图片,传文件path
     * @param content 内容
     * @param width 宽度
     * @param height 高度
     * @param filePath 文件路径
     * @throws IOException
     * @throws WriterException
     */
    public static void generateQRCodeImage(String content, int width, int height, String filePath) throws IOException,
            WriterException {
        // 用于设置QR二维码参数
        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
        // 设置QR二维码的纠错级别——这里选择最高H级别
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        // 设置编码方式
        hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
        BitMatrix bitMatrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, width, height,hints);
        Path path = FileSystems.getDefault().getPath(filePath);
        MatrixToImageWriter.writeToPath(bitMatrix,FORMAT_NAME,path);
    }

    /**
     * 生成二维码返回byte数组
     * @param content 内容
     * @param width 宽度
     * @param height 高度
     * @return 二维码的byte数组
     */
    public static byte[] getQRCodeImage(String content, int width, int height) throws IOException, WriterException {
        ByteArrayOutputStream pngOutputStream = new ByteArrayOutputStream();
        // 用于设置QR二维码参数
        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
        // 设置QR二维码的纠错级别——这里选择最高H级别
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        // 设置编码方式
        hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
        BitMatrix bitMatrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, width, height,hints);
        MatrixToImageWriter.writeToStream(bitMatrix, FORMAT_NAME, pngOutputStream);
        return pngOutputStream.toByteArray();
    }

    /**
     *  解析二维码获取内容
     * @param file 二维码文件,或定义InputStream
     * @return 二维码包含的字符串信息
     * @throws Exception
     */
    public static String decodeQRCodeImage(File file) throws Exception {
        if (!file.exists()) {
            return null;
        }
        BufferedImage image = ImageIO.read(file);
        BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

        Map hints = new HashMap<DecodeHintType, Object>();
        hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
        Result result = new MultiFormatReader().decode(bitmap, hints);
        return result.getText();
    }

    /**
     *  给二维码插入logo图片
     * @param data 二维码的字节数据,也可以是二维码文件,将二维码数据加载进内存处理就ok
     * @param logoFile logo图片所在的路径
     * @param needCompressed 是否需要压缩logo图片
     * @return 带logo二维码的byte数组
     * @throws IOException
     */
    private static byte[] addLogoImage(byte[] data, File logoFile, boolean needCompressed) throws IOException {
        if (!logoFile.exists()){
            System.out.println("logo文件不存在");
            return null;
        }

        BufferedImage qrcodeImage = ImageIO.read(new ByteArrayInputStream(data)); //data图片数据加载进内存
        int qrcodeWidth = qrcodeImage.getWidth(null);
        int qrcodeHeight = qrcodeImage.getHeight(null);
        Image logoImage = ImageIO.read(logoFile);
        int logoWidth = logoImage.getWidth(null);
        int logoHight = logoImage.getHeight(null);

        // 压缩logo图片
        if (needCompressed) {
            if (logoWidth > qrcodeWidth) logoWidth = qrcodeWidth/5;
            if (logoHight > qrcodeHeight) logoHight = qrcodeHeight/5;

            Image src = logoImage.getScaledInstance(logoWidth, logoWidth, Image.SCALE_SMOOTH); //创建此图像的缩放版本。
            BufferedImage tag = new BufferedImage(logoWidth, logoWidth, BufferedImage.TYPE_INT_RGB);
            Graphics2D graphics = tag.createGraphics();
            graphics.drawImage(src, 0, 0, null);// 绘制当前可用的指定图像的大小。
            graphics.dispose();  // 释放占有的资源
            logoImage = src;
        }
        //logoWidth = logoImage.getWidth(null);
        //logoHight = logoImage.getHeight(null);

        // 插入logo图片
        Graphics2D graphics = qrcodeImage.createGraphics();
        int x = (qrcodeWidth - logoWidth) / 2;
        int y = (qrcodeHeight - logoHight) / 2;
        graphics.drawImage(logoImage, x, y, logoWidth, logoHight, null);
        Shape shape = new RoundRectangle2D.Float(x, y, logoWidth, logoHight, 6, 6);
        graphics.setStroke(new BasicStroke(3f));
        graphics.draw(shape);
        graphics.dispose();

        // 带logo二维码返回
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ImageIO.write(qrcodeImage, FORMAT_NAME, bos);
        return bos.toByteArray();
    }

    /**
     *  给二维码底部添加文字
     * @param data 二维码的字节数据
     * @param text 底部文字
     * @param fontName 字体名
     * @param fontStyle 字体样式
     * @param color 字体颜色
     * @param fontSize 字体大小
     * @return 带文字二维码的byte数组
     * @throws IOException
     */
    public static byte[] addFontIMage(byte[] data, String text,String fontName,int fontStyle, Color color,
                                    int fontSize) throws IOException {
        //data图片数据加载进内存
        BufferedImage qrcodeImage = ImageIO.read(new ByteArrayInputStream(data));
        int qrcodeWidth = qrcodeImage.getWidth(null);
        int qrcodeHeight = qrcodeImage.getHeight(null);
        Graphics2D graphics = qrcodeImage.createGraphics();
        Font font = new Font(fontName, fontStyle, fontSize);

        // 文字在图片中的坐标,这里设置在中间
        FontMetrics metrics = graphics.getFontMetrics(font);
        int startX = (qrcodeWidth - metrics.stringWidth(text)) / 2;
        int startY = qrcodeHeight - 10;
        graphics.setColor(color);
        graphics.setFont(font);
        graphics.drawString(text, startX, startY);
        graphics.dispose();

        // 带文字二维码返回
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ImageIO.write(qrcodeImage, FORMAT_NAME, bos);
        return bos.toByteArray();
    }


    public static void main(String[] args) throws Exception {
        File logoFile = new File("E:/java/logo.jpg");
        byte[] data = QRCodeUtil.getQRCodeImage("发送端sadds12312", 550, 550);
        data = QRCodeUtil.addLogoImage(data,logoFile,true);
        // 内存二维码byte数据输出到磁盘
        // 带logo二维码
        FileOutputStream outputStream = new FileOutputStream("E:/java/as1234logo.jpg");
        outputStream.write(data);
        outputStream.close();

        //给logo二维码添加底部文字
        data = QRCodeUtil.addFontIMage(data, "二维码底部文字说明","宋体",Font.PLAIN,Color.BLUE,30);
        outputStream = new FileOutputStream("E:/java/as1234logotext.jpg");
        outputStream.write(data);
        outputStream.close();

        // 解析二维码
        String resultStr = QRCodeUtil.decodeQRCodeImage(new File("E:/java/as1234logotext.jpg"));
        System.out.println(resultStr); // 发送端sadds12312
    }
}

    

 

总结:

1)掌握ZXing核心类解析和生成二维码

     MultiFormatWriter 类或QRCodeWriter类编码和解码来生成和解析二维码

     MatrixToImageWriter 类将内存数据写出去或者使用ImageIO类写

2)掌握Java的核心类:Image,BufferedImage和ImageIO

参考文章:

     利用ZXing工具生成二维码以及解析二维码

 

站在前辈的肩膀上,每天进步一点点

ends~

发布了248 篇原创文章 · 获赞 59 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/qq_42402854/article/details/100289937