/差异字典用于 PDF 中的编码解析问题

/Differences dictionary for encode parsing issue in PDF

Type1 字体 /Differences 编码在值映射中使用字符串,例如 1 个字符被编码为 'one'。它仅用于数字和特殊字符。

使用这些编码的标准方式是什么?

我应该如何从使用这种编码的 PDF 中解码字符串?

Link 文件:http://www.filedropper.com/open

How should I decode string from PDF which uses such encoding?

如规范所述:

9.10.2 Mapping Character Codes to Unicode Values

A conforming reader can use these methods, in the priority given, to map a character code to a Unicode value. Tagged PDF documents, in particular, shall provide at least one of these methods:

  • If the font dictionary contains a ToUnicode CMap, use that CMap to convert the character code to Unicode.

  • If the font is a simple font that uses one of the predefined encodings MacRomanEncoding, MacExpertEncoding, or WinAnsiEncoding, or that has an encoding whose Differences array includes only character names taken from the Adobe standard Latin character set and the set of named characters in the Symbol font:

    a) Map the character code to a character name according to Table D.1 and the font’s Differences array.

    b) Look up the character name in the Adobe Glyph List to obtain the corresponding Unicode value.

  • If the font is a composite font ... (not applicable in your case)

If these methods fail to produce a Unicode value, there is no way to determine what the character code represents in which case a conforming reader may choose a character code of their choosing.

(ISO 32000-1)

因此,首先,您应该寻找 ToUnicode 映射。

如果有 none(如示例文档的情况),请使用 Encoding(预定义或差异)。

如果您的代码未映射到编码中的正确内容,根据规范 无法确定字符代码代表什么!

如果有问题的字体是嵌入的,您可能还有一个解决办法,就是解析嵌入的字体程序,该程序可能包含它自己到 Unicode 的映射。

否则,您可以从这里开始猜测(或委托给 OCR)。


但是你的假设

It is used for numbers and special characters only.

已经错了。如果您查看示例文档,例如文档第一页上使用的两种字体 F25F26 有一个像这样的 Differences 数组:

0 /.notdef 1 /dotaccent /fi /fl /fraction /hungarumlaut /Lslash /lslash /ogonek /ring 10 /.notdef 11 /breve /minus 13 /.notdef 14 /Zcaron /zcaron /caron /dotlessi /dotlessj /ff /ffi /ffl 22 /.notdef 30 /grave /quotesingle /space /exclam /quotedbl /numbersign /dollar /percent /ampersand /quoteright /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash /zero /one /two /three /four /five /six /seven /eight /nine /colon /semicolon /less /equal /greater /question /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar /braceright /asciitilde 127 /.notdef 130 /quotesinglbase /florin /quotedblbase /ellipsis /dagger /daggerdbl /circumflex /perthousand /Scaron /guilsinglleft /OE 141 /.notdef 147 /quotedblleft /quotedblright /bullet /endash /emdash /tilde /trademark /scaron /guilsinglright /oe 157 /.notdef 159 /Ydieresis 160 /.notdef 161 /exclamdown /cent /sterling /currency /yen /brokenbar /section /dieresis /copyright /ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron /degree /plusminus /twosuperior /threesuperior /acute /mu /paragraph /periodcentered /cedilla /onesuperior /ordmasculine /guillemotright /onequarter /onehalf /threequarters /questiondown /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide /oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis

其中包含正常大写 /A../Z 和小写 /a[=53= 的映射]../z个字符.


顺便说一句,

Type1 font /Differences encoding uses strings in mapping of values for example 1 character is encoded to 'one'.

并不严格正确,'/' 字符是相应映射值的一部分,例如/one,作为 PDF 对象,它们不是 Strings,而是 Names.

这是你文件中的 /Differences 数组(老实说,你应该刚刚发布这个而不是 link 一个狡猾的下载页面):

/Differences [
    24 /breve/caron/circumflex/dotaccent/hungarumlaut/ogonek/ring/tilde
    39 /quotesingle
    96 /grave
    128 /bullet/dagger/daggerdbl/ellipsis...
]

它的工作方式是字体也有与之关联的编码(例如 /MacRoman/WinANSI)。对于 Type 1 字体,字体中内置了编码。然后给定该编码的副本,您将差异应用于它。从数字开始(您的第一个是 24),您将条目 24-31 更改为 /breve/circumflex 等等。

在 Type 1 字体中,有一个名为 /CharStrings 的字典,它是字形名称与将呈现它的 data/code 的关联。例如,如果你得到一个代码为 26 的字符,你可以在你的编码数组中查找它(对于 Type 1 字体,它应该是一个 256 元素的数组)并应用差异,你会得到名称 /circumflex。然后在 CharStrings 字典中查找,提取字形数据并渲染它。编码中不存在的任何字符都应设置为 /.notdef,然后将呈现表示未定义字符(通常为空框)的形状。

现在您的问题可能是,我如何将这些字形名称转换为更有用的东西,比如 Unicode?

如果查看附件 D,您会看到一组 table,它们定义了标准拉丁编码的字符集。您将进行查找 table,将 Adob​​e 标准名称映射到 Unicode。不幸的是,附件 D 中的 table 是不完整的。幸运的是,Adobe 有一个文件为您定义了所有这些 here. There is a link in that file which is now dead, but most likely it was meant to go here