在 Ubuntu 上使用 ImageMagick 将 PDF 转换为 JPEG 时出现字体不匹配的问题?

Ant*_*ong 3 pdf ubuntu imagemagick

我正在使用此命令将 PDF 转换为一组 JPEG 文件:

convert -strip -quality 100 -alpha off \
        -density 165% -scene 1 tmp3GtW_h.pdf /tmp/a1.jpg
Run Code Online (Sandbox Code Playgroud)

这是原始PDF:

在此处输入图片说明

字体更薄,更类似于 Helvetica。

结果如下:

在此处输入图片说明

输出的 JPEG 文件中的字体不同且更粗。

convert命令显示此警告:

   **** Warning:  An error occurred while reading an XREF table.
   **** The file has been damaged.  This may have been caused
   **** by a problem while converting or transfering the file.
   **** Ghostscript will attempt to recover the data.

   **** This file had errors that were repaired or ignored.
   **** The file was produced by: 
   **** >>>> Microsoft? PowerPoint? 2013 <<<<
   **** Please notify the author of the software that produced this
   **** file that it does not conform to Adobe's published PDF
   **** specification.
Run Code Online (Sandbox Code Playgroud)

转换版本为:

$ convert --version
Version: ImageMagick 6.8.9-7 Q16 x86_64 2014-12-30 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2014 ImageMagick Studio LLC
Features: DPC OpenMP
Delegates: jng jpeg png x xml zlib
Run Code Online (Sandbox Code Playgroud)

Ghostscript 版本是:

$ gs --version
9.10
Run Code Online (Sandbox Code Playgroud)

我的问题是

1)我该如何解决这个问题?

2) 如何判断 PDF 文件使用的是什么字体?

3)我如何才能知道什么字体,可以convertgs

编辑:找到了问题 2 的答案。这是pdffonts命令的结果:

name                                 type              encoding         emb sub uni object ID
------------------------------------ ----------------- ---------------- --- --- --- ---------
Intro Black Italic                   Type 1            WinAnsi          no  no  no     145  0
Intro Regular                        Type 1            WinAnsi          no  no  no     147  0
Intro Black Inline Caps              Type 1            WinAnsi          no  no  no     388  0
ABCDEE+Segoe UI                      TrueType          WinAnsi          yes yes no    2233  0
ABCDEE+Segoe UI,Italic               CID TrueType      Identity-H       yes yes yes   2607  0
ABCDEE+Segoe UI,Italic               TrueType          WinAnsi          yes yes no    2612  0
Intro Bold Italic                    Type 1            WinAnsi          no  no  no    3781  0
Run Code Online (Sandbox Code Playgroud)

Kur*_*fle 5

如果您想了解 PDF 文档所用字体的所有相关详细信息,请使用

pdffonts the.pdf
Run Code Online (Sandbox Code Playgroud)

您将在emb标有yes或的列中看到no是否嵌入了字体。

如果字体不是嵌入的,当你看到这样的事情会发生:在PDF渲染器没有找到文件中的字体,所以它使用替代字体:

  1. 如果幸运的话,它会在本地系统上找到一个具有相同或相似名称的页面,并且呈现的页面看起来就像是在寻找 PDF 的制作者(他必须拥有与 PDF 使用的名称相同的字体)在他的系统上)。
  2. 如果你更倒霉,它使用了一种不太合适的替代字体,看起来不太好或“不合适”。
  3. 如果您非常不走运,则替换根本不起作用,页面看起来像垃圾。

但是文档在不同的查看者和不同的系统之间看起来很可能不同。因为每个查看器使用不同的算法来替换丢失的字体。

pdffonts命令的-subst参数。所以

pdffonts -subst the.pdf
Run Code Online (Sandbox Code Playgroud)

会报告,有什么替代字体可能被可能被使用。由于 Poppler 库pdffonts基于使用 FreeType 作为其字体引擎,因此报告的替换字体可能对每个也使用 FreeType 的查看器有效。

例如,Acrobat使用 FreeType,而是使用它自己的字体渲染引擎。因此,在 Adob​​e Reader 中,您可能会获得不同的替换字体。


幽灵脚本:

命令

gs -h
Run Code Online (Sandbox Code Playgroud)

将报告(除其他外)它将用作搜索字体的路径的目录。

您运行的任何 Ghostscript 命令都可以通过

-sFONTPATH=/path/to/dir:/path/to/other/dir
Run Code Online (Sandbox Code Playgroud)

告诉 Ghostscript 在当前命令的持续时间内在其他目录中查找所需的字体。

图像魔法:

这个命令

convert -list font
Run Code Online (Sandbox Code Playgroud)

将报告 ImageMagick 在系统上找到的所有字体。


更新:(更新问题后)

很明显,IntroPDF 中没有嵌入四种不同的字体。这是一种非常不常见的字体,当然不在 PDF 中全球使用的前 200 种字体中(我应该知道,因为我已经从网上收集了 1.000.000 个 PDF,并且目前正在创建一个关于它们各种属性的统计数据库——我不知道)Intro那里没有一个...)。

无论是谁创建了该 PDF,或者无论使用哪种软件,显然都对文档处理一无所知。因为必须打开、查看或处理该文档的每个其他系统、用户或应用程序将看到使用这些字体的那些页面的视图与其创建者所看到的完全不同。

为了将此 PDF 处理为图像,您不应依赖 ImageMagick,而应直接运行 Ghostscript:

  1. 找到四种Intro字体所在的目录。
  2. 使用上述-sFONTPATH=...参数运行 Ghostscript 命令。

让我再次重申:

  1. 您不能强制或建议convert使用任何字体将 PDF 页面渲染为光栅图像。
  2. 这是因为 ImageMagick 永远无法看到 PDF 本身。ImageMagick 收到的是一个光栅图像,它是由 Ghostscript 制作的。
  3. 一旦 Ghostscript 完成它的工作,事故就已经发生了,并且convert无法在后续的光栅数据中插入任何“字体”。
  4. convert可以使用的字体仅用于其自身的绘图、书写、字幕和注释操作。
  5. 所以你必须直接运行 Ghostscript,并提供-sFONTPATH=...参数。
  6. 您必须自己找出Intro字体系列在系统上的哪个位置。我不能为你这样做,对不起。

运行convert -verbose将让您深入了解 ImageMagick 如何准确地使用 Ghostscript 作为其“委托”进行 PDF 输入处理,以及它使用哪些命令行参数......