首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Type0 CMap解析问题

Type0 CMap解析问题
EN

Stack Overflow用户
提问于 2014-11-13 11:14:11
回答 2查看 2.2K关注 0票数 2

我目前正在工作的iOS PDF扫描使用PDFKitten。我试图提取文本,以PDF格式搜索具有Type0字体。我无法从PDF中提取文本。ToUnicode中的一些条目丢失了,有些条目被曲解了。解析CMap会有问题吗?如果我没有完整的CMap,我应该如何导出它?我可以为这些缺失的ToUnicode条目提取外部条目吗?

谢谢

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-11-13 13:57:33

PDF规范在9.10.2节中提供了如何提取文本内容的提示,将字符代码映射到Unicode值

  • 如果字体字典包含ToUnicode CMap (参见9.10.3,"ToUnicode CMaps"),则使用CMap将字符代码转换为Unicode。
  • 如果字体是使用预定义编码之一MacRomanEncodingMacExpertEncoding,或WinAnsiEncoding,的简单字体,或者具有差异的编码,则数组仅包括从Adobe标准拉丁字符集和符号字体中的命名字符集合中提取的字符名称(见附件D): ( a)根据表D.1和字体的差异数组将字符代码映射到字符名。 b)在Adobe列表(请参阅书目)中查找字符名,以获得相应的Unicode值。
  • 如果字体是一种复合字体,该字体使用表118中列出的预定义CMaps之一(标识-H和标识-V除外),或者其后代CIDFont使用Adobe-GB1、Adobe-CNS1、Adobe 1或Adobe 1字符集合: ( a)根据字体的CMap将字符代码映射到字符标识符(CID)。 b)从字体的CIDSystemInfo字典中获取字体的CMap (例如,AdobeandJapan1)使用的字符集合的注册表和顺序。 ( c)通过连接注册表和格式注册表( CMap 2)中步骤(b)中获得的顺序(例如Adobe-japan1-UC 2)来构造第二个注册中心名称。 d)以步骤(c)中构造的名称获取CMap (可从ASN站点获得;请参阅书目)。 ( e)根据步骤(d)中获得的CMap映射步骤(a)中获得的CID,生成Unicode值。

此外,如第9.10.1节所述,

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

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

编辑

OP通过邮件和指示提供了有关文件iPhoneConfigurationProfileRef-2013-GM.pdf。

每个字形我都会遇到麻烦。 问题是PDF中的范围是不完整的,并且不同于cmap文件。 如果我只使用嵌入在PDF中的CMap,就不会得到每个字符的映射,如果使用adobe,则所有映射都是错误的。

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

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

代码语言:javascript
复制
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映射:

代码语言:javascript
复制
/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条目):

代码语言:javascript
复制
<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>

这非常符合页面的外观:

票数 5
EN

Stack Overflow用户

发布于 2021-06-11 12:44:34

它可能关注的是,如果/ToUnicode CMap中缺少了一些条目,并且字体不是指预定义的编码/CMap之一,那么Adobe /Acrobat的行为将像我经验性观察到的那样:

  • 如果编码为1字节代码空间大小,它将直接将缺失的代码解释为Unicode代码点(基本上是身份转换);
  • 如果编码是2字节代码空间大小,它将只将代码解码为无效字符。

我没有测试其他组合,比如可变代码空间大小。这帮助我正确地执行PDF格式的文本提取,该字体只有1字节编码字体,只列出了/ToUnicode CMap中的字母字符,省略了一些标点符号,这些标点符号是用常规的ASCII代码编码的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26907600

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档