Java 生成二維碼 (包含 base64 存在的形式)

1. 導包

<!-- 生成二維碼 -->
<dependency>
	<groupId>com.google.zxing</groupId>
	<artifactId>javase</artifactId>
	<version>3.4.0</version>
</dependency>

2. 工具類

package com.springCloud.user.config.QRCode;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Base64;

/**
 * bases64 與 照片, 照片流的相互轉化
 */

public class ImgBase64 {

    private static Base64.Encoder encoder = Base64.getEncoder();

    private static Base64.Decoder decoder = Base64.getDecoder();

    /**
     * 照片轉化爲 bases64
     *
     * @param path   照片路徑
     * @param suffix 照片格式
     * @return String
     */
    public static String getImageBinary(String path, String suffix) {
        File file = new File(path);
        try {
            BufferedImage read = ImageIO.read(file);
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            ImageIO.write(read, suffix, byteArrayOutputStream);
            byte[] bytes = byteArrayOutputStream.toByteArray();
            return encoder.encodeToString(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 照片流轉化爲 bases64
     *
     * @param bufferedImage 照片流
     * @param suffix        照片格式
     * @return String
     */
    public static String bufferedImageToBase64String(BufferedImage bufferedImage, String suffix) {
        try {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            ImageIO.write(bufferedImage, suffix, byteArrayOutputStream);
            byte[] bytes = byteArrayOutputStream.toByteArray();
            return encoder.encodeToString(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * bases64 轉化爲照片流
     *
     * @param base64String bases64
     * @return String
     */
    public static BufferedImage base64StringToBufferedImage(String base64String) {
        try {
            byte[] decode = decoder.decode(base64String);
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(decode);
            return ImageIO.read(byteArrayInputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * bases64 轉化爲照片
     *
     * @param base64String bases64
     * @param path         照片生成的路徑
     * @param suffix       照片格式
     */
    public static void base64StringToImage(String base64String, String path, String suffix) {
        try {
            byte[] decode = decoder.decode(base64String);
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(decode);
            BufferedImage read = ImageIO.read(byteArrayInputStream);
            File f1 = new File(path);
            ImageIO.write(read, suffix, f1);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

3. 工具類

該工具包括的功能:

  1. 將生成二維碼放在指定路徑
  2. 將生成二維碼以 base64 字符串形式存在
  3. 指定 LOGO 照片路徑嵌入中生成二維碼
  4. 指定 LOGO 的 base64 字符串嵌入中生成二維碼
package com.springCloud.user.config.QRCode;

import com.google.zxing.*;
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 javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Hashtable;
import java.util.Random;

/**
 * 生成二維碼
 */

public class QRCode {

    // 編碼
    private static final String CHARSET = "utf-8";
    // 格式
    private static final String FORMAT_NAME = "png";
    // 二維碼尺寸
    private static final int QR_CODE_SIZE = 300;
    // LOGO 寬度
    private static final int WIDTH = 60;
    // LOGO 高度
    private static final int HEIGHT = 60;

    private static BufferedImage createImage(String content, String imgOrBase64, boolean judgeImgOrBase64, boolean needCompress) throws Exception {
        Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
        //  生成二維碼的容錯等級 M 爲 中級
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
        // 生成二維碼的字符編碼
        hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
        // 生成二維碼的圖片的黑線直接的邊距
        hints.put(EncodeHintType.MARGIN, 1);
        // 二維碼的生成
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QR_CODE_SIZE, QR_CODE_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) ? 0xFF000000 : 0xFFFFFFFF);
            }
        }
        // 插入圖片
        QRCode.insertImage(image, imgOrBase64, judgeImgOrBase64, needCompress);
        return image;
    }

    /**
     * 插入 LOGO
     *
     * @param source           二維碼圖片
     * @param imgOrBase64      LOGO 圖片的存在形式
     * @param judgeImgOrBase64 判斷 LOGO 存在形式
     * @param needCompress     是否壓縮
     * @throws Exception Exception
     */
    private static void insertImage(BufferedImage source, String imgOrBase64, boolean judgeImgOrBase64, boolean needCompress) throws Exception {
        Image bufferedImage;
        if (judgeImgOrBase64) {
            File file = new File(imgOrBase64);
            if (!file.exists()) {
                System.err.println("" + imgOrBase64 + "   該文件不存在!");
                return;
            }
            bufferedImage = ImageIO.read(new File(imgOrBase64));
        } else {
            bufferedImage = ImgBase64.base64StringToBufferedImage(imgOrBase64);
        }
        if (bufferedImage != null) {
            int width = bufferedImage.getWidth(null);
            int height = bufferedImage.getHeight(null);

            // 壓縮 LOGO
            if (needCompress) {
                if (width > WIDTH) {
                    width = WIDTH;
                }
                if (height > HEIGHT) {
                    height = HEIGHT;
                }
                Image image = bufferedImage.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();
                bufferedImage = image;
            }
            // 插入 LOGO
            Graphics2D graph = source.createGraphics();
            int x = (QR_CODE_SIZE - width) / 2;
            int y = (QR_CODE_SIZE - height) / 2;
            graph.drawImage(bufferedImage, 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();
        }
    }

    /**
     * 生成二維碼 (內嵌 LOGO)
     *
     * @param content          內容
     * @param imgOrBase64      LOGO 存在形式
     * @param judgeImgOrBase64 判斷 LOGO 存在形式
     * @param destPath         存放目錄
     * @param needCompress     是否壓縮 LOGO
     * @throws Exception Exception
     */
    private static String encode(String content, String imgOrBase64, boolean judgeImgOrBase64, String destPath, boolean needCompress) throws Exception {
        BufferedImage image = QRCode.createImage(content, imgOrBase64, judgeImgOrBase64, needCompress);
        mkdirs(destPath);
        String file = new Random().nextInt(99999999) + "." + FORMAT_NAME;
        ImageIO.write(image, FORMAT_NAME, new File(destPath + "/" + file));
        return file;
    }

    /**
     * 當文件夾不存在時, mkdirs 會自動創建多層目錄, 區別於 mkdir. (mkdir 如果父目錄不存在則會拋出異常)
     *
     * @param destPath 存放目錄
     */
    private static void mkdirs(String destPath) {
        File file = new File(destPath);
        if (!file.exists() && !file.isDirectory()) {
            file.mkdirs();
        }
    }

    /**
     * 解析二維碼
     *
     * @param file 二維碼圖片
     * @return String
     * @throws Exception Exception
     */
    private static String decode(File file) throws Exception {
        BufferedImage image;
        image = ImageIO.read(file);
        if (image == null) {
            return null;
        }
        BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
        Result result;
        Hashtable<DecodeHintType, Object> hints = new Hashtable<>();
        hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
        result = new MultiFormatReader().decode(bitmap, hints);
        return result.getText();
    }

    /**
     * 解析二維碼
     *
     * @param path 二維碼圖片地址
     * @return String
     * @throws Exception Exception
     */
    public static String decode(String path) throws Exception {
        return QRCode.decode(new File(path));
    }

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章