【问题标题】:How to identify and correct Bounding Box issues?如何识别和纠正边界框问题?
【发布时间】:2017-10-24 03:17:52
【问题描述】:

这是一个简单的冒犯pdf

当我运行DrawPrintTextLocations 时,我看到了下面的内容..

但据我了解,边界框(上方蓝色)应代表您选择文本时在任何 pdf 阅读器中显示的灰色区域,如下所示。

如果 pdf 阅读器能够找出要突出显示的灰色区域,则应该能够找出相同的内容,从而获得字体大小(?)。这个问题是任何人都可以指出我正确的方向。

以下是“测试线”文本中“T”的详细信息。来自其TextPosition 对象变量text

72.4801          //text.getXDirAdj()
83.7600          //text.getYDirAdj()
1.0              //text.getFontSize()
50.0             //text.getFontSizeInPt()   ::I'm unable to decipher the 50.0
12.0             //text.getXScale()         ::Can I assume this to be the font size 
8.004            //text.getHeightDir()
7.8984           //text.getWidthOfSpace()
7.1160           //text.getWidthDirAdj()
950.0            //fontDesc.getAscent()
-222.0           //fontDesc.getDescent()
[x=72.4801,y=75.7560,w=7.1160,h=8.0040]
                 //Red Box boundaries
[x=72.4801,y=46.3560,w=7.1160,h=66.9600]    //The height of 66.96 relates to 50 but not sure how?
                 //Blue Bounding Box boundaries

问题:
1. 边界框问题:当我调用font.getBoundingBox()时,这似乎不一致。有解决办法吗?
2. getFontSizeInPts(): 这个方法好像是受边界框影响。我这样想对吗?(因为 Pt 中的字体大小显示为 50)
3. FontSize 的获取方式是什么?

我需要字体大小,因为我的任务是使用不同的字体重新创建 pdf。

这也是一个正确 pdf 的例子,但字体大小显示为 16 而不是最初使用的 12。

对于类似的pdf 有适当的边界框,下面是详细信息:-

DrawPrintTextLocations 的输出是

以下是“测试线”文本中“T”的详细信息。来自其TextPosition 对象变量text

72.0605           //text.getXDirAdj()
83.3199           //text.getYDirAdj()
16.0              //text.getFontSize()      :: Why is this showing 16 while my font is 12 in size
16.0              //text.getFontSizeInPt()
12.0101           //text.getXScale()        ::Can I assume this to be the font size 
6.6618            //text.getHeightDir()
2.6447            //text.getWidthOfSpace()
7.1193            //text.getWidthDirAdj()
778.808           //fontDesc.getAscent()    :: There seems to be an issue with the ascent
-222.1680         //fontDesc.getDescent()
[x=72.0605,y=76.6581,w=7.1193,h=6.6618]
                  //Red Box boundaries
[x=72.0605,y=72.6176,w=7.1193,h=13.3237]    //The height of 13.3237 relates to 12 the font size but not sure how?
                  //Blue Bounding Box boundaries

使用 MKL 的答案后更新
以下是对我有用的...

//Make Line
Line2D.Float line = new Line2D.Float(0,0,0,1f);
LOG.debug("Line<Before Transform>:" + line.getBounds2D());
s=myTextMatrix.createAffineTransform().createTransformedShape(line);
LOG.debug("Line after AT:"+s.getBounds2D());
s=pageFlipAffineTransform.createTransformedShape(s);
s=pageRotateAffineTransform.createTransformedShape(s);
rect2 = s.getBounds2D();
LOG.debug("Line<After Transform>:" + rect2);
//Font Size
double wi=rect2.getWidth();
double he=rect2.getHeight();
double total=Math.sqrt(wi*wi+he*he);//This is done in case of rotation
long fntSizeinPt = Math.round(total);
LOG.debug("deciphered Font Size is:" + fntSizeinPt);            

【问题讨论】:

  • 与您不同,我的两个示例文件都得到了过度扩展的边界框。难怪在这两个文件中,PDF 字体信息都声称有一个巨大的边界框......
  • @mkl 在这里有同样的行为。两种字体都有相同的巨大边界框。例如边缘也使用此信息进行文本选择。在我们的解决方案中,我们尝试通过分析所有字形边界框来重新创建边界框来解决这种情况。无论如何,例如Foxit 的 Adob​​e Reader 似乎以另一种方式做到这一点,如bulbus 的第二张截图所示。
  • @JanSlabon OP 声称两个屏幕截图都是使用 PDFBox DrawPrintTextLocations 工具创建的。我使用了那个工具,但两个 PDF 都有巨大的边界框。
  • @mkl 道歉,我已经用正确的 pdf 更新了第二个链接。
  • @bulbus 我检查了你的第三个文件,确实,其中的主要字体有一个合理的 FontBBox 值;因此,您得到的大多是合理的蓝框。其中用于零宽度空间的第二种字体不太合理,并导致DrawPrintTextLocations 输出中出现蓝色尖峰。我已经相应地扩展了我的答案。

标签: java pdf fonts pdfbox


【解决方案1】:
  1. 边界框问题:当我调用font.getBoundingBox() 时,这似乎不一致。有解决办法吗?

正如评论中已经提到的,我无法完全重现您所描述的观察结果:我也得到了第二个 PDF 的过度扩展边界框!并且在这两种情况下,这与 PDF 中的字体信息是一致的,字体描述符 FontBBox 的值分别为 [-1475 -2463 2867 3117] 和 [-1474.60938 -2463.3789 2867.6758 3116.6992] 两者都是非常大,前者似乎是后者的圆形版本。

您提供的第三个 PDF(并将第二个替换为)使用两种字体。用于实际“测试线”的那个。 characters 的字体描述符 FontBBox 值为 [-19 -218 956 891],其值更正常。因此,DrawPrintTextLocations 在这些字符周围绘制的蓝框更有意义。第二种字体的 FontBBox 值有点大,[-1462 -813 1723 1134],结果是两条蓝线超出了蓝框:使用的其他字体的唯一字符是零宽度空格,所以它们周围的框也有零宽度...

因此,一切仍然是一致的。

一种可能的解决方法是不信任字体 PDF 表示中的信息,而是检查嵌入的字体程序

  1. getFontSizeInPts():这个方法好像受边界框影响。我这样想对吗?(因为 Pt 中的字体大小显示为 50)

没有。您必须知道,在 PDF 中,绘制文本的比例取决于许多项目:

  • 首先是您使用 Tf 指令设置的“字体大小”和字体;
  • 然后是可以放大或缩小此大小的文本矩阵;
  • 然后是当前的变换矩阵,它可以再次放大或缩小这个大小;
  • 最后是页面 UserUnit 值,它可以再次放大这个大小。

在您的第一个文档中,您的字体大小为 1,文本矩阵放大​​到 50,然后当前的转换矩阵再次缩小到 12 UserUnit 默认值保持不变的

在您的第二个和第三个文档中,您的字体大小为 16,文本矩阵保持原样,当前的转换矩阵缩小到 12,再次离开与 UserUnit 默认值一样。

FontSizeInPts 是您在第二步之后得到的值(嗯,有点,只考虑了文本矩阵的左上角条目)。正如您文件中的情况所示,它本质上只是一个没有进一步兴趣的中间结果。此外,边界框不参与其计算。

  1. 以点为单位获取 FontSize 的方法是什么?

IMO 你应该采用与字体大小值一样长的垂直线,应用文本矩阵和当前转换矩阵,获取结果行的长度并将其乘以页面 UserUnit 值.

TextPositionTextMatrix 值已经结合了许多这些步骤;尽管它的名字是 not PDF 规范中指定的文本矩阵,但更多,参见。它的文档:

/**
 * The matrix containing the starting text position and scaling. Despite the name, it is not the
 * text matrix set by the "Tm" operator, it is really the effective text rendering matrix (which
 * is dependent on the current transformation matrix (set by the "cm" operator), the text matrix
 * (set by the "Tm" operator), the font size (set by the "Tf" operator) and the page cropbox).
 *
 * @return The Matrix containing the starting text position
 */
public Matrix getTextMatrix()

因此,如果mMatrix,您只需将其应用于点 (0, 0) 和 (0, 1),将矩阵应用于它们,测量结果点的距离,并将该距离乘以页面 UserUnit 值(通常是 1)。

【讨论】:

  • 我已经设法实现了您推荐的内容,但我得到了像 9.75 for 10 这样的小数字体大小; 28 为 27.84;8 为 7.92 等。虽然圆形字体没问题。我的假设是 pdf 创建者出于某种原因如何收缩字体吗?
  • “我已经设法实现了你推荐的,但我得到了小数字体大小” - 我既没有你的 PDF,也没有你的实际实现,所以我无法检查是否有PDFBox 中的一些问题,在您的实现中,或者 PDF 中的字体大小实际上是否是分数,无论某些 PDF 创建者说什么。我认为这是最后的选择。
  • @bulbus "你能给我指出 UserUnit" 的正确方向吗 - 不幸的是,PDPage 没有该页面的明确 getter字典条目。但是对于PDPage page 检索page.getCOSObject().getFloat("UserUnit", 1f) 应该这样做。 (大多数文档不使用选择默认用户单位的选项,因此您可能很难找到不返回 1 的 PDF...)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-26
  • 1970-01-01
  • 1970-01-01
  • 2020-12-27
相关资源
最近更新 更多