<dependency>
<groupId>com.google.zxinggroupId>
<artifactId>coreartifactId>
<version>3.4.1version>
dependency>
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.apache.commons.lang3.StringUtils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class QRCodeGenerator {
// 二维码尺寸
private static final int QRCODE_SIZE = 512;
// logo尺寸
private static final int LOGO_SIZE = 200;
// logo圆角
private static final int LOGO_BORDER_RADIUS = 25;
// 背景色
private static final Color BACKGROUND_COLOR = new Color(230, 132, 72);
// 字体颜色
private static final Color TEXT_COLOR = Color.BLACK;
// 图片padding
private static final int PADDING = 20;
// 底部文字大小
private static int FONT_SIZE = 22;
/**
* 生成带底部文字的二维码
*
* @param content 二维码内容
* @param text 底部文字
* @param outputFile 输出文件
*/
public static void generateQRCodeWithText(String content, String text, String logo, File outputFile) throws WriterException, IOException {
// 创建二维码
BufferedImage qrImage = createQRCode(content);
// 计算最终图片高度(二维码高度 + 文字区域高度)
int height = PADDING + qrImage.getHeight() + FONT_SIZE + PADDING;
int width = PADDING + qrImage.getWidth() + PADDING;
// 创建新的BufferedImage,包含二维码和文字区域
BufferedImage combinedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = combinedImage.createGraphics();
// 设置背景为白色
g.setColor(BACKGROUND_COLOR);
// 填充整个图片区域
g.fillRect(0, 0, width, height);
// 绘制二维码到新图片的上部
g.drawImage(qrImage, PADDING, PADDING, null);
// 绘制logo
if (StringUtils.isNotBlank(logo)) {
BufferedImage logoImg = ImageIO.read(new File(logo));
// 设置logo宽高
logoImg = resizeImageHighQuality(logoImg, LOGO_SIZE, LOGO_SIZE);
// 设置logo圆角
logoImg = createRoundedCornerImage(logoImg, LOGO_BORDER_RADIUS);
g.drawImage(logoImg, PADDING + qrImage.getWidth() / 2 - LOGO_SIZE / 2, PADDING + qrImage.getHeight() / 2 - LOGO_SIZE / 2, null);
}
// 设置文字样式
String fontName = "Microsoft YaHei";
// 尝试加载字体,如果找不到则使用默认字体
Font font;
try {
font = new Font(fontName, Font.PLAIN, FONT_SIZE);
} catch (Exception e) {
font = new Font("Arial", Font.PLAIN, FONT_SIZE);
System.err.println("警告: 无法加载中文字体 " + fontName + ", 使用默认字体");
}
g.setColor(TEXT_COLOR);
g.setFont(new Font(fontName, Font.BOLD, FONT_SIZE));
// 计算文字位置(居中)
FontMetrics fontMetrics = g.getFontMetrics();
int textWidth = fontMetrics.stringWidth(text);
// 如果文字太长,自动缩小字体,左右各留10像素边距
int maxTextWidth = width - PADDING * 2;
while (textWidth > maxTextWidth && FONT_SIZE > 8) {
FONT_SIZE--;
font = new Font(fontName, Font.PLAIN, FONT_SIZE);
g.setFont(font);
fontMetrics = g.getFontMetrics();
textWidth = fontMetrics.stringWidth(text);
}
int x = (width - textWidth) / 2;
int y = PADDING + qrImage.getHeight() + (height - PADDING - qrImage.getHeight()) / 2 + fontMetrics.getAscent() / 4;
// 绘制文字
g.drawString(text, x, y);
g.dispose();
// 保存图片
ImageIO.write(combinedImage, "png", outputFile);
}
/**
* 创建基本二维码图片
*
* @param content 二维码内容
* @return BufferedImage
* @throws WriterException
*/
private static BufferedImage createQRCode(String content) throws WriterException {
Map<EncodeHintType, Object> hints = new HashMap<>();
// 高容错率
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
// 二维码边距
hints.put(EncodeHintType.MARGIN, 0);
QRCodeWriter qrCodeWriter = new QRCodeWriter();
BitMatrix bitMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);
BufferedImage image = new BufferedImage(QRCODE_SIZE, QRCODE_SIZE, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < QRCODE_SIZE; x++) {
for (int y = 0; y < QRCODE_SIZE; y++) {
image.setRGB(x, y, bitMatrix.get(x, y) ? TEXT_COLOR.getRGB() : BACKGROUND_COLOR.getRGB());
}
}
return image;
}
/**
* 设置图像宽高
*/
private static BufferedImage resizeImageHighQuality(BufferedImage original, int targetWidth, int targetHeight) {
BufferedImage resized = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D g = resized.createGraphics();
// 设置抗锯齿和高质量渲染
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.drawImage(original, 0, 0, targetWidth, targetHeight, null);
g.dispose();
return resized;
}
/**
* 创建圆角图像
*/
private static BufferedImage createRoundedCornerImage(BufferedImage original, int arcSize) {
int width = original.getWidth();
int height = original.getHeight();
// 创建新的空白图像,支持透明度
BufferedImage rounded = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
// 启用抗锯齿
Graphics2D g2d = rounded.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// 绘制圆角矩形路径并裁剪
RoundRectangle2D roundRect = new RoundRectangle2D.Float(0, 0, width, height, arcSize, arcSize);
g2d.setClip(roundRect);
// 绘制原始图像
g2d.drawImage(original, 0, 0, null);
g2d.dispose();
return rounded;
}
public static void main(String[] args) throws IOException, WriterException {
String content = "https://www.baidu.com";
String text = "百度一下,你就知道";
File outputFile = new File("E:\\DeskTop\\baidu.png");
generateQRCodeWithText(content, text, "E:\\DeskTop\\logo.png", outputFile);
System.out.println("二维码已生成到: " + outputFile.getAbsolutePath());
}
}
如您在阅读中发现不足,欢迎留言!!!