最新版本更新
https://code.jiangjiesheng.cn/article/352
1. 样式1 :
2.1 效果图 :
忽略红色,最外层的红色只是方便展示当前图片的宽高
2.2 代码
package cn.jiangjiesheng.utils;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.PostConstruct;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 或者换个思路,写html导出pdf 或者导出png ,不知道能否行得通?参考 eduinp 生产pdf和zip打包的逻辑的逻辑。
* <dependency>
* <groupId>com.google.zxing</groupId>
* <artifactId>core</artifactId>
* <version>3.4.1</version>
* </dependency>
* <dependency>
* <groupId>com.google.zxing</groupId>
* <artifactId>javase</artifactId>
* <version>3.4.1</version>
* </dependency>
*/
public class QRCodeWithTextGenerator {
private final static Logger log = LoggerFactory.getLogger(QRCodeWithTextGenerator.class);
private static boolean IS_DEBUG = true;
private static final String OUTPUT_FILE = "qrcode.png"; // 输出文件名
private static final String SPACE = " "; // 输出文件名
private static int QRCODE_WIDTH = 200;
private static final int FONT_SIZE = 12;
private static final int EXPANSION_FACTOR = 5; // textInfo 扩大倍数 ,按 \\n 换行(一条属性信息),一条属性信息可能比较长,还会继续换行,最终来裁切图片,此值大致表示每条属性信息最多可能的换行条数
private static final int SPACE_COUNT = 14; // 换行时左侧的空格占位
private static Font FONT = new Font("Microsoft YaHei", Font.PLAIN, FONT_SIZE);
public static void main(String[] args) {
try {
//main 方法测试使用 直接使用 static 默认值就行
//init();
String QR_CODE_TEXT = "http://code.jiangjiesheng.cn";
String textInfo = "设备名称: xxxx\n所属机构: 123456789123456789123456789\n所属测点: xxxx\n所属区域: 江苏省南京市江北新区安徽省安庆市\n其他信息: 联系人 xxx \n";
BufferedImage image = generateQRCodeWithText(QR_CODE_TEXT, QRCODE_WIDTH, textInfo);
saveImageToFile(image, OUTPUT_FILE);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
@PostConstruct
public void init() throws IOException, FontFormatException {
// 加载系统字体
// FONT = new Font("Microsoft YaHei", Font.PLAIN, FONT_SIZE);
// 加载自定义字体
try {
writeFontFile(this.getClass(), "Microsoft YaHei-normal.ttc", false);
String fontPath = getFontFilePath4Read("Microsoft YaHei-normal.ttc");
FONT = Font.createFont(Font.TRUETYPE_FONT, new File(fontPath)).deriveFont(Font.PLAIN, FONT_SIZE);
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
ge.registerFont(FONT);
} catch (IOException | FontFormatException e) {
log.error("加载自定义字体出错", e);
}
}
private static BufferedImage generateQRCodeWithText(String codeContent, int qrcodeWidthHeight, String textInfo) throws WriterException {
// 设置二维码参数
Map<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
hints.put(EncodeHintType.MARGIN, 1); // 边距
QRCodeWriter qrCodeWriter = new QRCodeWriter();
BitMatrix bitMatrix = qrCodeWriter.encode(codeContent, BarcodeFormat.QR_CODE, qrcodeWidthHeight, qrcodeWidthHeight, hints);
int qrWidth = bitMatrix.getWidth();
int qrHeight = bitMatrix.getHeight();
// 创建二维码图像
BufferedImage qrImage = new BufferedImage(qrWidth, qrHeight, BufferedImage.TYPE_INT_ARGB);
for (int x = 0; x < qrWidth; x++) {
for (int y = 0; y < qrHeight; y++) {
qrImage.setRGB(x, y, bitMatrix.get(x, y) ? Color.BLACK.getRGB() : Color.WHITE.getRGB());
}
}
// 创建一个新的图像,包含二维码和文本
int textPadding = 10; // 文本区域的内边距
int imageWidth = qrcodeWidthHeight + textPadding; // 文本区域的内边距
int lineHeight = FONT_SIZE + 10; // 行高
//默认每一行不需要换行的高度
int textHeightNoWrap = (int) (lineHeight * (countLines(textInfo))); // +1 最后一行后也保留个空行,模拟padding
int textMaxHeightWrapped = textHeightNoWrap * EXPANSION_FACTOR;
// 计算总的宽度和高度
int totalWidth = qrWidth;
// int totalHeightNoWrap = qrHeight + textHeightNoWrap &