Fork me on GitHub

Itext5生成高质量、易识别、适合小尺寸标签打印的二维码

高质量、易识别、小尺寸二维码生成

1.增大二维码的原始尺寸(例如 1000 x 1000 或更大),再缩放为 PDF 所需的大小。这样可以保留更多像素细节,提高识别率。
2.降低容错级别到 L 或 M,如果你的内容不是特别长或复杂的话,这样能减少密集度。
3.优化缩放方式:
• 使用 BufferedImage 放大或缩小时,避免图片模糊。
• 尽量在原始生成阶段保持高分辨率。
需要引入zxing

<!--  zxing  -->
<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>core</artifactId>
    <version>3.5.0</version>
</dependency>
<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>javase</artifactId>
    <version>3.5.0</version>
</dependency>
/**
   * 生成二维码
   * @param content 字符串(二维码内容)
   * @param cb PDF模版文件
   * @throws Exception
   */
private void generateQRcode(String content, PdfContentByte cb) throws Exception {
    Map<EncodeHintType, Object> hints = new HashMap<>();
    hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
    hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L); // 容错级别调为 L
    hints.put(EncodeHintType.MARGIN, 0); // 去掉白边,实际没起作用

    int originalSize = 1000; // 生成更大的二维码
    QRCodeWriter qrCodeWriter = new QRCodeWriter();
    BitMatrix bitMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, originalSize, originalSize, hints);

    int width = bitMatrix.getWidth();
    int height = bitMatrix.getHeight();

    // 创建高分辨率的 BufferedImage
    BufferedImage qrImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    Graphics2D graphics = qrImage.createGraphics();

    // 设置背景为白色
    graphics.setColor(Color.WHITE);
    graphics.fillRect(0, 0, width, height);

    // 绘制二维码
    graphics.setColor(Color.BLACK);
    for (int x = 0; x < width; x++) {
        for (int y = 0; y < height; y++) {
            if (bitMatrix.get(x, y)) {
                qrImage.setRGB(x, y, 0xFF000000);
            }
        }
    }
    graphics.dispose(); // 释放图形资源

    // 将高质量二维码写入字节流
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    ImageIO.write(qrImage, "png", byteArrayOutputStream);

    // 从字节流中读取为 iText Image 对象
    Image qrcodeImage = PngImage.getImage(byteArrayOutputStream.toByteArray());

    // 缩放图片到适合 PDF 的大小
    qrcodeImage.scaleAbsolute(274, 271);

    // 设置位置
    qrcodeImage.setAbsolutePosition(417, 13);
    cb.addImage(qrcodeImage);
}

二维码裁剪白色边框

hints.put(EncodeHintType.MARGIN, 0)去掉白边代码,实际没起作用

            InputStream templateStream = getClass().getResourceAsStream("/template/Autumntemplate.pdf");
            PdfReader reader = new PdfReader(templateStream);
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            PdfStamper stamper = new PdfStamper(reader, outputStream);

            // 获取第1页的 PdfContentByte
            PdfContentByte cb = stamper.getOverContent(1);
            // 传入 PdfContentByte 对象,附加二维码
            generateQRcode(qrContent, cb);
	/**
     * 生成二维码并附加到PDF上
     * @param content
     * @param cb
     * @throws Exception
     */
    private void generateQRcode(String content, PdfContentByte cb) throws Exception {
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        // 容错级别调为 L
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
        // 去掉白边,实际没有去掉
        hints.put(EncodeHintType.MARGIN, 0);
        // 生成更大的二维码
        int originalSize = 1000;
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        BitMatrix bitMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, originalSize, originalSize, hints);


        // 创建一个与二维码大小相同的 BufferedImage
        int width = bitMatrix.getWidth();
        int height = bitMatrix.getHeight();
        BufferedImage qrImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        // 填充二维码图像
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                qrImage.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
            }
        }

        // 裁剪掉白色边距
        BufferedImage croppedImage = cropWhiteBorder(qrImage);

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ImageIO.write(croppedImage, "png", byteArrayOutputStream);

        Image qrcodeImage = PngImage.getImage(byteArrayOutputStream.toByteArray());
        // 设置图片大小,最终二维码大小和位置在这里设置
        qrcodeImage.scaleAbsolute(274, 271);
        // 设置位置
        qrcodeImage.setAbsolutePosition(417, 13);
        cb.addImage(qrcodeImage);
    }

    /**
     * 去二维码白边
     * @param image
     * @return
     */
    private BufferedImage cropWhiteBorder(BufferedImage image) {
        int width = image.getWidth();
        int height = image.getHeight();

        int left = width, right = 0, top = height, bottom = 0;

        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                // 如果是黑色像素
                if (image.getRGB(x, y) == 0xFF000000) {
                    if (x < left) left = x;
                    if (x > right) right = x;
                    if (y < top) top = y;
                    if (y > bottom) bottom = y;
                }
            }
        }

        // 根据检测到的边界裁剪
        return image.getSubimage(left, top, right - left + 1, bottom - top + 1);
    }
posted @ 2025-03-24 16:36  秋夜雨巷  阅读(62)  评论(0)    收藏  举报