PDF 文本提取问题 - 字体/大小写不一致

标签 pdf character-encoding adobe-indesign text-extraction truetype

我正在尝试从 pdf 书中提取文本并继续运行一个问题,即复制的文本部分在粘贴到文本文档时无法保留正确的大写属性。我有权复制这本书,也有使用所有必要字体的许可。起初我以为问题是由未嵌入的字体引起的,但我检查了一下,所有字体似乎都是嵌入的子集。在 pdf 中,使用了 100 多种具有以下属性之一的字体:

TrueType 编码:Ansi TrueType (CID) 编码:Identity-H 类型 1 (CID) 编码:Identity-H 类型 1 编码:自定义

书中的语言包括英语、德语、西类牙语和意大利语。在德国,大写是绝对重要的。与小写字母相比,它更容易丢失大写字母的属性。

错误示例为:WELD -> weld

我真的不知道该怎么办。我已经要求这本书的所有者嵌入他作为子集完成的字体,但问题仍然存在。我曾尝试将 pdf 文件保存为后记,然后通过蒸馏器运行它,这正确地解决了大部分问题,但在某些情况下导致文本被不同的字符或数字替换为头骨。我知道 CID 字体可能是导致此问题的原因,但我遇到过非 CID 字体产生相同结果的实例。

是什么导致了这个问题?字体是子集还是完全嵌入?有没有更好的方法将 native 文件 (InDesign) 保存为 pdf,以便更好地提取字体?它是否与非 unicode 字体有关?如果是,是否有不需要所有者选择不同字体的替代方案?

非常感谢任何和所有帮助。

最佳答案

这确实很有趣。 OP 提供的示例 PDF 确实明显包含大写字符,其中一些仅在大写行中,一些在混合行中,Adobe Reader 将其提取为小写字符。

你想知道

What could be causing this issue?

作为一个例子,让我们看看 Pelle Più bella

在页面内容中,该短语实际上看起来像大写字母的视觉表示:

/T1_0 1 Tf
-0.025 Tc 12 0 0 12 379.5354 554.8809 Tm
(PELLE PI\331 BELLA)Tj

查看使用的字体 T1_0(DIN-Bold 子集),我们看到它声称使用 WinAnsiEncoding,这也表明对这些字符代码的解释页面流为大写字母

但是字体还有一个ToUnicode映射,这个映射映射

<41> <0061> — 'A' → a
<42> <0062> — 'B' → b
<43> <0043> — 'C' → C
<44> <0044> — 'D' → D
<45> <0065> — 'E' → e
<49> <0069> — 'I' → i
<4C> <006C> — 'L' → l
<4D> <004D> — 'M' → M
<4E> <006E> — 'N' → n
<50> <0050> — 'P' → P
<52> <0072> — 'R' → r
<53> <0053> — 'S' → S
<54> <0074> — 'T' → t
<D9> <00F9> — 'Ù' → ù

(我只提取了WinAnsiEncoding中代表大写字母的字符编码的映射。)

Is there a better way to save the native file (InDesign) to a pdf that will allow for better font extraction?

抱歉,我不太喜欢 InDesign。但该软件来自 Adob​​e,如果这是 InDesign 中的错误或它导出为 PDF,我会感到惊讶。会不会是 InDesign 文件中的某些信息将 PELLE PIÙ BELLA 标记为 Pelle Più bella,InDesign 然后在 PDF 导出中将其转换为此 ToUnicode 映射?

Does it have to do with non-unicode fonts and if so is there an alternative that does not require the owner to select different fonts?

如果您的示例文档有三种字体,它们都带有 Encoding 条目 WinAnsiEncoding, 它们都是嵌入的子集,但只有两个具有这样的有趣的 ToUnicode 映射,DIN-Medium 和 DIN-Bold,而 Helvetica 没有 ToUnicode 映射。所以它在某种程度上与字体有关。具体如何我不能说。

解决方法,如果您的示例文档是删除字体字典中的 ToUnicode 映射。

例如,使用 Java 和 iText 库,您可以这样做:

PdfReader reader = new PdfReader(INPUT);
for (int i = 1; i <= reader.getXrefSize(); i++)
{
    PdfObject obj = reader.getPdfObject(i);
    if (obj != null && obj.isDictionary())
    {
        PdfDictionary dic = (PdfDictionary) obj;
        if (PdfName.FONT.equals(dic.getAsName(PdfName.TYPE)))
        {
            dic.remove(PdfName.TOUNICODE);
        }
    }
}
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(OUTPUT));
stamper.close();
reader.close();

经过此操作后,Adobe Reader 文本提取结果为

PELLE PIÙ BELLA

这显然只适用于示例文档中的情况。

如果在您的其他文档中混合了多种字体,其中一些需要它们各自的 ToUnicode 映射来提取文本,而另一些则类似于上面的麻烦字体,您可能需要添加一些额外的条件Java 代码仅删除错误字体定义中的 map 。

关于PDF 文本提取问题 - 字体/大小写不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17737776/

相关文章:

java - 使用 ICE PDF 查看器 pdf 在内部框架内不会更改

javascript - 将 javascript 插入现有 pdf 文件的方法有哪些(通过 API)

c - 打印输入字符时,getchar/putchar 返回带问号的框

indexing - 解析 InDesign (.indd) 文件以获取搜索索引

macos - 在 mac osx 上使用 latex (特别是 pdflatex)生成时,pdf 文档中的字体搞砸了

java - 如何限制单行字符数?

Jquery 将文本附加到 html 字符集 utf8 时不起作用

java - 在 HTML 页面的什么地方添加 UTF-8 扩展名?

javascript - 从 nodejs 运行 InDesign ExtendedScript

adobe-indesign - 将 indesign 输出转换为 html5