ios - Type0 CMap 解析问题

标签 ios pdf fonts adobe scanning

我目前正在使用 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。

  • 如果字体是使用预定义编码之一的简单字体 MacRomanEncodingMacExpertEncodingWinAnsiEncoding,或者有一种编码,其Differences 数组仅包括从 Adob​​e 标准拉丁字符集中获取的字符名称和 Symbol 字体中的命名字符集(参见附件 D):

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

    b) 在 Adobe 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(例如,Adobe 和 Japan1)使用的字符集合的注册表和排序。

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

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

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

此外,如第 9.10.1 节所示,

  • 结构元素或标记内容序列的 ActualText 条目(参见 14.9.4,“替换 Text") 可用于直接指定文本内容

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

编辑

OP 通过邮件提供了相关文件 iPhoneConfigurationProfileRef-2013-GM.pdf 并指出

I am getting problem for every glyph.

The issue is that ranges present in PDF are not complete and are different from adobe-identity-cmap file.

If I only use CMap embedded in PDF, I get no mapping for every character and if I use adobe one the all mappings are wrong.

由于他没有得到任何字形的映射,让我们以扉页为例。

内容流包含这些与文本提取相关的操作:

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>

这与页面的外观非常匹配:

scrrenshot of the title page

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

相关文章:

ios - ParseFacebookUtilsV4、Swift 和 CocoaPods : unresolved identifier

ios - Xcode 12 模拟器崩溃

java - 如何与 PDFBox 协调这些文本位置和行位置?

python - PDFminer - 有没有办法从 pdfminer 将 pdf 转换为 html?

ios - 需要将 firebase 远程配置中的值更新到我的 plist

pdf - 是否可以从 J2ME 运行 pdf 文件

python - 停止 matplotlib 使用 Arial 字体

css - 服务器上的 wkhtmltopdf unicode 和自定义字体

html - 为什么斜体字体不起作用

ios - 跨多个 UIViewControllers 重用一个函数