如何提取 pdf 中的文本编码和 ToUnicode 都存在于 pdf 中?怎么映射呢?
how to exract the text in pdf if encoding and ToUnicode both are present in pdf? how to map it?
这里我用qpdf工具解压了数据,下面是输出。如果您看到 encoding 和 ToUnicode 都存在于 pdf 中。我知道是否只有 ToUnicode 存在,所以如果您看到内容流的输出在
之后,如何使用 Cmap file.but 映射单个字符
Tf
0.999402 0 0 1 71.9995 759.561 TM
[()-2.11826()-1.14177()2.67786()-2.11826()8.55269()-5.44998()-4.70186()2.67786()-2.32338()2.67786()12.679()-3.75591()9.73429()] TJ
在break-at中有一些不可见的垃圾数据。那么如何link数据到cmap文件?
另一个问题是,在 /Encoding 中 Difference 中包含什么值?
10 0 个对象
<< /BaseEncoding /WinAnsiEncoding /Differences [ 1 /g100 /g28 /g94 /g3 /g87 /g24 /g38 /g47 /g62 ] /Type /Encoding >>
甚至我将 Difference 数组的值一个一个地传递到一个名为 FT_Get_Name_Indek 的 FreeType 函数中。此函数 return 值如 [ 100 28 94 3 87 24 38 47 62]
这些值是什么?如何映射这些值?
运行 跟随 cmd
qpdf --stream-data=uncompress input.pdf output.text
如果我将内容流数据传递到 zlib,我会得到相同的输出。请检查来自 link
的 output.txt 文件
首先是一般性问题
how to exract the text in pdf if encoding and ToUnicode both are present in pdf? how to map it?
[...] if you see there are encoding and ToUnicode both are present in pdf. i know if only ToUnicode is there so how to map individual char with Cmap file.
在这种情况下,即当您拥有足够完整和正确的 ToUnicode 映射和字体的 Encoding 时,你可以忽略编码,只使用ToUnicode映射。
这来自 PDF 规范,该规范在第 9.10.2 节 "Mapping Character Codes to Unicode Values" 中指出,将字符代码映射到具有最高优先级的 Unicode 值的方法是
If the font dictionary contains a ToUnicode CMap (see 9.10.3, "ToUnicode CMaps"), use that CMap to convert the character code to Unicode.
因此,如果您(如您所说)已经知道如何在只有 ToUnicode 映射的情况下提取文本,则可以使用相同的算法不变。作为推论,如果这不起作用,则有问题的 ToUnicode 映射不够完整或不正确,或者您对如何仅使用 提取文本的知识本身ToUnicode图其实是不完整的。
其次是示例文档
你写了
[()-2.11826()-1.14177()2.67786()-2.11826()8.55269()-5.44998()-4.70186()2.67786()-2.32338()2.67786()12.679( )-3.75591()9.73429()]TJ
in break-at there are some garbag data that is not visible. so how to link data to cmap file ?
括号中是标识字形的值,因此它们绝对不是垃圾。
因此,这里是括号内的字节值:
[(
01
)-2.11826(
02
)-1.14177(
03
)2.67786(
01
)-2.11826(
04
)8.55269(
05
)-5.44998(
06
)-4.70186(
07
)2.67786(
04
)-2.32338(
07
)2.67786(
08
)12.679(
09
)-3.75591(
02
)9.73429(
04
)]TJ
使用相关字体的 ToUnicode 映射
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CMapType 2 def
1 begincodespacerange
<00><ff>
endcodespacerange
9 beginbfrange
<01><01><0054>
<02><02><0045>
<03><03><0053>
<04><04><0020>
<05><05><0050>
<06><06><0044>
<07><07><0046>
<08><08><0049>
<09><09><004c>
endbfrange
endcmap
CMapName currentdict /CMap defineresource pop
end end
括号内的字节值映射到:
01 0054 "T"
02 0045 "E"
03 0053 "S"
01 0054 "T"
04 0020 " "
05 0050 "P"
06 0044 "D"
07 0046 "F"
04 0020 " "
07 0046 "F"
08 0049 "I"
09 004c "L"
02 0045 "E"
04 0020 " "
因此,
"TEST PDF FILE "
与渲染文件匹配得很好:
第三是编码
and one another question is that in /Encoding what are values contain in Difference ?
10 0 obj << /BaseEncoding /WinAnsiEncoding /Differences [ 1 /g100 /g28 /g94 /g3 /g87 /g24 /g38 /g47 /g62 ] /Type /Encoding >>
根据PDF规范,
The value of the Differences entry shall be an array of character codes and character names organized as follows:
code1 name1,1 name1,2 …
code2 name2,1 name2,2 …
…
coden namen,1 namen,2 …
Each code shall be the first index in a sequence of character codes to be changed. The first character name after the code becomes the name corresponding to that code. Subsequent names replace consecutive code indices until the next code appears in the array or the array ends. These sequences may be specified in any order but shall not overlap.
因此,您的编码条目表示编码基本上是 WinAnsiEncoding,区别在于代码 1、...、9 代表名为 /g100 的字形, /g28, /g94, /g3, /g87, /g24, /g38, /g47, /g62.
由于这些字形名称不是标准字形名称,PDF 规范认为这种编码对文本提取没有帮助,因为它只描述了一种简单字体的方法
that has an encoding whose Differences array includes only character names taken from the Adobe standard Latin character set and the set of named characters in the Symbol font (see Annex D)
您样本中的“/gXX”名称显然不在其中。
值得注意的是,大多数时候 /Encoding
映射是 字符代码 (旨在作为字符串的编码字节)到 CID 映射,其中 CID(字符 ID)在大多数字体类型中对应一个字形 index/identifier。 Type2 字体出现异常,这些字体具有单独的 CID 和 GID(字形 ID)概念,提供a /CIDToGIDMap
在它们之间进行转换。在上述情况下,/Encoding
映射与解码字符串的 Unicode 表示无关。要解码 Unicode 表示,您绝对应该在可用时使用 /ToUnicode
,如 bt @mkl 所指出的。如果它不可用,那么在一种情况下,您要么具有预定义编码(可选地使用 /Difference
映射)或 CMap,要么在这种情况下字体程序提供隐式编码,如 Type1 字体。这在非常好的@mkl answer 中也有说明。 /Encoding
可能对应于在 字符代码 和 Unicode 代码点 之间转换的映射,当它是预定义编码(如 MacRomanEncoding、MacExpertEncoding 或 WinAnsiEncoding,但我也看到使用了可能不兼容的 Identity-H,这是一个预定义的 CMap 名称,而不是预定义的编码)或假定格式错误的字体。在这方面,PDF reference/standard 经常混淆什么是合法的,什么是不合法的,因此解码 PDF 中的编码字符串的库应始终尽可能宽松。此外,PDF reference/standard 本身在解释 字符代码 、CID、GID[ 之间的区别时也不是很清楚=39=] 和 Unicode 表示。
这里我用qpdf工具解压了数据,下面是输出。如果您看到 encoding 和 ToUnicode 都存在于 pdf 中。我知道是否只有 ToUnicode 存在,所以如果您看到内容流的输出在
之后,如何使用 Cmap file.but 映射单个字符Tf 0.999402 0 0 1 71.9995 759.561 TM [()-2.11826()-1.14177()2.67786()-2.11826()8.55269()-5.44998()-4.70186()2.67786()-2.32338()2.67786()12.679()-3.75591()9.73429()] TJ
在break-at中有一些不可见的垃圾数据。那么如何link数据到cmap文件?
另一个问题是,在 /Encoding 中 Difference 中包含什么值?
10 0 个对象 << /BaseEncoding /WinAnsiEncoding /Differences [ 1 /g100 /g28 /g94 /g3 /g87 /g24 /g38 /g47 /g62 ] /Type /Encoding >>
甚至我将 Difference 数组的值一个一个地传递到一个名为 FT_Get_Name_Indek 的 FreeType 函数中。此函数 return 值如 [ 100 28 94 3 87 24 38 47 62]
这些值是什么?如何映射这些值?
运行 跟随 cmd
qpdf --stream-data=uncompress input.pdf output.text
如果我将内容流数据传递到 zlib,我会得到相同的输出。请检查来自 link
的 output.txt 文件首先是一般性问题
how to exract the text in pdf if encoding and ToUnicode both are present in pdf? how to map it?
[...] if you see there are encoding and ToUnicode both are present in pdf. i know if only ToUnicode is there so how to map individual char with Cmap file.
在这种情况下,即当您拥有足够完整和正确的 ToUnicode 映射和字体的 Encoding 时,你可以忽略编码,只使用ToUnicode映射。
这来自 PDF 规范,该规范在第 9.10.2 节 "Mapping Character Codes to Unicode Values" 中指出,将字符代码映射到具有最高优先级的 Unicode 值的方法是
If the font dictionary contains a ToUnicode CMap (see 9.10.3, "ToUnicode CMaps"), use that CMap to convert the character code to Unicode.
因此,如果您(如您所说)已经知道如何在只有 ToUnicode 映射的情况下提取文本,则可以使用相同的算法不变。作为推论,如果这不起作用,则有问题的 ToUnicode 映射不够完整或不正确,或者您对如何仅使用 提取文本的知识本身ToUnicode图其实是不完整的。
其次是示例文档
你写了
[()-2.11826()-1.14177()2.67786()-2.11826()8.55269()-5.44998()-4.70186()2.67786()-2.32338()2.67786()12.679( )-3.75591()9.73429()]TJ
in break-at there are some garbag data that is not visible. so how to link data to cmap file ?
括号中是标识字形的值,因此它们绝对不是垃圾。
因此,这里是括号内的字节值:
[(
01
)-2.11826(
02
)-1.14177(
03
)2.67786(
01
)-2.11826(
04
)8.55269(
05
)-5.44998(
06
)-4.70186(
07
)2.67786(
04
)-2.32338(
07
)2.67786(
08
)12.679(
09
)-3.75591(
02
)9.73429(
04
)]TJ
使用相关字体的 ToUnicode 映射
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CMapType 2 def
1 begincodespacerange
<00><ff>
endcodespacerange
9 beginbfrange
<01><01><0054>
<02><02><0045>
<03><03><0053>
<04><04><0020>
<05><05><0050>
<06><06><0044>
<07><07><0046>
<08><08><0049>
<09><09><004c>
endbfrange
endcmap
CMapName currentdict /CMap defineresource pop
end end
括号内的字节值映射到:
01 0054 "T"
02 0045 "E"
03 0053 "S"
01 0054 "T"
04 0020 " "
05 0050 "P"
06 0044 "D"
07 0046 "F"
04 0020 " "
07 0046 "F"
08 0049 "I"
09 004c "L"
02 0045 "E"
04 0020 " "
因此,
"TEST PDF FILE "
与渲染文件匹配得很好:
第三是编码
and one another question is that in /Encoding what are values contain in Difference ?
10 0 obj << /BaseEncoding /WinAnsiEncoding /Differences [ 1 /g100 /g28 /g94 /g3 /g87 /g24 /g38 /g47 /g62 ] /Type /Encoding >>
根据PDF规范,
The value of the Differences entry shall be an array of character codes and character names organized as follows:
code1 name1,1 name1,2 …
code2 name2,1 name2,2 …
…
coden namen,1 namen,2 …
Each code shall be the first index in a sequence of character codes to be changed. The first character name after the code becomes the name corresponding to that code. Subsequent names replace consecutive code indices until the next code appears in the array or the array ends. These sequences may be specified in any order but shall not overlap.
因此,您的编码条目表示编码基本上是 WinAnsiEncoding,区别在于代码 1、...、9 代表名为 /g100 的字形, /g28, /g94, /g3, /g87, /g24, /g38, /g47, /g62.
由于这些字形名称不是标准字形名称,PDF 规范认为这种编码对文本提取没有帮助,因为它只描述了一种简单字体的方法
that has an encoding whose Differences array includes only character names taken from the Adobe standard Latin character set and the set of named characters in the Symbol font (see Annex D)
您样本中的“/gXX”名称显然不在其中。
值得注意的是,大多数时候 /Encoding
映射是 字符代码 (旨在作为字符串的编码字节)到 CID 映射,其中 CID(字符 ID)在大多数字体类型中对应一个字形 index/identifier。 Type2 字体出现异常,这些字体具有单独的 CID 和 GID(字形 ID)概念,提供a /CIDToGIDMap
在它们之间进行转换。在上述情况下,/Encoding
映射与解码字符串的 Unicode 表示无关。要解码 Unicode 表示,您绝对应该在可用时使用 /ToUnicode
,如 bt @mkl 所指出的。如果它不可用,那么在一种情况下,您要么具有预定义编码(可选地使用 /Difference
映射)或 CMap,要么在这种情况下字体程序提供隐式编码,如 Type1 字体。这在非常好的@mkl answer 中也有说明。 /Encoding
可能对应于在 字符代码 和 Unicode 代码点 之间转换的映射,当它是预定义编码(如 MacRomanEncoding、MacExpertEncoding 或 WinAnsiEncoding,但我也看到使用了可能不兼容的 Identity-H,这是一个预定义的 CMap 名称,而不是预定义的编码)或假定格式错误的字体。在这方面,PDF reference/standard 经常混淆什么是合法的,什么是不合法的,因此解码 PDF 中的编码字符串的库应始终尽可能宽松。此外,PDF reference/standard 本身在解释 字符代码 、CID、GID[ 之间的区别时也不是很清楚=39=] 和 Unicode 表示。