You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用PDFBox在已添加图片上方居中添加文本?

问题:PDF图片上方文本无法居中

我需要向PDF中添加图片,并在图片上方添加文本。图片已设置为居中显示,文本需在图片上方居中且与图片保留少量边距。目前图片可正常添加并居中,但文本未实现居中效果。

效果截图

以下是我的代码,重点关注drawTitleAtTop方法的调用部分:我将新添加图片的高度加上3的边距赋值给y坐标,x坐标根据传入文本计算,但存在计算错误,恳请提供修正建议?

private static void addScaledImage(ImageData imgData, PDDocument pdDocument, Dimension thePdfDimension) {
    ImageHelper helper = Scalr::resize;
    byte[] scaledImage = ImageUtils.resizeImageKeepAspectRatio(helper, imgData.getImageBinary(), thePdfDimension.width);

    PDRectangle rectangle = pdDocument.getPage(0).getMediaBox();
    PDPage page = new PDPage(rectangle);
    pdDocument.addPage(page);
    PDImageXObject pdImage = null;
    try {
        pdImage = PDImageXObject.createFromByteArray(pdDocument, scaledImage, null);
        LOG.debug("size of scaled image is x: {0} y {1}", pdImage.getWidth(), pdImage.getHeight());
        int xForImage = (thePdfDimension.width - pdImage.getWidth()) / 2 ;
        int yForImage = (thePdfDimension.height - pdImage.getHeight()) / 2;
        LOG.debug("new x {0} new y {1}", xForImage, yForImage);
        try (PDPageContentStream contentStream = new PDPageContentStream(pdDocument, page, AppendMode.APPEND, true, true)) {
            if (StringUtils.isNotBlank(imgData.getTitle())) {
                yForImage = xForImage - 20;
                contentStream.drawImage(pdImage, xForImage, yForImage, pdImage.getWidth(), pdImage.getHeight());
                drawTitelAtTop(imgData, page, xForImage , yForImage + pdImage.getHeight() + 3, contentStream);
            } else {
                contentStream.drawImage(pdImage, xForImage, yForImage, pdImage.getWidth(), pdImage.getHeight());
            }
        }

    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

private static void drawTitelAtTop(ImageData imgData, PDPage page, int x, int y,  PDPageContentStream contentStream) throws IOException {
    PDFont font = PDType1Font.COURIER;
    int fontSize = FONT_SIZE_FOR_TITLE;

    float titleWidth = font.getStringWidth(imgData.getTitle()) / 1000 * fontSize;
    LOG.debug("title width is " + titleWidth);
    contentStream.setFont(font, fontSize);
    contentStream.beginText();
    float tx = ((x - titleWidth) / 2) + x;
    //float tx = x;
    //float ty = page.getMediaBox().getHeight() - marginTop + (marginTop / 4);
    float ty = y;
    LOG.debug("title offset x {0} y {1}", tx, ty);
    contentStream.newLineAtOffset(tx,
        ty);

    contentStream.showText(imgData.getTitle());
    contentStream.endText();

}

修正方案

1. 修复图片位置的逻辑错误

原代码中yForImage = xForImage - 20;属于低级错误——将水平坐标xForImage赋值给垂直坐标yForImage,导致图片位置完全偏离预期。正确逻辑是向下移动图片(PDF y轴从底部向上递增),为标题留出空间:

if (StringUtils.isNotBlank(imgData.getTitle())) {
    // 预留标题高度(字体大小+额外边距)
    int titleSpace = FONT_SIZE_FOR_TITLE + 5;
    // 图片向下移动,给标题腾位置
    yForImage -= titleSpace;
    contentStream.drawImage(pdImage, xForImage, yForImage, pdImage.getWidth(), pdImage.getHeight());
    // 标题y坐标:图片顶部 + 3像素边距
    float titleY = yForImage + pdImage.getHeight() + 3;
    // 传递图片的x坐标和宽度,用于计算文本居中位置
    drawTitelAtTop(imgData, page, xForImage, pdImage.getWidth(), titleY, contentStream);
}

2. 修正文本居中的坐标计算

原drawTitelAtTop方法中float tx = ((x - titleWidth) / 2) + x;的计算公式完全错误。要实现文本与图片居中对齐,需让文本的水平中心与图片的水平中心重合,正确的x坐标计算方式为:

private static void drawTitelAtTop(ImageData imgData, PDPage page, float imageX, float imageWidth, float y, PDPageContentStream contentStream) throws IOException {
    PDFont font = PDType1Font.COURIER;
    int fontSize = FONT_SIZE_FOR_TITLE;

    float titleWidth = font.getStringWidth(imgData.getTitle()) / 1000 * fontSize;
    LOG.debug("title width is " + titleWidth);
    contentStream.setFont(font, fontSize);
    contentStream.beginText();
    // 文本起始x坐标 = 图片左边界 + (图片宽度 - 文本宽度)/2
    float tx = imageX + (imageWidth - titleWidth) / 2;
    float ty = y;
    LOG.debug("title offset x {0} y {1}", tx, ty);
    contentStream.newLineAtOffset(tx, ty);
    contentStream.showText(imgData.getTitle());
    contentStream.endText();
}

关键说明

  • PDF的坐标系统:y轴从页面底部开始向上递增,因此调整图片位置时,yForImage -= titleSpace是将图片向下移动(远离页面顶部),为标题留出空间。
  • 文本居中逻辑:通过计算图片的水平中心,再让文本的水平中心与之对齐,确保文本在图片上方居中显示。

内容的提问来源于stack exchange,提问作者Al Phaba

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 11:46:07