在此示例中提取单词的位置时: 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'之间空格字符的右下角的x值。而且' oder'是208,这似乎是正确的,也似乎是“oder”这个词的正确x-pos。也许它与段落的fillmode有关,但我不确定我应该采取哪些操作来获得正确的坐标。
我使用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);
}
}
答案 0 :(得分:1)
这确实是iText&amp; iTextSharp的:
具有极不准确的x坐标的行是设置了大字数间隔值的行,例如,你的行:
0.2861 Tw T*
[<0047004500480045004E0000>-286<004F0044004500520000>-286<0049004D0000>-231<003700490044004500520053005000520055004300480000>-286<005A005500520000>-286<00320045004900530045004100550053000D>]TJ
(0.2861
的{{1}}参数很大。)
根据相关字体的 ToUnicode 地图,每个单词末尾的Tw
映射到空格字符。因此,iText在计算 x 坐标时会添加单词间距值,因为根据PDF规范ISO 32000-1:
字间距与字符间距的工作方式相同,但仅适用于ASCII空格字符
(第9.3.3节“Word间距”的第一句)
不幸的是,它没有考虑到
在使用时,字间距应适用于字符串中每次出现的单字节字符代码32 简单字体或复合字体,将代码32定义为单字节代码。它不适用于。的出现 多字节代码中的字节值32。
(第9.3.3节“Word间距”的最后一句)
因此,在0000
以上,不得应用字间距,即使它已映射到空格字符,因为
通常这在文本提取过程中不是问题,通常使用多字节编码对空格字符进行编码的PDF生成器会发现字间距不适用于它们,因此不会改变字间距。默认值为0,因此这里的iText错误没有任何危害。字间距指令的使用通常表示使用的字体将单字节代码32映射到空格字符。
另一方面,你的PDF似乎并没有在脑海中创造出这样的事实,看起来首先设置了单词间距(0000
),并且在认识到它没有区别之后,已添加显式间隙(0.2861 Tw
指令中的-286
。 (或者这是PDF生成器开发历史的一部分。)
请注意 TJ 参数中的正值表示向左移位,因此负值(如上文TJ
所述)确实扩大或增加差距:
array TJ 显示一个或多个文本字符串,允许单独的字形定位。数组的每个元素应该是字符串或数字。如果元素是字符串,则此运算符应显示字符串。如果是数字,运营商应按该数量调整文本位置;也就是说,它应翻译文本矩阵 T m 。数字应以文本空间为单位的千分之一表示(见9.4.4,&#34;文本空间详细信息&#34;)。根据写入模式,该量应从当前水平或垂直坐标中减去。在默认坐标系中,正调整具有将下一个字形向左或向下移动给定量的效果。图46显示了将偏移量传递给 TJ 的效果示例。
(表109 - ISO 32000-1中的文字显示运算符)