如何从 PDF 中提取嵌入字体作为有效字体文件?

Posted

技术标签:

【中文标题】如何从 PDF 中提取嵌入字体作为有效字体文件?【英文标题】:How can I extract embedded fonts from a PDF as valid font files? 【发布时间】:2011-03-30 02:50:22 【问题描述】:

我知道pdftk.exe 实用程序可以指示 PDF 使用哪些字体,以及它们是否嵌入。

现在的问题是:鉴于我有嵌入字体的 PDF 文件——我如何提取这些字体以使其可作为常规字体文件重复使用?是否有(最好是免费的)工具可以做到这一点?另外:这可以通过 iText 等编程方式完成吗?

【问题讨论】:

【参考方案1】:

您有多种选择。所有这些方法都适用于 Linux 以及 Windows 或 Mac OS X。但是,请注意,大多数 PDF 在嵌入字体时不包含完整、完整的字体。大多数情况下,它们仅包含文档中使用的字形的子集


使用pdftops

在 *nix 系统上最常用的方法之一包括以下步骤:

    将 PDF 转换为 PostScript,例如使用 XPDF 的 pdftops(在 Windows 上:pdftops.exe 帮助程序。 现在字体将以.pfa (PostScript) 格式嵌入 + 您可以使用文本编辑器提取它们。 您可能需要使用t1utilspfa2pfb.pfa(ASCII)转换为.pfb(二进制)文件。 在 PDF 中永远不会嵌入 .pfm.afm 文件(字体公制文件)(因为 PDF 查看器对这些有内部知识)。没有这些,字体文件很难以视觉上令人愉悦的方式使用。

使用fontforge

另一种方法是使用免费字体编辑器FontForge

    使用打开文件时使用的“打开字体”对话框。 然后在对话框的过滤器部分选择“从 PDF 中提取”。 选择要提取字体的 PDF 文件。 “选择一种字体”对话框打开 -- 在此处选择要打开的字体。

查看 FontForge 手册。您可能需要执行一些不一定简单的特定步骤,以便将提取的字体数据保存为可重复使用的文件。


使用mupdf

接下来,MuPDF。此应用程序附带一个名为 pdfextract(在 Windows 上:pdfextract.exe)的实用程序,它可以从 PDF 中提取字体和图像。 (如果您不了解 MuPDF,它仍然是相对不为人知的新事物:“MuPDF 是用便携式 C 语言编写的免费轻量级 PDF 查看器和工具包。”,由 Artifex 软件开发人员编写,为我们提供 Ghostscript 的同一家公司。)更新: MuPDF 的较新版本已将 'pdfextract' 的旧功能移至命令 'mutool extract'。在此处下载:mupdf.com/downloads)

注意:pdfextract.exe 是一个命令行程序。要使用它,请执行以下操作:

c:\>  pdfextract.exe  c:\path\to\filename.pdf         # (on Windows)
$>    pdfextract  /path/tofilename.pdf                # (on Linux, Unix, Mac OS X)

此命令会将引用的 pdf 文件中的所有可提取文件转储到当前目录中。通常,您会看到各种文件:图像和字体。其中包括 PNG、TTF、CFF、CID 等。如果图像的 PDF 对象编号为 412,则图像名称将类似于 img-0412.png。字体名称将类似于 FGETYK +LinLibertineI-0966.ttf,如果字体的 PDF 对象编号为 966。

CFF(Compact Font Format)文件是一种公认​​的格式,可以通过各种转换器转换为其他格式,以便在不同的操作系统上使用。

再次提醒:请注意,这些字体文件中的大多数可能只有一个子集字符,并且可能不代表完整的字体。

更新:(2013 年 7 月)mupdf 的最新版本在内部对其二进制文件进行了改组和重命名,不止一次,而是多次。主要实用程序曾经是一个类似于“瑞士刀”的二进制文件,名为mubusy(名称灵感来自busybox?),最近更名为mutool。这些支持子命令infocleanextractpostershow。不幸的是,这些工具的官方文档不是最新的(还)。如果您在 Mac 上使用“MacPorts”:则该实用程序已重命名,以避免与使用相同名称的其他实用程序发生名称冲突,您可能需要使用 mupdfextract

要使用 mutool 实现(大致)等效的结果,就像之前的工具 pdfextract 所做的那样,只需运行 mubusy extract ...。*

因此,要提取字体和图像,您可能需要运行以下命令行之一:

c:\>  mutool.exe extract filename.pdf      # (on Windows)
$>    mutool     extract filename.pdf      # (on Linux, Unix, Mac OS X)

下载地址:mupdf.com/downloads


使用gs (Ghostscript)

然后,Ghostscript 也可以直接从 PDF 中提取字体。但是,它需要一个名为 extractFonts.ps 的特殊实用程序的帮助,该程序用 PostScript 语言编写,可从 Ghostscript source code repository 获得。

现在使用它,您需要同时运行此文件extractFonts.ps 和您的 PDF 文件。 Ghostscript 然后将使用 PostScript 程序中的指令从 PDF 中提取字体。在 Windows 上看起来像这样(是的,Ghostscript 理解“正斜杠”/,在 Windows 上也是路径分隔符!):

gswin32c.exe                  ^
  -q -dNODISPLAY              ^
   c:/path/to/extractFonts.ps ^
  -c "(c:/path/to/your/PDFFile.pdf) extractFonts quit"

或在 Linux、Unix 或 Mac OS X 上:

gs                          \
  -q -dNODISPLAY            \
   /path/to/extractFonts.ps \
  -c "(/path/to/your/PDFFile.pdf) extractFonts quit"

几年前我已经测试过 Ghostscript 方法。当时它确实提取 *.ttf (TrueType) 就好了。我不知道是否还会提取其他字体类型,如果是的话,以可重用的方式。我不知道该实用程序是否会阻止提取标记为受保护的字体。


使用pdf-parser.py

最后,Didier Stevens 的pdf-parser.py:这个可能不太容易使用,因为您需要了解一些有关内部 PDF 结构的知识。 pdf-parser.py 是一个 Python 脚本,它也可以做很多其他事情。它还可以从对象中解压和提取任意流,因此它也可以提取嵌入的字体文件。

但您需要知道要寻找什么。让我们用一个例子来看看。我有一个名为 big.pdf 的文件。作为第一步,我使用 -s 参数在 PDF 中搜索关键字 FontFile 的任何出现(pdf-parser.py 不需要区分大小写的搜索):

pdf-parser.py -s fontfile big.pdf

就我而言,对于我的 big1.pdf,我得到了以下结果:

obj 9 0
 Type: /FontDescriptor
 Referencing: 15 0 R
  <<   
    /Ascent 728
    /CapHeight 716
    /Descent -210 
    /Flags 32
    /FontBBox [ -665 -325 2000 1006 ]
    /FontFile2 15 0 R
    /FontName /ArialMT
    /ItalicAngle 0
    /StemV 87
    /Type /FontDescriptor
    /XHeight 519
  >>   

obj 11 0 
 Type: /FontDescriptor
 Referencing: 16 0 R
  <<   
    /Ascent 728
    /CapHeight 716
    /Descent -210 
    /Flags 262176
    /FontBBox [ -628 -376 2000 1018 ]
    /FontFile2 16 0 R
    /FontName /Arial-BoldMT
    /ItalicAngle 0
    /StemV 165
    /Type /FontDescriptor
    /XHeight 519
  >>   

它告诉我在 PDF 中有两个 FontFile2 实例,它们在 PDF 对象中。 15 和没有。 16,分别。对象编号15 为字体 /ArialMT 保存/FontFile2,对象编号。 16 持有/FontFile2 字体/Arial-BoldMT

为了更清楚地展示这一点:

pdf-parser.py -s fontfile big1.pdf | grep -i fontfile
  /FontFile2 15 0 R
  /FontFile2 16 0 R

快速浏览 PDF 规范会发现关键字 /FontFile2“包含 TrueType 字体程序的流”/FontFile 将与包含类型 1 字体程序' 和 /FontFile3 将与一个 ' 流相关,该流包含一个字体程序,其格式由流字典中的子类型条目指定' 因此要么是一个 Type1CCIDFontType0C 子类型。)

具体查看 PDF 对象编号。 15(包含字体/ArialMT),可以使用-o 15参数:

pdf-parser.py -o 15 big1.pdf

 obj 15 0
  Type: 
  Referencing: 
  Contains stream
   <<
     /Length1 778552
     /Length 1581435
     /Filter /ASCIIHexDecode
   >>

这个pdf-parser.py 输出告诉我们这个对象包含一个长度为 1.581.435 字节的流(它不会直接显示),并使用 ASCIIHexEncode 编码(==“压缩”),需要解码(== “解压缩”或“过滤”)在标准 /ASCIIHexDecode 过滤器的帮助下。

要从对象转储任何流,可以使用 -d dumpname 参数调用 pdf-parser.py。让我们开始吧:

pdf-parser.py -o 15 -d dumped-data.ext big1.pdf

我们提取的数据转储将在名为 dumped-data.ext 的文件中。让我们看看它有多大:

ls -l dumped-data.ext
  -rw-r--r--  1 kurtpfeifle  staff  1581435 Apr 11 00:29 dumped-data.ext

哦,看,它是 1.581.435 字节。我们在上一个命令的输出中看到了这个数字。使用文本编辑器打开此文件确认其内容是 ASCII 十六进制编码数据。

使用otfinfo(这是lcdf-typetools package的一部分)之类的字体阅读工具打开文件一开始会让人有些失望:

otfinfo -i dumped-data.ext
  otfinfo: dumped-data.ext: not an OpenType font (bad magic number)

好的,这是因为我们(还)没有让pdf-parser.py 充分利用它的魔力:转储过滤后的解码流。为此,我们必须添加 -f 参数:

pdf-parser.py -o 15 -f -d dumped-data-decoded.ext big1.pdf

这个新文件的大小是多少?

ls -l dumped-data-decoded.ext
  -rw-r--r--  1 kurtpfeifle  staff  778552 Apr 11 00:39 dumped-data-decoded.ext

哦,看:那个确切的数字也已经存储在 PDF 对象号中。 15 字典作为键的值 /Length1...

file 认为是什么?

file dumped-data-decoded.ext
  dumped-data-decoded.ext: TrueType font data

otfinfo 告诉我们什么?

otfinfo -i dumped-data-decoded.ext
  Family:              Arial
  Subfamily:           Regular
  Full name:           Arial
  PostScript name:     ArialMT
  Version:             Version 5.10
  Unique ID:           Monotype:Arial Regular:Version 5.10 (Microsoft)
  Designer:            Monotype Type Drawing Office - Robin Nicholas, Patricia Saunders 1982
  Manufacturer:        The Monotype Corporation
  Trademark:           Arial is a trademark of The Monotype Corporation.
  Copyright:           © 2011 The Monotype Corporation. All Rights Reserved.
  License Description: You may use this font to display and print content as permitted by
                       the license terms for the product in which this font is included.
                       You may only (i) embed this font in content as permitted by the 
                       embedding restrictions included in this font; and (ii) temporarily 
                       download this font to a printer or other output device to help
                       print content.
  Vendor ID:           TMC

所以宾果游戏!,我们有一个赢家:pdf-parser.py 确实为我们提取了一个有效的字体文件。鉴于此文件的大小(778.552 字节),看起来此字体甚至已完全嵌入到 PDF 中...

我们可以将其重命名为 arial-regular.ttf 并照此安装并愉快地使用它。


注意事项:

在任何情况下,您都需要遵循适用于该字体的许可。某些字体许可证不允许免费使用和/或分发。盗版字体就像盗版任何软件或其他受版权保护的材料。

大多数流行的 PDF 无论如何都不会嵌入完整字体,而只会嵌入子集。提取字体的子集仅在非常有限的范围内有用。

请同时阅读以下关于字体提取工作的优点和(更多)缺点:

http://typophile.com/node/34377 — 不再提供,但可以在 Wayback Machine 上看到 https://web.archive.org/web/20110717120241/typophile.com/node/34377

【讨论】:

@kizzx2:请随意对我的任何其他 [PDF] 或 [Ghostscript] 答案投赞成票或反对票 :-) 如果您在 Mac 上并从端口(或者也可能从二进制文件)安装 mupdf,提取也称为 mupdfextract。只要它在路径中,您就可以从终端运行它。 @Orwellophile:感谢您的提示。我借此机会更新了我对mupdf 的一些提示。另见this... 我去看看。所以这不是一个毫无意义的评论:你的过程工作得很棒......(投票赞成)......它提取并命名了字体的 3 个变体,然后我使用 fontforge(也从 macports 中免费)进行合并。不幸的是,我的字体仍然缺少大写字母“X”......几率是多少:p @Chris:是的,这是两个不同的子集(甚至可能有很大一部分重叠)。没有自动合并它们的选项。【参考方案2】:

使用在线服务http://www.extractpdf.com。无需安装任何东西。

【讨论】:

在我的例子中,它只能提取 Type 1 字体而不是 TrueType 我已使用此站点提取字体并将其复制到~/.fonts,并且复制和粘贴工作正常!【参考方案3】:

即使这个问题已有 10 年的历史,它仍然有效,并且随着技术的变化,一个有效的答案也会发生变化。

在搜索当前答案时,没有人注意到 WOFF(Web 开放字体格式)(W3C)(Wikipedia)可用于重新创建单个字符(字形)并在网页中准确显示它们.

使用 IDR Solutions 提供的免费在线网页,将 PDF 转换为 html5 (link),将 PDF 转换为 zip 文件。在生成的 zip 中将是 woff 文件类型的字体目录。如果您不知道,当前的 Internet 浏览器支持 woff 文件。 (reference) 这些可以在在线站点 FontDrop 上查看! (link)。

WOFF 文件可以在WOFFer 与 OTF 或 TTF 相互转换 - WOFF 字体转换器

此外,从 PDF 到 HTML5 的 zip 文件将包含每个 PDF 页面的 HTML 文件,可以在 Internet 浏览器中打开,这是我发现或见过的最好和最准确的 PDF 翻译之一。

虽然我只是在学习如何使用 WOFF 文件,但值得一读。享受吧。

PS,随着我了解有关使用 woff 文件类型的更多信息,我可能会更新更多信息,但由于这是知识共享,如果您有一些有价值的东西可以传递,请随时编辑此答案。

【讨论】:

谢谢!这个解决方案对我有用(就像在创建一个有效的 TTF 时一样),而我尝试过的其他解决方案却没有。是因为 WOFF 能更好地处理不完整的字体吗? @Daan Is it because WOFF handles incomplete fonts better? 我不知道。你的猜测和我的一样好。正如我所指出的,我自己只是在学习 WOFF。 @Daan 也许您应该将Is it because WOFF handles incomplete fonts better? 作为一个新的 SO 问题发布,其他有更多知识的人会看到并希望提供一个有意义的答案。 我可能会这样做。谢谢。 仅供参考Adobe will disable support for authoring with Type 1 fonts in January 2023【参考方案4】:

最终找到the FontForge Windows installer package,通过安装的程序打开PDF。辛苦了,真开心。

【讨论】:

最新页面可以在这里找到:fontforgebuilds.sourceforge.net【参考方案5】:

http://www.verypdf.com/app/pdf-font-extractor/pdf-font-extracting-tool.html IMO 提取字体的最简单方法 (Windows)。

【讨论】:

【参考方案6】:

目前可用于提取 pdf 字体的最佳在线工具之一是 http://www.pdfconvertonline.com/extract-pdf-fonts-online.html

【讨论】:

【参考方案7】:

PDF2SVG 来自PDFTron 的 6.0 版做得很合理。它默认生成 OpenType (.otf) 字体。使用--preserve_fontnames 保留“从源文件获得的字体/字体系列命名方案”。

PDF2SVG 是一种商业产品,但您可以下载免费的演示可执行文件(其中包括 SVG 输出上的水印,但不限制使用)。可能还有其他 PDFTron 产品也可以提取字体,但我自己最近才发现 PDF2SVG。

【讨论】:

不幸的是,如果您有重叠的部分字体,--preserve_fontnames 将不起作用 - 它似乎不包括前缀,例如 MSCIYG+Ge'ez-1 中的 MSCIYG,因此会覆盖之前的部分字体。跨度> 【参考方案8】:

这是 @Kurt Pfeifle's answer 的 font-forge 部分的后续内容,专门针对 Red Hat(可能还有其他 Linux 发行版)。

    打开 PDF 并选择所需字体后,您需要选择“文件 -> 生成字体...”选项。 如果文件中存在错误,您可以选择忽略它们或保存文件并进行编辑。如果您点击“修复”足够多次,大部分错误都可以自动修复。 点击“元素 -> 字体信息...”,“字体名”、“姓氏”和“人名”都设置为您喜欢的值。如果没有,请修改它们并将文件保存在某处。这些名称将决定您的字体在系统上的显示方式。 选择您的文件名并点击“保存...”

获得 TTF 文件后,您可以通过以下方式将其安装到系统上

    将其复制到文件夹 /usr/share/fonts(以 root 身份) 运行 fc-cache -f /usr/share/fonts/(以 root 身份)

【讨论】:

以上是关于如何从 PDF 中提取嵌入字体作为有效字体文件?的主要内容,如果未能解决你的问题,请参考以下文章

为啥WORD转换PDF时字体会丢失?

如何修复 PDF 文件并嵌入丢失的字体

如何在现有 PDF 中嵌入字体?

如何在 DomPDF 中正确嵌入 Google 字体?打印时中断

如何替换或修改嵌入在 PDF 文件中的字体或字形?

Drawboard PDF 输入文字可以更改字体吗?