生成二维码

This commit is contained in:
曹磊 2025-07-09 14:18:14 +08:00
parent c4b6f6a0ba
commit 15ddcaa998
1 changed files with 136 additions and 0 deletions

View File

@ -0,0 +1,136 @@
package com.nu.modules.nuBaseInfo.utils;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.EnumMap;
import java.util.Map;
/**
* 生成带logo的二维码工具类
*/
public class QRCodeUtil {
/**
* 工具类入口
* @param content 二维码内容如带参数的网址
* @param size 二维码图像尺寸数值越大尺寸越大
* @param margin 二维码边距
* @param logoPath Logo文件路径
* @param outputPath 输出文件路径
* @throws Exception
*/
public static void generateQRCodeWithLogo(String content, int size, int margin,
String logoPath, String outputPath) throws Exception {
// 1. 生成基础二维码
Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 高容错
hints.put(EncodeHintType.MARGIN, margin);
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
QRCodeWriter qrCodeWriter = new QRCodeWriter();
BitMatrix bitMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, size, size, hints);
// 创建二维码图像
BufferedImage qrImage = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB);
Graphics2D qrGraphics = qrImage.createGraphics();
// 填充白色背景
qrGraphics.setColor(Color.WHITE);
qrGraphics.fillRect(0, 0, size, size);
// 绘制黑色模块
qrGraphics.setColor(Color.BLACK);
for (int x = 0; x < size; x++) {
for (int y = 0; y < size; y++) {
if (bitMatrix.get(x, y)) {
qrGraphics.fillRect(x, y, 1, 1);
}
}
}
// 2. 添加Logo到中心
BufferedImage logo = null;
try {
logo = ImageIO.read(new File(logoPath));
} catch (Exception e) {
System.err.println("无法加载Logo图片: " + e.getMessage());
// 如果无法加载Logo则直接保存二维码
qrGraphics.dispose();
ImageIO.write(qrImage, "PNG", new File(outputPath));
return;
}
// 计算Logo尺寸(最大不能超过二维码宽度的25%)
int logoSize = Math.min(size / 5, Math.min(logo.getWidth(), logo.getHeight()));
int logoX = (size - logoSize) / 2;
int logoY = (size - logoSize) / 2;
// 处理Logo为圆形(可选)
if (!logoPath.toLowerCase().endsWith(".png")) {
// 对于非透明格式的图片添加白色背景
qrGraphics.setColor(Color.WHITE);
qrGraphics.fillRect(logoX - 3, logoY - 3, logoSize + 6, logoSize + 6);
}
// 创建圆形Logo
BufferedImage circularLogo = createCircularImage(logo, logoSize);
// 添加Logo到二维码
qrGraphics.drawImage(circularLogo, logoX, logoY, null);
qrGraphics.dispose();
// 3. 保存最终图像
ImageIO.write(qrImage, "PNG", new File(outputPath));
}
// 创建圆形Logo图片
private static BufferedImage createCircularImage(BufferedImage source, int diameter) {
BufferedImage output = new BufferedImage(diameter, diameter, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = output.createGraphics();
// 设置圆形剪裁区域
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Ellipse2D.Double circle = new Ellipse2D.Double(0, 0, diameter, diameter);
g2d.setClip(circle);
// 缩放并绘制Logo
Image scaledLogo = source.getScaledInstance(diameter, diameter, Image.SCALE_SMOOTH);
g2d.drawImage(scaledLogo, 0, 0, null);
// 添加白色边框
g2d.setClip(null);
g2d.setColor(Color.WHITE);
g2d.setStroke(new BasicStroke(3));
g2d.drawOval(0, 0, diameter, diameter);
g2d.dispose();
return output;
}
public static void main(String[] args) {
try {
// 生成带Logo的二维码
generateQRCodeWithLogo(
"https://www.focusnu.com/devops", // 二维码内容
400, // 图像尺寸
5, // 二维码边距
"D:\\logo.png", // Logo文件路径
"D:\\qr_with_logo.png" // 输出文件路径
);
System.out.println("带Logo的二维码已生成: qr_with_logo.png");
} catch (Exception e) {
System.err.println("二维码生成失败: " + e.getMessage());
e.printStackTrace();
}
}
}