我有一个PDF 1.3,我想在其中提取文本。 但是在流中有两种不同类型的文本。 一些纯文本和一些带有转义序列的字符编码文本。
这里有个例子:
/TextClip BMC
BT
/T1_2 1 Tf
0 Tc 0 Tw 7 Tr 16.2626 0 0 16.2626 37.2512 581.738 Tm
(Test Test)Tj
ET
EMC
q
/GS0 gs
67.6799985 0 0 -13.4399997 37.439994 594.2399583 cm
/Im47 Do
Q
Q
Q
q
37.499 569.52 179.713 8.34 re
W n
q
/GS0 gs
180.959996 0 0 -9.5999998 36.959999 578.3999755 cm
/Im48 Do
Q
Q
q
37.499 569.52 179.713 8.34 re
W n
q
/TextClip BMC
BT
0 Tc 0 Tw 7 Tr 9.899 0 0 9.899 37.2512 569.7178 Tm
[(\000E\000V\000d\000e\000\003\000E\000V\000d\000e)]TJ
ET
EMC
在此示例中,该文本是“ Test Test”文本的2倍。一次作为计划文本,另一次作为转义序列\000E\000V\000d\000e\000\003\000E\000V\000d\000e
。
我只知道,如果在转义序列后有3位数字,则这是一个八进制字符代码。但是在我的示例中,有一些4位数字,有时有3位数字。
转义序列后的第4个字符位于正确的ASCII码旁边的15。 (\000E
是字符“ T”)但是正确的转换是什么?
文本块\000\003
应该是空格符号。转换黑客有什么?
致谢
答案 0 :(得分:2)
显示诸如 TJ 和 Tj 之类的指令的文本的字符串参数的编码取决于相关的PDF字体,请参见。规格
文本显示运算符的字符串操作数应解释为标识要绘制的字形的字符代码序列。
使用简单字体时,字符串的每个字节均应视为单独的字符代码。然后应按照字体的编码查找字符代码以选择字形,如9.6.6“字符编码”所述。
对于复合字体(PDF 1.2),可以使用多字节代码来选择字形。在这种情况下,字符串的一个或多个连续字节应被视为单个字符代码。代码长度和从代码到字形的映射在称为 CMap 的数据结构中定义,如9.7“复合字体”中所述。
(第9.4.3节-文本显示运算符-在ISO 32000-1中)
用于显示第一个文本的字体
(Test Test)Tj
可能是带有ASCII码的简单字体,可能是 WinAnsiEncoding 。字体本身是在上方的两行中选择的
/T1_2 1 Tf
因此您只需要查找字体资源 T1_2 (如果您向我们展示页面内容流的摘录,则为页面资源)即可进行验证。
第二个文本显示操作中使用的字体
[(\000E\000V\000d\000e\000\003\000E\000V\000d\000e)]TJ
似乎是具有双字节编码的复合字体,可能是 Identity-H ,并且底层字体程序似乎具有在TrueType字体中最常见的字形代码。您应该使用该PDF字体寻找 ToUnicode 映射,以便于解码。
选择该字体的说明不在您发布的说明中,而必须在上方。此选择已保存为图形状态的一部分(在某些早期的 q 指令中)并再次恢复(在显示您共享的指令的两个文本之间的某些 Q 指令中)。
如果在转义序列后有3位数字,则为八进制字符代码。但是在我的示例中,有时是4位数字,有时是3位数字。
否,在您的示例中,总是存在带有三个八进制数字的转义序列。此后的字符是一个单独的字节,即您具有字节“ \ 000”,“ E”,“ \ 000”,“ V”,“ \ 000”,“ d”,“ \ 000”,“ e”,“ \ 000','\ 003','\ 000','E','\ 000','V','\ 000','d','\ 000'和'e'。
如上所述,这看起来像是双字节编码,尤其是映射
\000E -> 'T'
\000V -> 'e'
\000d -> 's'
\000e -> 't'
\000\003 -> ' ' (space)
这似乎是TrueType字体中经常出现的一种字形编码,对于拉丁字母而言,这只是表示其Unicode代码的常数偏移量。
但是也有许多常用的不同的多字节编码,有时甚至是专为手头页面上的字体创建的即席编码。
因此,如果您真的想从PDF中提取文本,则确实必须研究PDF规范并按照其要求实施,而不是希望有一些转换黑客。
Adobe已在其网页https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdfs/PDF32000_2008.pdf上发布了旧的PDF规范ISO 32000-1的副本