All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.soento.core.util.ZingUtil Maven / Gradle / Ivy

package com.soento.core.util;

import com.google.zxing.*;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.soento.core.enums.DateFormat;
import com.soento.core.util.zxing.ImageLuminanceSource;
import com.soento.core.util.zxing.ImageWriter;
import com.soento.core.util.zxing.LogoConfig;
import org.apache.commons.codec.Charsets;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Date;
import java.util.EnumMap;
import java.util.Map;

/**
 * @author yantao.zeng
 */
public class ZingUtil {
    /**
     * 生成二维码的默认边长,因为是正方形的,所以高度和宽度一致
     */
    private static final int DEFAULT_LENGTH = 400;
    /**
     * 生成二维码的格式
     */
    private static final String FORMAT = "jpg";

    /**
     * 根据内容生成二维码数据
     *
     * @param content 二维码文字内容[为了信息安全性,一般都要先进行数据加密]
     * @param length  二维码图片宽度和高度
     */
    private static BitMatrix createMatrix(String content, int length) {
        Map hints = new EnumMap<>(EncodeHintType.class);
        // 设置字符编码
        hints.put(EncodeHintType.CHARACTER_SET, Charsets.UTF_8.name());
        // 指定纠错等级
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        try {
            return new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, length, length, hints);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 根据指定边长创建生成的二维码
     *
     * @param content    二维码内容
     * @param length     二维码的高度和宽度
     * @param logoFile   logo 文件对象,可以为空
     * @param logoConfig logo 配置,可以为空
     * @return 二维码图片的字节数组
     */
    public static File create(String content, int length, File logoFile, LogoConfig logoConfig) {
        if (logoFile != null && !logoFile.exists()) {
            throw new IllegalArgumentException("请提供正确的logo文件!");
        }
        BitMatrix qrCodeMatrix = createMatrix(content, length);
        if (qrCodeMatrix == null) {
            return null;
        }
        try {
            File file = File.createTempFile(DateFormat.YYYYMMDDHHMISSMS.instance().format(new Date()) + "QR", "." + FORMAT);
            ImageWriter.writeToFile(qrCodeMatrix, FORMAT, file);
            if (logoFile != null) {
                if (logoConfig == null) {
                    logoConfig = new LogoConfig();
                }
                // 添加logo图片, 此处一定需要重新进行读取,而不能直接使用二维码的BufferedImage 对象
                BufferedImage img = ImageIO.read(file);
                overlapImage(img, FORMAT, file.getAbsolutePath(), logoFile, logoConfig);
            }
            return file;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 创建生成二维码图片
     *
     * @param content 二维码内容
     * @param length  二维码的高度和宽度
     * @return 二维码图片的字节数组
     */
    public static File create(String content, int length) {
        return create(content, length, null, null);
    }

    /**
     * 创建生成默认高度(400)的二维码图片
     *
     * @param content 二维码内容
     * @return 二维码图片的字节数组
     */
    public static File create(String content) {
        return create(content, DEFAULT_LENGTH, null, null);
    }

    /**
     * 将logo添加到二维码中间
     *
     * @param image     生成的二维码图片对象
     * @param imagePath 图片保存路径
     * @param logoFile  logo文件对象
     * @param format    图片格式
     */
    private static void overlapImage(BufferedImage image, String format, String imagePath, File logoFile, LogoConfig logoConfig) {
        try {
            BufferedImage logo = ImageIO.read(logoFile);
            Graphics2D g = image.createGraphics();
            // 考虑到logo图片贴到二维码中,建议大小不要超过二维码的1/5;
            int width = image.getWidth() / logoConfig.getLogoPart();
            int height = image.getHeight() / logoConfig.getLogoPart();
            // logo起始位置,此目的是为logo居中显示
            int x = (image.getWidth() - width) / 2;
            int y = (image.getHeight() - height) / 2;
            // 绘制图
            g.drawImage(logo, x, y, width, height, null);
            // 给logo画边框
            // 构造一个具有指定线条宽度以及 cap 和 join 风格的默认值的实心 BasicStroke
            g.setStroke(new BasicStroke(logoConfig.getBorder()));
            g.setColor(logoConfig.getBorderColor());
            g.drawRect(x, y, width, height);
            g.dispose();
            // 写入logo图片到二维码
            ImageIO.write(image, format, new File(imagePath));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 解析二维码
     *
     * @param file 二维码文件内容
     * @return 二维码的内容
     */
    public static String decode(File file) {
        try {
            BufferedImage image = ImageIO.read(file);
            LuminanceSource source = new ImageLuminanceSource(image);
            Binarizer binarizer = new HybridBinarizer(source);
            BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
            Map hints = new EnumMap<>(DecodeHintType.class);
            hints.put(DecodeHintType.CHARACTER_SET, Charsets.UTF_8.name());
            return new MultiFormatReader().decode(binaryBitmap, hints).getText();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy