2

使用peepdf我正在分析两个简单的 pdf 文件。这两个文件都包含一行文本(“ZYXWVUTSRQQRSTUVWXYZ”),并且是在 Mac OS X 上创建的。

第一个文件是用 TextEdit 创建的。只有三个流,看第一个(用peepdf自动解码)清楚地显示文本。

PPDF> stream 4

q Q q 72 707.272 468 12.72803 re W n /Cs1 cs 0 sc q 0.9790795 0 0 -0.9790795 72 720
cm BT 0.0001 Tc 11 0 0 -11 5 10 Tm /TT1 1 Tf (ZYXWVUTSRQQRSTUVWXYZ) Tj ET
Q Q

第二个文件是用 MS Word 创建的。有四个流,但无法找到解码的文本。查看 Word 文档中的相应流不会显示解码的字符串:

PPDF> stream 4

q Q q 18 40 576 734 re W n /Cs1 cs 0 0 0 sc q 0.24 0 0 0.24 90 708.72 cm BT
-0.0004 Tc 50 0 0 50 0 0 Tm /TT2 1 Tf [ (!") -1 (#) -1 ($) -1 (%&'\() -1 (\))
-1 (*) -1 (*) -1 (\)) -1 (\() -1 ('&%$) -1 (#) -1 (") -1 (!) ] TJ ET Q q 0.24 0 0 0.24 239.168 708.72
cm BT 50 0 0 50 0 0 Tm /TT2 1 Tf (+) Tj ET Q Q

对我来说,字符串在文件中的位置或此流中的信息的含义并不明显。有什么见解吗?

4

2 回答 2

5

我不清楚字符串在文件中的位置

通常,您不会在内容流中看到明文,因为那里使用的编码不需要是标准编码,也不需要 ASCII'ish。

[ (!") -1 (#) -1 ($) -1 (%&'\() -1 (\)) -1 (*) -1 (*) -1 (\)) -1 (\() -1 ('&%$) -1 (#) -1 (") -1 (!) ] TJ

此操作在其数组操作数中包含您ZYXWVUTSRQQRSTUVWXYZ对某些字符对的一些字距修正。

它看起来像是使用从 33 (= 0x21 = '!') 开始的字节的 ad hoc 编码。'!' 用于需要的第一个字形,Z, '"' 用于需要的第二个Y, '#' 用于第三个X等。您的测试字符串不仅以这些字符开头,而且以它们结尾,也是如此上面的数组,(!") -1 (#)...(#) -1 (") -1 (!)

检查所用字体的定义 ( TT2 )。它可能(或可能不)包含帮助您解码此编码的信息。

或者这个流中的信息是什么意思。有什么见解吗?

要了解 PDF 内容流的内容,您应该阅读 PDF 规范ISO 32000-1的相关部分,尤其是第 8 章图形和第 9章文本

由于您的问题集中在文本内容的识别上,例如阅读第 9.10.2 节将字符代码映射到 Unicode 值

符合标准的读者可以使用这些方法,按照给定的优先级,将字符代码映射到 Unicode 值。带标签的 PDF 文档尤其应提供以下方法中的至少一种(参见 14.8.2.4.2,“带标签的 PDF 中的 Unicode 映射”):

  • 如果字体字典包含ToUnicode CMap(参见 9.10.3,“ToUnicode CMaps”),则使用该 CMap 将字符代码转换为 Unicode。

  • 如果字体是使用预定义编码MacRomanEncodingMacExpertEncodingWinAnsiEncoding之一的简单字体,或者其差异数组仅包含取自 Adob​​e 标准拉丁字符集的字符名称和符号中的命名字符集的编码字体(见附件 D):

    a) 根据表 D.1 和字体的差异数组将字符代码映射到字符名称。

    b) 在Adob​​e Glyph List(参见参考书目)中查找字符名称以获得对应的 Unicode 值。

  • 如果字体是使用表 118 中列出的预定义 CMap 之一的复合字体(Identity-H 和 Identity-V 除外)或其后代 CIDFont 使用 Adob​​e-GB1、Adobe-CNS1、Adobe-Japan1 或 Adob​​e-Korea1人物合集:

    a) 根据字体的 CMap 将字符代码映射到字符标识符 (CID)。

    b) 从其CIDSystemInfo字典中获取字体的 CMap(例如 Adob​​e 和 Japan1)使用的字符集合的注册表和排序。

    c) 通过将在步骤 (b) 中获得的注册表和排序以注册表-排序-UCS2 格式(例如,Adobe-Japan1-UCS2)连接,构造第二个 CMap 名称。

    d) 获取具有在步骤 (c) 中构建的名称的 CMap(可从 ASN 网站获得;参见参考书目)。

    e) 根据步骤(d)得到的CMap映射步骤(a)得到的CID,产生一个Unicode值。

注 其后代 CIDFonts 使用 Adob​​e-GB1、Adobe-CNS1、Adobe-Japan1 或 Adob​​e-Korea1 字符集(在 CIDSystemInfo 字典中指定)的 Type 0 字体应具有与符合标准的 PDF 版本相对应的补充编号。读者。有关给定 PDF 版本对应的字符集列表,请参见表 3。(可以使用这些字符集的其他增补,但如果增补的编号比支持的 PDF 版本对应的编号高,则仅后一增补中的 CID 被视为标准 CID。)

如果这些方法无法生成 Unicode 值,则无法确定字符代码代表什么,在这种情况下,符合标准的读者可以选择他们选择的字符代码。

编辑: 关于评论

其中一个对象提供了一些字体信息。它是“JJOWGO+Cambria”并将对象 16 引用为“字体文件”,这也是不可读的。我会查看手册。在网上找不到任何关于“JJOWGO”的信息。

您不会找到任何具体的内容,JJOWGO因为它很可能是一个随机键序列,前缀Cambria表示并非所有字体都被嵌入,而只是一个子集。参照。ISO 32000-1的第 9.6.4 节字体子集:

PDF 文档可能包含 Type 1 和 TrueType 字体的子集。描述字体子集的字体和字体描述符与普通字体略有不同。这些差异允许符合标准的阅读器识别字体子集并合并包含相同字体的不同子集的文档。(有关字体描述符的更多信息,请参阅 9.8,“字体描述符”。)

对于字体子集,字体的 PostScript 名称——字体的BaseFont条目和字体描述符的FontName条目的值——应以标记开头,后跟加号 (+)。标签应由六个大写字母组成;字母的选择是任意的,但是同一个PDF文件中的不同子集应该有不同的标签。

示例 EOODIA+Poetica 是 Poetica® 子集的名称,一种 Type 1 字体。

 <<
 /FontBBox [ -1475 -2463 2867 3117 ]
 /StemV 0
 /FontFile2 16 0 R
 /Descent -222
 /XHeight 467
 /Flags 4
 /Ascent 950
 /FontName /JJOWGO+Cambria
 /Type /FontDescriptor
 /ItalicAngle 0
 /AvgWidth 615
 /MaxWidth 2919
 /CapHeight 667
 >>

此字体描述符不包含明显的编码信息。查看实际的字体字典并查找ToUnicode条目,参见。引用上文第 9.10.2 节的内容。

于 2014-03-17T05:57:31.217 回答
3

@mkl 的评论清楚地表明了正在发生的事情。MS Word 生成的 pdf 中的文本使用了字符映射。

我通过搜索具有 ToUnicode 条目的对象来跟踪字体字典:

<< /FirstChar 33
/Widths [ 538 570 571 921 604 648 593 496 621 653 220 ]
/Type /Font
/BaseFont /JJOWGO+Cambria
/LastChar 43
/Subtype /TrueType
/FontDescriptor 13 0 R
/ToUnicode 14 0 R >>

ToUnicode 条目引用了对象 14,所以我接下来看了一下:

/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CIDSystemInfo <<
  /Registry (Adobe)
  /Ordering (UCS)
  /Supplement 0
>> def
/CMapName /Adobe-Identity-UCS def
/CMapType 2 def
1 begincodespacerange
<00><FF>
endcodespacerange
1 beginbfchar
<2b><0009 000d 0020 00a0>
endbfchar
10 beginbfrange
<21><21><005a>
<22><22><0059>
<23><23><0058>
<24><24><0057>
<25><25><0056>
<26><26><0055>
<27><27><0054>
<28><28><0053>
<29><29><0052>
<2a><2a><0051>
endbfrange
endcmap
CMapName currentdict /CMap defineresource pop
end
end

ISO 32000-1 的第 9.10.3 节解释了 beginbfrange 如何将字符范围相互映射。字符代码范围映射到 Unicode 值。“范围” 21-21 包含一个字符,即“!”。它映射到 U+005a(“Z”)。映射包含我的测试文档中从 Z 到 Q 的每个字符的一行。(!到 *)

于 2014-03-18T14:25:38.720 回答