我目前正在使用PDFKitten进行iOS PDF扫描。
我正在尝试提取文本以在具有Type0字体的PDF中进行搜索。我无法从PDF中提取文本。
ToUnicode 中的某些条目丢失,并且某些条目被误解了。
CMap的解析是否存在问题?
如果我没有完整的CMap,应该如何导出?
我可以为这些缺少的 ToUnicode 条目获取外部条目吗?

谢谢

最佳答案

PDF specification在第9.10.2节“将字符代码映射到Unicode值”中提供有关如何提取文本内容的提示:

  • 如果字体字典包含 ToUnicode CMap(请参见9.10.3,“ToUnicode CMaps”),请使用该CMap将字符代码转换为Unicode。
  • 如果字体是使用预定义编码之一的简单字体 MacRomanEncoding MacExpertEncoding WinAnsiEncoding ,或者其编码的差异数组仅包含标准字符集以及Symbol字体中的命名字符集(请参见附件D):

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

    b)在Adobe字形列表(请参见参考书目)中查找字符名称,以获得
    对应的Unicode值。
  • 如果该字体是使用表118中列出的预定义CMap之一(Identity–H和Identity–V除外)的复合字体,或者其后代CIDFont使用Adobe-GB1,Adobe-CNS1,Adobe-Japan1或Adobe- Korea1个字符集:

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

    b)从字体的CMap(例如Adobe和Japan1)的 CIDSystemInfo 词典中获取字符集的注册表和顺序。

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

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

    e)根据步骤(d)中获得的CMap映射步骤(a)中获得的CID,生成Unicode值。

  • 此外,如9.10.1节所述,
  • 结构元素或标记内容序列的ActualText条目(请参见14.9.4,“替换
    文字”)可用于直接指定文字内容

  • 根据规范,如果这些方法无法产生Unicode值,则无法确定字符代码代表什么。这不是完全正确的。例如嵌入式字体程序可能包含其自己的Unicode映射;但是此类其他信息源超出了实际的PDF格式。

    编辑

    OP通过邮件提供了有问题的文件iPhoneConfigurationProfileRef-2013-GM.pdf,并指明了

    每个字形都出现问题。

    问题在于PDF中存在的范围不完整,并且与adobe-identity-cmap文件不同。

    如果仅使用嵌入在PDF中的CMap,则每个字符都不会得到映射,如果使用Adobe,所有映射都是错误的。

    由于他没有获得任何字形的映射,因此让我们以标题页为例。

    内容流包含与文本提取相关的以下操作:
    BT
    50 0 0 50 60 669.225 Tm
    /G1 1 Tf
    <0025> Tj
    ET
    BT
    50 0 0 50 87.6 669.225 Tm
    /G1 1 Tf
    <005100500048004b004900570054> Tj
    ET
    BT
    50 0 0 50 238 669.225 Tm
    /G1 1 Tf
    <0043> Tj
    ET
    BT
    50 0 0 50 261.45 669.225 Tm
    /G1 1 Tf
    <0056004b00510050> Tj
    ET
    BT
    50 0 0 50 355.4 669.225 Tm
    /G1 1 Tf
    <0032> Tj
    ET
    BT
    50 0 0 50 380.75 669.225 Tm
    /G1 1 Tf
    <0054> Tj
    ET
    BT
    50 0 0 50 396.55 669.225 Tm
    /G1 1 Tf
    <00510048004b004e0047> Tj
    ET
    BT 50 0 0 50 60 609.225 Tm
    /G1 1 Tf
    <0034> Tj
    ET
    BT
    50 0 0 50 86.65 609.225 Tm
    /G1 1 Tf
    <00470048> Tj
    ET
    BT
    50 0 0 50 125.05 609.225 Tm
    /G1 1 Tf
    <00470054> Tj
    ET
    BT
    50 0 0 50 165.45 609.225 Tm
    /G1 1 Tf
    <004700500045> Tj
    ET
    BT
    50 0 0 50 238.9 609.225 Tm
    /G1 1 Tf
    <0047> Tj
    ET
    

    因此,我们仅需要查看第1页上的字体 G1 。幸运的是,该字体具有 ToUnicode 映射:
    /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
    <0000><FFFF>
    endcodespacerange
    1 beginbfchar
    <000f><002d 2010>
    endbfchar
    15 beginbfrange
    <0002><0002><0020>
    <0004><000c><0022>
    <000e><000e><002c>
    <0010><001d><002e>
    <001f><001f><003d>
    <0022><0032><0040>
    <0034><003d><0052>
    <003f><003f><005d>
    <0041><0041><005f>
    <0043><005c><0061>
    <005e><005e><007c>
    <008a><008a><00a9>
    <00a4><00a4><2014>
    <00a5><00a6><201c>
    <00a8><00a8><2019>
    endbfrange
    endcmap
    CMapName currentdict /CMap defineresource pop
    end
    end
    

    尝试应用此映射(基于显式的beginbfrange...endbfrange条目):
    <0025> Tj                          % "C"       = <0043>                         due to <0022><0032><0040>
    <005100500048004b004900570054> Tj  % "onfigur" = <006f006e00660069006700750072> due to <0043><005c><0061>
    <0043> Tj                          % "a"       = <0061>                         due to <0043><005c><0061>
    <0056004b00510050> Tj              % "tion"    = <00740069006f006e>             due to <0043><005c><0061>
    <0032> Tj                          % "P"       = <0050>                         due to <0022><0032><0040>
    <0054> Tj                          % "r"       = <0072>                         due to <0043><005c><0061>
    <00510048004b004e0047> Tj          % "ofile"   = <006f00660069006c0065>         due to <0043><005c><0061>
    <0034> Tj                          % "R"       = <0052>                         due to <0034><003d><0052>
    <00470048> Tj                      % "ef"      = <00650066>                     due to <0043><005c><0061>
    <00470054> Tj                      % "er"      = <00650072>                     due to <0043><005c><0061>
    <004700500045> Tj                  % "enc"     = <0065006e0063>                 due to <0043><005c><0061>
    <0047> Tj                          % "e"       = <0065>                         due to <0043><005c><0061>
    

    这非常符合页面的外观:

    关于ios - Type0 CMap解析问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26907600/

    10-10 05:35