Java实现创建和解析带图标的二维码

二维码工具类

用到的jar包:

<dependency>
	<groupId>com.google.zxing</groupId>
	<artifactId>core</artifactId>
	<version>${zxingcore.version}</version>
</dependency>

<dependency>
	<groupId>com.google.zxing</groupId>
	<artifactId>javase</artifactId>
	<version>${zxingse.version}</version>
</dependency>

代码:

package com.util.qrcode;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.NotFoundException;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import java.awt.BasicStroke;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.OutputStream;
import java.util.Hashtable;
import javax.imageio.ImageIO;


/**
 * <p>Description: 二维码工具类</p>
 * <p>Copyright: Copyright (c) 2020</p>
 * @author ZhangLang
 * Create Time: 2020年1月15日 上午11:18:34
 */
public class QRCodeUtil {
    private static final String CHARSET = "utf-8";
    private static final String FORMAT_NAME = "jpg";

    // 二维码尺寸,像素
    private int QRCODE_SIZE = 500;

    // LOGO尺寸,像素
    private int LOGO_SIZE = 166;

    //背景色白色
    private int offColor = 0xFFFFFFFF;

    //前景色,默认黑色
    private int onColor = 0xFF000000;

    /**
     * 设置二维码颜色
     * @param onColor        16进制颜色,例如:0xFF000000,0xFF为前缀,000000为16进制颜色
     */
    public void setOnColor(int onColor) {
        this.onColor = onColor;
    }

    /**
     * 设置二维码大小,默认500
     * @param qRCODE_SIZE 像素
     */
    public void setQRCodeSize(int qRCODE_SIZE) {
        QRCODE_SIZE = qRCODE_SIZE;
    }

    /**
     * 设置二维码logo大小, 默认166
     * @param lOGO_SIZE 像素
     */
    public void setLogoSize(int lOGO_SIZE) {
        LOGO_SIZE = lOGO_SIZE;
    }

    /**
     * Description: 创建文件夹, 当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.(mkdir如果父目录不存在则会抛出异常)
     * Create Time: 2020年1月15日 上午11:34:10
     * @author ZhangLang
     * @param destPath
     */
    private File mkdirs(String destPath) {
        File file = new File(destPath);

        if (!file.exists() && !file.isDirectory()) {
            file.mkdirs();
        }

        return file;
    }

    /**
     * Description: 生成二维码图片,并嵌入二维码logo
     * @param content                二维码内容
     * @param imgPath                嵌入logo图片路径
     * @return
     * @throws Exception
     */
    private BufferedImage createImage(String content, String imgPath)
        throws Exception {
        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
        hints.put(EncodeHintType.MARGIN, 0);

        BitMatrix bitMatrix = new MultiFormatWriter().encode(content,
                BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, 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) ? onColor : offColor);
            }
        }
        if ((imgPath == null) || "".equals(imgPath)) {
            return image;
        }
        // 插入图片
        this.insertImage(image, imgPath, true);
        
        return image;
    }

    /**
     * Description: 向二维码中插入logo
     * @param source        二维码图片
     * @param imgPath        logo路径
     * @param needCompress        是否需要压缩logo
     * @throws Exception
     */
    private void insertImage(BufferedImage source, String imgPath,
        boolean needCompress) throws Exception {
        File file = new File(imgPath);

        if (!file.exists()) {
            return;
        }

        Image src = ImageIO.read(new File(imgPath));
        int width = src.getWidth(null);
        int height = src.getHeight(null);

        if (needCompress) { // 压缩LOGO
           	// logo图片不要超过二维码尺寸的50%
            if ((QRCODE_SIZE / 2.5) < LOGO_SIZE) {
                LOGO_SIZE = (int) (QRCODE_SIZE / 2.5);
            }
            width = LOGO_SIZE;
            height = LOGO_SIZE;

            Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);
            BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics g = tag.getGraphics();
            g.drawImage(image, 0, 0, null); // 绘制缩小后的图
            g.dispose();
            src = image;
        }

        // 插入LOGO
        Graphics2D graph = source.createGraphics();
        //给graph带上反锯齿属性
        graph.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        graph.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        int x = (QRCODE_SIZE - width) / 2;
        int y = (QRCODE_SIZE - height) / 2;
        graph.drawImage(src, x, y, width, height, null);

        Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
        graph.setStroke(new BasicStroke(3f));
        graph.draw(shape);
        graph.dispose();
    }

    /**
     * Description:        生成带logo二维码
     * @param content        内容
     * @param imgPath        logo图片路径
     * @param destPath        二维码图片存储路径
     * @throws Exception
     */
    public File encode(String content, String imgPath, String destPath) {
        File file = null;
        try {
            BufferedImage image = this.createImage(content, imgPath);
            file = mkdirs(destPath);
            ImageIO.write(image, FORMAT_NAME, file);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return file;
    }

    /**
     * Description: 生成普通二维码
     * @param content        内容
     * @param destPath        二维码图片存储路径
     * @return
     * @throws Exception
     */
    public File encode(String content, String destPath) {
        return this.encode(content, null, destPath);
    }

    /**
     * Description: 生成带logo二维码并写入output
     * @param content        内容
     * @param imgPath        logo图片路径
     * @param output
     * @throws Exception
     */
    public void encode(String content, String imgPath, OutputStream output) {
        try {
            BufferedImage image = this.createImage(content, imgPath);
            ImageIO.write(image, FORMAT_NAME, output);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Description:         生成普通二维码并写入output
     * @param content        内容
     * @param output
     * @throws Exception
     */
    public void encode(String content, OutputStream output) {
        this.encode(content, null, output);
    }

    /**
     * Description: 解析二维码内容
     * @param file 二维码图片文件
     * @return
     * @throws Exception
     */
    public String decode(File file) {
        String resultStr = "";

        try {
            BufferedImage image = ImageIO.read(file);
            if (image == null) {
                return resultStr;
            }

            BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

            Hashtable<DecodeHintType, String> hints = new Hashtable<DecodeHintType, String>();
            hints.put(DecodeHintType.CHARACTER_SET, CHARSET);

            try {
                Result result = new MultiFormatReader().decode(bitmap, hints);
                resultStr = result.getText();
            } catch (NotFoundException e) {
                //没有读取到二维码内容
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultStr;
    }

    /**
     * Description: 解析二维码内容
     * @param path 二维码图片路径
     * @return
     * @throws Exception
     */
    public String decode(String path) {
        File file = new File(path);
        if (!file.exists()) {
            return "";
        }
        return this.decode(file);
    }

    public static void main(String[] args) {
        String logoPath = "E:\\qrCode\\saif-icon.png";
        String content = "4004378093";
        QRCodeUtil qrCodeUtil = new QRCodeUtil();
        qrCodeUtil.setOnColor(0xFF333333);
        qrCodeUtil.setLogoSize(166);

        File file = qrCodeUtil.encode(content, logoPath,
                "E:\\qrCode\\qrcode\\qrcode3.png");
        String qrcodePath = file.getAbsolutePath();
        System.out.println("-->" + qrcodePath);

        String result = qrCodeUtil.decode(qrcodePath);
        System.out.println("--->" + result);
    }
}
posted @ 2021-12-09 19:27  CheungLang  阅读(233)  评论(0)    收藏  举报