使用脚本取消设置PDF字体

时间:2014-10-12 16:34:42

标签: python c linux pdf fonts

我正在使用xhtml2pdf库自动创建PDF。几个月前,我有this problem(我没有使用的嵌入式字库,因此印刷公司无法打印PDF),我没有找到解决方案。所以我将PDF下载到我的电脑和Adobe Acrobat Pro我删除了未使用的字体。但是有什么方法可以用脚本来做到这一点吗?无论用什么语言。

我在互联网上发现的唯一想法是:http://www.commandlinefu.com/commands/view/1666/remove-embedded-fonts-from-a-pdf。但我不知道如何使用它。 (我认为这将删除所有字体,而不是未使用的字体)

非常感谢

2 个答案:

答案 0 :(得分:2)

的Java

可以使用iText库等工具完成;在这里看example。但那是在Java中。

(实际上,我已经尝试并构建了一个非常简单的JAR来完成上述操作(即打开一个Stamper并调用未使用的对象删除.TFM说这将删除未使用的字体,所以如果您的麻烦字体真的未使用,它应该做的伎俩。)如果您有一个PDF可以测试它,我可以试一试 - 或者我可以发送给你.java和.jar文件。它们是针对iText 5.4.2构建的,你可以upgrade them at 5.5.3):

java -jar pdftrim.jar input.pdf output.pdf

其他语言(理论上甚至bash脚本)

在Python,C或shell中,没有我知道的能够做到这一点的工具。但是你自己写一个并不是不可能的。

作为第一步,您需要使用pdftk解压缩PDF文件(不是不完美的,它是由iText制成的)。生成的PDF是一个文本文件(除了第一行和多字节注意事项......),可以在闲暇时进行检查。例如,grep将起作用。

要检测字体用法,您需要检查格式

的所有行
/Font NNNNNN 0 R

会告诉您某些文本正在使用字体引用对象NNNNNN。然后由

给出字体引用列表(不是字体)
grep "^\/Font " $PDFFILE  | sort -n -k2.1 | uniq

我们现在在文件中查找类似这样的项目

 NNNNNN 0 obj
 <<
 /F0 XXXXXX 0 R
 /F1 YYYYYY 0 R
 >>

这将为我们提供更多相同字体的不同字体的对象编号。 XXXXXX可能是粗体字体的标题,YYYYYY可能是粗斜体字体的标题,比如说。 XXXXXX和YYYYYY(也许是ZZZZZZ ......)是我们的&#34; true&#34;字体编号。在那些物体偏移处,你会发现类似

的东西
XXXXXX 0 obj
<<
/Encoding /WinAnsiEncoding
/ToUnicode AAAAAA 0 R
/FontDescriptor BBBBBB 0 R
/Widths [...]
/Subtype /TrueType
/Type /Font
/FirstChar 32
/LastChar 121
/BaseFont /Whatever+Font+Name
>>

这将告诉我们这个头引用偏移BBBBBB处的描述符和地址AAAAAA处的字体数据块。字体数据块又可以由子流组成。

因此,使用一些字典查找存储来处理我们具有这些间接级别的事实,并且一个指令如/ Font引用一个数字而相应的/ BaseFont引用另一个,我们现在可以:

  • 找到安装的字体(通过/ BaseFont指令,如果需要,可以关注它)
  • 找到使用的字体(通过/ Font指令)

通过删除未使用的字体对象子树,从BaseFont和FontDescriptor提供的地址开始,重新编号具有更高ID号的对象ID,然后重新计算所有文件,可以删除(尽管不适合胆小的人)偏移(它们位于PDF文件的底部);在实践中,最后通过将对象从旧PDF复制到新PDF并通过ftell()读取新文件中的文件偏移来实现。然后可以重写底部的PDF XREF

xref                     -- start of XREF (NOT NECESSARILY AT A NEWLINE)
0 3315                   -- there are 3315 objects
0000000000 65535 f       -- not an object; flags
0000000015 00000 n       -- first object is 15 bytes past the beginning of the file
0000033003 00000 n
...
0010169101 00000 n
trailer
<<
/Info 3314 0 R -- the info table, usually just before the XREF (needs renumbering)
/Root 3259 0 R -- the root object ID (needs renumbering)
/Size 3315     -- number of objects, again
>>
startxref
10169367       -- file offset of XREF table above.
%%EOF
然后可以使用

pdftk重新压缩生成的PDF文件。

我也尝试使用PDFEdit这样的工具,但收效甚微。

答案 1 :(得分:1)

通常,如果使用了某些字符,则字体会包含在文件中。更安全的方法是将所有字体嵌入pdf文件中。假设output.pdf需要印前质量,可以使用

  gswin64c -dCompatibilityLevel=1.4 -dPDFSETTINGS=/prepress -dCompressFonts=true -dSubsetFonts=true -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=output.pdf -f input.pdf

您需要安装ghostscript(http://www.ghostscript.com/),此处提供的选项说明http://www.ghostscript.com/doc/9.14/Ps2pdf.htm#Options