二维码

This commit is contained in:
zt
2025-09-08 16:38:01 +08:00
parent c90828f98e
commit 8a18223d06

View File

@ -219,16 +219,11 @@ public class PdfBoxQrCodeGenerator {
// 固定的边距(点)
private static final float MARGIN = 10.0f;
// 二维码大小比例页面宽高中较小值的20%
private static final float QR_SIZE_RATIO = 0.2f;
/**
* 在PDF每一页的指定位置添加二维码并返回数据流二维码放大10倍居中放置带边界检查
*/
public static ByteArrayOutputStream addQRCodeToPDFOnAllPages(String srcPdf, byte[] qrCodeBytes, boolean isChangeFile) public static ByteArrayOutputStream addQRCodeToPDFOnAllPages(String srcPdf, byte[] qrCodeBytes, boolean isChangeFile)
throws IOException { throws IOException {
@ -263,50 +258,37 @@ public class PdfBoxQrCodeGenerator {
for (int pageNum = 1; pageNum <= numberOfPages; pageNum++) { for (int pageNum = 1; pageNum <= numberOfPages; pageNum++) {
PdfPage page = pdfDoc.getPage(pageNum); PdfPage page = pdfDoc.getPage(pageNum);
// 获取页面的实际可见区域(裁剪框) // 获取页面的所有边界框信息
Rectangle mediaBox = page.getMediaBox();
Rectangle cropBox = page.getCropBox(); Rectangle cropBox = page.getCropBox();
if (cropBox == null) {
cropBox = page.getPageSize();
}
float pageWidth = cropBox.getWidth(); // 使用CropBox作为主要参考因为它定义了页面的可见区域
float pageHeight = cropBox.getHeight(); Rectangle visibleArea = (cropBox != null) ? cropBox : mediaBox;
// 计算页面宽高中较小的值
float minDimension = Math.min(visibleArea.getWidth(), visibleArea.getHeight());
// 动态计算二维码大小页面宽高中较小值的20%
float qrSize = minDimension * QR_SIZE_RATIO;
// 输出页面尺寸信息 // 输出页面尺寸信息
System.out.println("页面 " + pageNum + " 宽度: " + pageWidth + ", 高度: " + pageHeight); System.out.println("页面 " + pageNum + " 尺寸: " + visibleArea.getWidth() + "x" + visibleArea.getHeight());
System.out.println("页面 " + pageNum + " 二维码大小 (点): " + qrSize);
// 根据页面大小动态计算二维码尺寸页面宽度的15% // 计算左上角的位置PDF坐标系原点在左下角
float qrSize = pageWidth * 0.15f; float qrX = visibleArea.getLeft() + MARGIN;
float qrY = visibleArea.getTop() - qrSize - MARGIN;
// 设置边距页面宽度的2% // 打印二维码位置信息
float margin = pageWidth * 0.02f; System.out.println("页面 " + pageNum + " 左上角二维码位置: x=" + qrX + ", y=" + qrY);
// 计算二维码位置 - 左上角
// 注意PDF坐标系的原点在左下角所以Y坐标需要从页面高度减去二维码高度和边距
float qrX = cropBox.getLeft() + margin;
float qrY = cropBox.getTop() - qrSize - margin;
try { try {
// 使用最简单的方法:直接添加图像 // 使用Canvas API添加左上角二维码
addQRCodeSimple(pdfDoc, page, qrCodeBytes, qrX, qrY, qrSize); addQRCodeWithCanvas(pdfDoc, page, qrCodeBytes, qrX, qrY, qrSize);
} catch (Exception e) { } catch (Exception e) {
System.err.println("在页面 " + pageNum + " 添加二维码时出错: " + e.getMessage()); System.err.println("在页面 " + pageNum + " 添加二维码时出错: " + e.getMessage());
e.printStackTrace(); e.printStackTrace();
// 尝试使用Canvas方法作为备用
try {
addQRCodeWithCanvas(pdfDoc, page, qrCodeBytes, qrX, qrY, qrSize, cropBox);
} catch (Exception ex) {
System.err.println("Canvas备用方法也失败: " + ex.getMessage());
// 最后尝试使用原始大小
try {
addQRCodeSimple(pdfDoc, page, qrCodeBytes, qrX, qrY, 50); // 使用固定大小
} catch (Exception ex2) {
System.err.println("最简单方法也失败: " + ex2.getMessage());
}
}
} }
} }
@ -314,89 +296,44 @@ public class PdfBoxQrCodeGenerator {
return pdfOut; return pdfOut;
} }
// 使用Canvas的备用方法 // 使用Canvas API添加图像
private static void addQRCodeWithCanvas(PdfDocument pdfDoc, PdfPage page, private static void addQRCodeWithCanvas(PdfDocument pdfDoc, PdfPage page,
byte[] qrCodeBytes, float x, float y, float size, Rectangle pageSize) throws IOException {
PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamAfter(), page.getResources(), pdfDoc);
try (Canvas canvas = new Canvas(pdfCanvas, pageSize)) {
ImageData imageData = ImageDataFactory.create(qrCodeBytes);
com.itextpdf.layout.element.Image image = new com.itextpdf.layout.element.Image(imageData);
// 设置二维码尺寸和位置
image.scaleAbsolute(size, size);
image.setFixedPosition(x, y);
// 设置透明度确保不会被背景遮挡
image.setOpacity(0.9f);
canvas.add(image);
}
}
// 最简单的方法:使用原始图像大小
private static void addQRCodeSimple(PdfDocument pdfDoc, PdfPage page,
byte[] qrCodeBytes, float x, float y, float size) throws IOException { byte[] qrCodeBytes, float x, float y, float size) throws IOException {
PdfCanvas canvas = new PdfCanvas(page.newContentStreamAfter(), page.getResources(), pdfDoc); // 创建Canvas对象 - 使用PdfPage和Rectangle构造函数
Canvas canvas = new Canvas(page, page.getPageSize());
// 创建图像对象 // 创建图像数据
ImageData imageData = ImageDataFactory.create(qrCodeBytes); ImageData imageData = ImageDataFactory.create(qrCodeBytes);
com.itextpdf.kernel.pdf.xobject.PdfImageXObject imageXObject =
new com.itextpdf.kernel.pdf.xobject.PdfImageXObject(imageData);
// 添加图像到指定位置(使用原始大小) // 创建Image对象
canvas.addXObjectAt(imageXObject, x, y); Image image = new Image(imageData);
canvas.release(); // 设置图像位置和大小
image.setFixedPosition(x, y);
image.setWidth(size);
image.setHeight(size);
// 添加图像到Canvas
canvas.add(image);
// 关闭Canvas
canvas.close();
System.out.println("Canvas方法设置位置: x=" + x + ", y=" + y);
} }
public static void simpleTest(String pdfPath, String outputPath, byte[] qrCodeBytes) { // main方法示例
try {
PdfDocument pdfDoc = new PdfDocument(new PdfReader(pdfPath), new PdfWriter(outputPath));
for (int i = 1; i <= pdfDoc.getNumberOfPages(); i++) {
PdfPage page = pdfDoc.getPage(i);
Rectangle rect = page.getPageSize();
// 简单地在左上角添加一个固定大小的二维码
PdfCanvas canvas = new PdfCanvas(page.newContentStreamAfter(), page.getResources(), pdfDoc);
ImageData imageData = ImageDataFactory.create(qrCodeBytes);
com.itextpdf.kernel.pdf.xobject.PdfImageXObject imageXObject =
new com.itextpdf.kernel.pdf.xobject.PdfImageXObject(imageData);
// 固定位置和大小
float x = 20; // 固定X位置
float y = rect.getHeight() - 70; // 固定Y位置
canvas.addXObjectAt(imageXObject, x, y);
canvas.release();
}
pdfDoc.close();
System.out.println("简单测试完成");
} catch (Exception e) {
e.printStackTrace();
}
}
// public static void main(String[] args) {
// String path = "C:\\Users\\YuanJie\\Desktop\\test.pdf";
// String outputPath = "C:\\Users\\YuanJie\\Desktop\\test1.pdf";
// String params = "http://192.168.110.151:7788/codeDetail?id=" + "1957649652924448769";
// byte[] bytes = PdfBoxQrCodeGenerator.generateQRCodeBytes(params);
// simpleTest(path, outputPath, bytes);
// }
// 如果使用带放大倍数参数的方法需要修改main方法
public static void main(String[] args) { public static void main(String[] args) {
//合规性手续业务流 test 测试101_101
String path = "C:\\Users\\YuanJie\\Desktop\\合规性手续业务流.pdf"; String path = "C:\\Users\\YuanJie\\Desktop\\test.pdf";
String outputPath = "C:\\Users\\YuanJie\\Desktop\\test1.pdf"; String outputPath = "C:\\Users\\YuanJie\\Desktop\\test1.pdf";
String params = "http://192.168.110.151:7788/codeDetail?id=" + "1957649652924448769"; String params = "http://192.168.110.151:7788/codeDetail?id=" + "1957649652924448769";
byte[] bytes = PdfBoxQrCodeGenerator.generateQRCodeBytes(params); BufferedImage image = QrCodeUtil.generate(params, 200, 200);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ImgUtil.write(image, ImgUtil.IMAGE_TYPE_PNG, out);
byte[] bytes = out.toByteArray();
try { try {
System.out.println("二维码字节大小: " + bytes.length + " 字节"); System.out.println("二维码字节大小: " + bytes.length + " 字节");
@ -407,9 +344,8 @@ public class PdfBoxQrCodeGenerator {
System.out.println("二维码图片已保存到桌面,用于验证二维码是否生成正确"); System.out.println("二维码图片已保存到桌面,用于验证二维码是否生成正确");
} }
// 在每一页添加二维码放大10倍 // 在每一页添加二维码
ByteArrayOutputStream byteArrayOutputStream = ByteArrayOutputStream byteArrayOutputStream = addQRCodeToPDFOnAllPages(path, bytes, false);
PdfBoxQrCodeGenerator.addQRCodeToPDFOnAllPages(path, bytes, false);
try (FileOutputStream fileOut = new FileOutputStream(outputPath)) { try (FileOutputStream fileOut = new FileOutputStream(outputPath)) {
byteArrayOutputStream.writeTo(fileOut); byteArrayOutputStream.writeTo(fileOut);
@ -447,6 +383,12 @@ public class PdfBoxQrCodeGenerator {