iTextSharp的 - 不正确的文本位置
在提取的话,在这个例子中的位置: 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);
}
}
实际上就是在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
,因此,字间距不能即使它被映射到空格字符施加因为
- 所讨论的字体编码是纯的多字节和
- 即使在单字节编码空格字符的情况下,字间距也仅适用于单字节代码 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文本显示运营商)
你误解负值:他们这样做拉开差距。 – mkl
如上所述,由于我们有严格的双字节编码,所以在这里任何地方都不应用字间距*,因此没有单字节32编码空间。 – mkl