【问题标题】:How to draw a string at a specific position on a pdf page in java using pdfbox?java - 如何使用pdfbox在java中pdf页面的特定位置绘制字符串?
【发布时间】:2014-07-28 08:47:09
【问题描述】:

我有一个 pdf 坐标 (x, y) 作为输入。我需要在给定的输入坐标处绘制一个字符串[例如:- (x,y)=(200,250)]。我正在使用 pdfbox ,当我使用以下方法 moveTextPositionByAmount 时,我没有得到确切的位置。即使我尝试过 moveTo()。请帮助我如何在确切位置绘制字符串?

PDPageContentStream contentStream = new PDPageContentStream(document, page,true,true);
contentStream.beginText();
contentStream.setFont(PDType1Font.HELVETICA_BOLD, 12);
contentStream.moveTextPositionByAmount(xindex, yindex);
contentStream.setNonStrokingColor(color);
contentStream.drawString(comment);                      
contentStream.stroke();
contentStream.endText();

谢谢。

【问题讨论】:

  • 你期望在给定的位置是什么? PDF 将该位置解释为文本的基线
  • 我想在那个位置画一个字符串,当我尝试执行上面的代码时,它绘制的文本与原始文本相比变化很大。
  • 我发现了一个可能的问题,参见。我的回答如下。如果使用建议的修复程序仍然有问题,请提供由您的代码更改的示例文档来说明问题,并说明您从何处获得这些目标坐标,因为 PDF 中有多个坐标系统在工作,并且一些 PDF 处理器带来了他们的拥有。
  • 样本数据 X:-121,Y:-305,W:-262,h:-104。请检查以下链接以获取屏幕截图。 [链接]tinypic.com/r/11b6lap/8.我也在画矩形。当使用相同的坐标时,我成功地获得了准确的输出。我已经使用 contentStream.fillRect(xValue,yValue,wValue,hValue) 来绘制矩形,但是使用 drawstring 时会出现问题。
  • 屏幕截图仅在提供 PDF 时才有帮助。此外,您还没有解释从哪里获得这些坐标。它们可能必须进行转换,因为这里可能涉及多个坐标系。

标签: java pdf pdfbox


【解决方案1】:

摆脱现有页面内容的图形状态变化

您使用带有两个 boolean 参数的 PDPageContentStream 构造函数:

new PDPageContentStream(document, page,true,true);

这个构造函数实现为:

this(document, sourcePage, appendContent, compress, false);

即它使用三个boolean 参数调用构造函数,最后一个参数使用false。最后的boolean 参数记录为:

* @param resetContext Tell if the graphic context should be reseted.

因此,您可以在不重置图形上下文的情况下附加到页面内容。这意味着在现有页面内容中对当前转换矩阵所做的任何更改仍会转换您的坐标。为防止这种情况发生,您应该使用带有三个 boolean 参数的 PDPageContentStream 构造函数:

new PDPageContentStream(document, page, true, true, true);

使用这个可以轻松定位文字。

绘制矩形和测试

OP提到他成功绘制了矩形但没有绘制文本。

以下代码

PDPage firstPage = allPages.get(0);
PDRectangle pageSize = firstPage.findMediaBox();

float x = 121;
float y = 305;
float w = 262;
float h = 104;

PDPageContentStream contentStream = new PDPageContentStream(document, firstPage, true, true, true);

contentStream.setNonStrokingColor(Color.yellow);
contentStream.fillRect(pageSize.getLowerLeftX() + x, pageSize.getLowerLeftY() + y, w, h);

contentStream.beginText();
contentStream.moveTextPositionByAmount(pageSize.getLowerLeftX() + x, pageSize.getLowerLeftY() + y);
contentStream.setFont(PDType1Font.HELVETICA_BOLD, 12);
contentStream.setNonStrokingColor(Color.red);
contentStream.drawString("My Text Here");
contentStream.endText();
contentStream.close();

结果

正如预期的那样。

必须说明输入坐标的含义

OP 还在他的 cmets 中提到 X:-121,Y:-305,W:-262,h:-104 作为 来自外部应用程序的坐标

由于 PDF 通常在媒体框内具有正坐标,因此这些 X 和 Y 坐标通常对 PDF 没有意义。

此外,OP 无法共享文档

因此,无法确定这些负坐标是否对他的特殊 PDF 有意义。

矩形绘制操作接受宽度和高度的负值,但如果用于文本,它们可能意味着 Y 坐标不表示基线,或者文本不应从 X 开始,而是从到此为止,或者文本应该被镜像,或者,或者,或者......

因此,必须首先解释那些负坐标和维度的含义。 那些坐标的原点,是正的y坐标的上方还是下方,是矩形的左下角的X,Y,负的宽度或高度是什么意思,这里相对于X,Y应字符串被绘制?

【讨论】:

  • 我在api中找不到上面的构造函数。[link]pdfbox.apache.org/apidocs/org/apache/pdfbox/pdmodel/edit/…
  • 我的意思是坐标是 X=121,Y=305,W=262,h=104 。这个对我有用。谢谢。但我得到了另一种解决方案的输出。
  • x、y、宽、高的单位是什么?当我尝试您给出的绘制黄色矩形的示例时,我以 100% 的缩放级别打开我的 PDF 查看器,并测量矩形的宽度(以像素为单位)。它是 350 像素宽,而不是代码中的 262 像素。
  • PDF 中默认的用户空间单位是DTP point,1/72 英寸。
【解决方案2】:

我发现这个对我有用。

PDPageContentStream contentStream = new PDPageContentStream(document, page,true,true);
contentStream.beginText();
contentStream.setFont(PDType1Font.HELVETICA_BOLD, 12);
contentStream.moveTextPositionByAmount(xindex, yindex);
contentStream.setNonStrokingColor(color);
contentStream.drawString(comment);                      
contentStream.endText();

【讨论】:

  • 您似乎使用的是旧的 PDFBox 版本;在 2013 年初添加了检查,这将使您的 contentStream.moveTo(0,0) 抛出异常。原因:moveTostroke添加路径创建或路径绘制操作。在文本对象 (beginText ... endText) 内禁止此类操作,因此会创建损坏的 PDF。不过,大多数 PDF 查看器都会忽略此错误。
  • 是的。我正在使用旧版本的 PDFBox,因为我正在工作的项目已经开发得较早,我只能使用那些 jar 文件。抱歉,我的代码中没有使用 stroke()。
  • stroke() 未在我的代码中使用 - 严格来说,moveTo 也不允许在文本对象中...
  • 不知道确切但它有效。 contentStream.moveTo(0,0); contentStream.beginText(); contentStream.setFont(PDType1Font.HELVETICA_BOLD, 12); contentStream.moveTextPositionByAmount(xValue,yValue); contentStream.setNonStrokingColor(颜色); contentStream.drawString(comment); contentStream.endText(); contentStream.close();
  • 您的contentStream.moveTo(0,0) 开始创建路径。路径创建必须以路径绘制操作结束。您开始一个文本对象,而不是这样的操作。因此,严格来说,您的解决方案会创建无效的 PDF。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-20
  • 1970-01-01
  • 1970-01-01
  • 2023-03-26
  • 2014-07-25
  • 1970-01-01
  • 2012-01-21
相关资源
最近更新 更多