如果PDF格式中存在编码和ToUnicode,如何在pdf中提取文本?如何映射呢?

时间:2016-10-14 06:44:16

标签: c++ c pdf qpdf

这里,我使用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.67786()12.679() - 3.75591()9.73429()] TJ

在突破中有一些不可见的装袋数据。那么如何将数据链接到cmap文件?

另一个问题是/在/差异中包含什么值?

10 0 obj << / BaseEncoding / WinAnsiEncoding / Differences [1 / g100 / g28 / g94 / g3 / g87 / g24 / g38 / g47 / g62] /类型/编码>>

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

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

here is pdf

按照cmd运行

qpdf --stream-data = uncompress input.pdf output.text

output.text

如果我将内容流数据传递到zlib,我得到的输出相同。请从链接

检查output.txt文件

2 个答案:

答案 0 :(得分:0)

首先是一般性问题

  

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

     

[...]如果你看到编码和ToUnicode都存在于pdf中。我知道如果只有ToUnicode,那么如何使用Cmap文件映射单个char。

在这种情况下,即当你有一个足够完整和正确的 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

     

在突破中有一些不可见的装袋数据。那么如何将数据链接到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 "

匹配渲染文件就好了:

Screenshot

第三是编码

  

另一个问题是/在/差异中包含什么值?

     

10 0 obj&lt;&lt; / BaseEncoding / WinAnsiEncoding / Differences [1 / g100 / g28 / g94 / g3 / g87 / g24 / g38 / g47 / g62] /类型/编码&gt;&gt;

根据PDF规范,

  

差异条目的值应为字符代码和字符名称数组,其组织如下:

     

代码 1 name 1,1 name 1, 2 ...

     

代码 2 name 2,1 name 2, 2 ...

     

...

     

代码 n name n,1 name n, 2 ...

     

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

因此,您的案例中的编码条目表示编码基本上是 WinAnsiEncoding ,区别在于代码1,...,9代表名为/ g100,/ g28,/的字形g94,/ g3,/ g87,/ g24,/ g38,/ g47和/ g62。

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

  

具有差异数组的编码仅包含取自Adobe标准拉丁字符集的字符名称和符号字体中的命名字符集(参见附件D)

样本中的“/ gXX”名称显然不在其中。

答案 1 :(得分:0)

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