2016-02-19 52 views
0

在提取的话,在这个例子中的位置: http://www.dertour.de/static/agb/2015/sommer/DER_Deutschland_So15.pdf 与iTextSharp的5.5.8iTextSharp的 - 不正确的文本位置

我得到“不正确”坐标一些话。例如,在第一段的第17行:'gehen oder im Widerspruch zur Reiseaus-' ,单词的左侧顶部位置的x值是118,217,296,350,524,587。只有第一个值似乎是正确的(118,208,277,320,487,540)。 'gehen'和'oder'之间空格字符右下角的x值是208,这看起来是正确的,而且似乎是“oder”这个单词的正确x-pos。也许它与段落的填充模式有关,但我不确定我应该执行哪些操作来获得正确的坐标。

我正在使用LocationTextExtractionStrategy并将字位置计算为300 dpi坐标系。

 public override void RenderText(TextRenderInfo renderInfo) 
     { 
      // for the provided example 
      // uUnit = 1 
      // originX = 33.862 
      // originY = 33.555 
      // dpi = 300 

      // above values where calculated with code: 
      // PdfNumber userUnit = pageDict.GetAsNumber(PdfName.USERUNIT); 
      // if (userUnit != null) 
      // { 
      // uUnit = userUnit.FloatValue; 
      // } 
      // Rectangle dim = reader.GetPageSize(i); 
      // float originX = dim.Left; 
      // float originY = dim.Bottom; 


      // calculate coordinates: 
      renderInfo.GetText(); 
      LineSegment segment = renderInfo.GetBaseline(); 
      List<TextRenderInfo> charInfo = renderInfo.GetCharacterRenderInfos().ToList(); 

      foreach (TextRenderInfo item in charInfo) 
      { 
       LineSegment char_segment = item.GetBaseline(); 

       int char_left = (int)Math.Round((char_segment.GetStartPoint()[0] - originX) * dpi * uUnit/72.0f); 
       int char_top = (int)Math.Round((item.GetAscentLine().GetEndPoint()[1] - originY) * dpi * uUnit/72.0f); 
       int char_right = (int)Math.Round((char_segment.GetEndPoint()[0] - originX) * dpi * uUnit/72.0f); 
       int char_bottom = (int)Math.Round((item.GetDescentLine().GetStartPoint()[1] - originY) * dpi * uUnit/72.0f); 
      } 
    } 

回答

1

实际上就是在iText的& iTextSharp的一个错误:

与极不准确X坐标系是那些针对其大wordspacing值被设置,例如您行:

0.2861 Tw T* 
[<0047004500480045004E0000>-286<004F0044004500520000>-286<0049004D0000>-231<003700490044004500520053005000520055004300480000>-286<005A005500520000>-286<00320045004900530045004100550053000D>]TJ 

(即0.2861论据Tw大)

根据每个单词映射到空格字符结束的ToUnicode地图有问题的0000的字体。因此,iText的计算X坐标的时候,这里增加了字间距值,因为根据PDF规范ISO 32000-1

字间距的工作方式相同字符间距,但仅适用于ASCII空格字符

(段的第一句9.3.3字间距)

遗憾的是它并没有考虑到

使用 简单字体或将代码32定义为单字节代码的复合字体时,字间距应适用于字符串中出现的每个单字节字符代码32。它不适用于多字节代码中字节值32的出现 。

(最后一句9.3节。3字间距)

在高于0000,因此,字间距不能即使它被映射到空格字符施加因为

  1. 所讨论的字体编码是纯的多字节和
  2. 即使在单字节编码空格字符的情况下,字间距也仅适用于单字节代码 32,而不是仅通过ASCII映射到空间字符的代码德32

通常这不是文本提取,一般PDF生成器使用该多字节编码的编码空格字符都知道,字间距并不适用于他们,因此,不要在一个问题将字间距从其默认的0值改变,所以这里的iText错误没有任何危害。字间距指令的使用通常指示使用将单字节代码32映射到空格字符的字体。

另一方面,您的PDF看起来似乎还没有在头脑中创建这个事实,它看起来像首先设置了字间距(0.2861 Tw),并且在认识到它没有区别之后,显式差距已被添加(TJ指令中的-286)。 (或者说是有问题的PDF生成器的发展历史的一部分。)

请注意,在TJ参数正值意味着向左移位,所以负值(如声称对-286上文)确实扩大或增加空白:

阵列TJ显示的一个或多个文本串,允许个人字形的定位。数组中的每个元素应该是一个字符串或一个数字。如果该元素是一个字符串,则该运算符应显示该字符串。如果是数字,则操作员应按该数量调整文本位置;也就是说,它应该翻译文本矩阵,T m。编号应以文本空间单位的千分之一表示(见第9.4.4节“文本空间详细信息”)。根据写入模式,该数量应从当前水平或垂直坐标中减去。在默认坐标系中,正向调整的效果是将下一个字形向左或向下移动给定量。图46显示了将偏移量传递给TJ的一个示例。

(表109 - 在ISO 32000-1文本显示运营商)

+1

你误解负值:他们这样做拉开差距。 – mkl

+1

如上所述,由于我们有严格的双字节编码,所以在这里任何地方都不应用字间距*,因此没有单字节32编码空间。 – mkl