From 15ddcaa9986423f3a4ee3119df5320c4e16a8769 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9B=B9=E7=A3=8A?= <45566618@qq.com> Date: Wed, 9 Jul 2025 14:18:14 +0800 Subject: [PATCH] =?UTF-8?q?=E7=94=9F=E6=88=90=E4=BA=8C=E7=BB=B4=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/nuBaseInfo/utils/QRCodeUtil.java | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 nursing-unit-admin/nu-admin-biz/src/main/java/com/nu/modules/nuBaseInfo/utils/QRCodeUtil.java diff --git a/nursing-unit-admin/nu-admin-biz/src/main/java/com/nu/modules/nuBaseInfo/utils/QRCodeUtil.java b/nursing-unit-admin/nu-admin-biz/src/main/java/com/nu/modules/nuBaseInfo/utils/QRCodeUtil.java new file mode 100644 index 0000000..9aadc54 --- /dev/null +++ b/nursing-unit-admin/nu-admin-biz/src/main/java/com/nu/modules/nuBaseInfo/utils/QRCodeUtil.java @@ -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 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(); + } + } +}