Проблема для синтаксического анализа Type0 CMap
В настоящее время я работаю над сканированием PDF в iOS с использованием PDFKitten. Я пытаюсь извлечь текст для поиска в PDF с шрифтом Type0. Я не могу извлечь текст из PDF. Некоторые записи в ToUnicode отсутствуют, а некоторые неверно истолкованы. Может ли быть проблема с разбором CMap? Если у меня нет полного CMap, как мне его получить? Могу ли я взять внешние записи для этих пропущенных записей ToUnicode?
Спасибо
2 ответа
Спецификация PDF предлагает советы о том, как извлечь текстовое содержимое в разделе 9.10.2 Отображение кодов символов в значения Unicode:
Если словарь шрифтов содержит ToUnicode CMap (см. 9.10.3, "ToUnicode CMaps"), используйте этот CMap для преобразования кода символа в Unicode.
Если шрифт является простым шрифтом, который использует одну из предопределенных кодировок MacRomanEncoding, MacExpertEncoding или WinAnsiEncoding или имеет кодировку, в которой в массиве различий содержатся только имена символов, взятые из стандартного латинского набора символов Adobe, и набор именованных символов в символе шрифт (см. Приложение D):
a) Сопоставьте код символа с именем символа в соответствии с таблицей D.1 и массивом различий шрифта.
б) Найдите имя персонажа в списке глиф Adobe (см. Библиографию), чтобы получить соответствующее значение Unicode.
Если шрифт является составным шрифтом, который использует один из предопределенных CMaps, перечисленных в Таблице 118 (кроме Identity-H и Identity-V), или чей потомок CIDFont использует Adobe-GB1, Adobe-CNS1, Adobe-Japan1 или Adobe-Korea1 коллекция персонажей:
а) Сопоставить код символа с идентификатором символа (CID) в соответствии с CMap шрифта.
б) Получить реестр и порядок набора символов, используемых шрифтом CMap (например, Adobe и Japan1) из его словаря CIDSystemInfo.
c) Создайте второе имя CMap, объединив реестр и упорядочив, полученные на шаге (b) в формате Registry-Ordering-UCS2 (например, Adobe-Japan1-UCS2).
d) Получите CMap с именем, созданным на шаге (c) (доступно на веб-сайте ASN; см. библиографию).
e) Сопоставьте CID, полученный на этапе (a), с CMap, полученным на этапе (d), с получением значения Unicode.
Кроме того, как указано в разделе 9.10.1,
- Запись ActualText для элемента структуры или последовательности отмеченного содержимого (см. 14.9.4, "Заменяющий текст") может использоваться для непосредственного указания текстового содержимого.
Согласно спецификации, если этим методам не удается получить значение Unicode, невозможно определить, что представляет собой символьный код. Это не совсем правда; например, программы встроенных шрифтов могут содержать свои собственные отображения в Unicode; но такие дополнительные источники информации выходят за рамки фактического формата PDF.
РЕДАКТИРОВАТЬ
ОП предоставил по почте файл iPhoneConfigurationProfileRef-2013-GM.pdf и указал
У меня проблема с каждым глифом.
Проблема заключается в том, что диапазоны, представленные в PDF, не являются полными и отличаются от файла adobe-identity-cmap.
Если я использую только CMap, встроенный в PDF, я не получаю сопоставления для каждого символа, и если я использую Adobe One, все сопоставления неверны.
Поскольку он не получил отображение ни одного глифа, давайте посмотрим на титульную страницу в качестве примера.
Поток содержимого содержит следующие операции, относящиеся к извлечению текста:
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
Поэтому нам нужно взглянуть только на шрифт G1 на странице 1. К счастью, у шрифта есть карта 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>
Это очень хорошо соответствует внешнему виду страницы:
Кого это может касаться, если некоторые записи отсутствуют в CMap и шрифт не относится к одной из предопределенных кодировок / CMap (s), то Adobe Reader / Acrobat будет вести себя следующим образом, как я эмпирически заметил:
- Если размер кодирования составляет 1 байт, он будет напрямую интерпретировать отсутствующий код как кодовую точку Unicode (в основном, приведение идентичности);
- Если размер кодирования составляет 2 байта, он просто декодирует код как недопустимый символ.
Я не тестировал другие комбинации, такие как переменный размер кодового пространства. Это помогло мне правильно выполнить извлечение текста в PDF с помощью шрифта кодировки 1 байт, который перечислял только алфавитные символы в
/ToUnicode
CMap, без некоторых знаков препинания, которые были закодированы обычным кодом ASCII.