如何使用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
相关产品推荐
相关产品推荐

