【问题标题】:iTextSharp - Incorrect text positioniTextSharp - 文本位置不正确
【发布时间】:2016-02-19 14:19:15
【问题描述】:

在本例中提取单词的位置时: http://www.dertour.de/static/agb/2015/sommer/DER_Deutschland_So15.pdf 使用 iTextSharp 5.5.8

我得到一些单词的“不正确”坐标。例如在第一段的第 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);
           }
     }

【问题讨论】:

    标签: pdf character-encoding itextsharp itext text-extraction


    【解决方案1】:

    这确实是 iText 和 iTextSharp 中的一个错误:

    x 坐标极其不准确的行是那些设置了大字间距值的行,例如你的线路:

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

    Tw0.2861 参数很大。)

    根据相关字体的 ToUnicode 映射,每个单词末尾的 0000 映射到空格字符。因此,iText 在计算 x 坐标时在这里添加了单词间距值,因为根据 PDF 规范ISO 32000-1:

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

    (第 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 显示一个或多个文本字符串,允许单独的字形定位。数组的每个元素应为字符串或数字。如果元素是字符串,则此运算符应显示字符串。如果是数字,则操作者将文本位置调整该数量;也就是说,它应该翻译文本矩阵 Tm 。该数字应以文本空间单位的千分之一表示(见 9.4.4,“文本空间细节”)。根据书写模式,应从当前水平或垂直坐标中减去该数量。在默认坐标系中,正调整具有将绘制的下一个字形向左或向下移动给定量的效果。图 46 显示了将偏移量传递给 TJ 的效果示例。

    (表 109 - ISO 32000-1 中的文本显示运算符)

    【讨论】:

    • 您误解了负值:它们确实扩大了差距。
    • 如上所述,字间距在任何地方都不应用,因为我们有严格的两字节编码,所以没有单字节32编码空格.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-09
    • 2019-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多