3

在这里,我使用 qpdf 工具解压缩数据,下面是输出。如果您看到编码和 ToUnicode 都存在于 pdf 中。我知道是否只有 ToUnicode 存在,所以如何使用 Cmap 文件映射单个字符。但是如果您看到内容流的输出如下

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.32338()-2.32338()2.786() -3.75591()9.73429()]TJ

在 break-at 中有一些不可见的垃圾数据。那么如何将数据链接到cmap文件?

另一个问题是 /Encoding 中包含的值是什么?

10 0 obj << /BaseEncoding /WinAnsiEncoding /Differences [ 1 /g100 /g28 /g94 /g3 /g87 /g24 /g38 /g47 /g62 ] /Type /Encoding >>

即使我将差异数组的值一一传递到 FreeType 函数之一,也被命名为 FT_Get_Name_Indek。此函数返回值如 [ 100 28 94 3 87 24 38 47 62]

这些价值观是什么?如何映射那些价值?

这是pdf

按照cmd运行

qpdf --stream-data=解压缩 input.pdf output.text

输出文本

如果我将内容流数据传递到 zlib 中,我得到的输出相同。请从链接检查 output.txt 文件

4

2 回答 2

4

首先是一般性问题

如果编码和ToUnicode都存在于pdf中,如何提取pdf中的文本?如何映射它?

[...] 如果您看到编码和 ToUnicode 都存在于 pdf 中。我知道是否只有 ToUnicode 存在,所以如何使用 Cmap 文件映射单个字符。

在这种情况下,即当您同时拥有足够完整和正确的ToUnicode映射和字体的编码时,您可以忽略编码并仅使用ToUnicode映射。

这遵循 PDF 规范,该规范在第 9.10.2 节“将字符代码映射到 Unicode 值”中指出,将字符代码映射到具有最高优先级的 Unicode 值的方法是

如果字体字典包含 ToUnicode CMap(参见 9.10.3,“ToUnicode CMaps”),则使用该 CMap 将字符代码转换为 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

在 break-at 中有一些不可见的垃圾数据。那么如何将数据链接到cmap文件?

括号中是标识字形的值,因此它们绝对不是垃圾。

因此,这里是括号内的字节值:

[(
    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 "

与渲染文件匹配得很好:

截屏

三、编码

另一个问题是 /Encoding 中包含的值是什么?

10 0 obj << /BaseEncoding /WinAnsiEncoding /Differences [ 1 /g100 /g28 /g94 /g3 /g87 /g24 /g38 /g47 /g62 ] /Type /Encoding >>

根据 PDF 规范,

差异条目的值应是一组字符代码和字符名称,其组织方式如下:

代码1 名称1,1 名称1,2 ...</p>

代码2 名称2,1 名称2,2 ...</p>

…</p>

代号n 名称n,1 名称n,2 ...</p>

每个代码应是要更改的字符代码序列中的第一个索引。代码后的第一个字符名称成为该代码对应的名称。随后的名称替换连续的代码索引,直到下一个代码出现在数组中或数组结束。这些序列可以按任何顺序指定,但不得重叠。

因此,在您的情况下,编码条目表示编码基本上是WinAnsiEncoding,不同之处在于代码 1、...、9 代表名为 /g100、/g28、/g94、/g3、/g87、/g24 的字形、/g38、/g47 和 /g62。

由于这些字形名称不是标准字形名称,因此 PDF 规范不认为这种编码对文本提取有帮助,因为它只描述了一种简单字体的方法

有一个编码,其差异数组仅包含取自 Adob​​e 标准拉丁字符集的字符名称和符号字体中的命名字符集(参见附录 D)

您的示例中的“/gXX”名称显然不在其中。

于 2016-10-17T12:42:41.620 回答
0

值得注意的是,大多数情况下,/Encoding映射是字符代码(旨在作为字符串的编码字节)到CID映射,其中大多数字体类型中的CID(字符 ID)对应于字形索引/标识符。Type2字体似乎例外,它具有单独的CIDGID(字形 ID)概念,提供/CIDToGIDMap在它们之间进行转换的方法。在上述情况下,映射与解码字符串的Unicode/Encoding表示无关。要解码 Unicode 表示,您绝对应该使用/ToUnicode可用时,正如 bt @mkl 指出的那样。如果它不可用,则在一种情况下,您要么具有预定义的编码(可选地使用/Difference映射)或CMap,要么在字体程序提供隐式编码的情况下,例如Type1字体。这一切都在非常好的@mkl答案中得到了说明。当它是预定义的编码(如MacRomanEncodingMacExpertEncodingWinAnsiEncoding/Encoding )时,可能对应于要在字符代码和 Unicode代码点之间转换的映射,但我也看到使用了可能不兼容的 Identity-H,这是一个预定义的CMap名称,而不是预定义的编码)或采用了一种假定格式错误的字体。在这方面,PDF 参考/标准通常会混淆什么是合法的,什么是不合法的,因此解码 PDF 中编码字符串的库应始终尽可能宽松。此外,PDF 参考/标准本身在解释字符代码CIDGIDUnicode表示之间的区别方面也不是很清楚。

于 2021-06-21T08:59:12.837 回答