使用pdfTk创建的pdf中如何删除多个嵌入字体

9
有没有办法从pdf文件中删除多次嵌入的字体?
这是我的情况:
1)一个程序生成几个单页pdf报告(查询数据库,在excel模板上放置信息并导出格式化信息为pdf)
2)pdftk将单页pdf合并成一个文件。
一切都很好,但生成的pdf文件大小非常大:实际上,我注意到字体被多次嵌入(每一页都从相同的excel模板生成,字体嵌入单个pdf文件,pdftk只是将pdf粘合在一起)。有没有办法只保留每个嵌入字体的一个副本?
我尝试在从Excel->PDF导出时仅在第一页嵌入字体:文件大小显着减小,但似乎其他页面无法访问嵌入的字体。
谢谢, Alessandro

你能提供 2-3 个单页 PDF 的样例吗?(如果原始数据过于敏感,可以使用虚拟数据) - Kurt Pfeifle
你能否为你的一些输入文件添加 pdffonts input.pdf 的输出结果,以及为 pdftk 从相同的输入集创建的文件添加 pdffonts output.pdf 的输出结果? - Kurt Pfeifle
抱歉,我没有看到你在这里的评论。我在下面写了如何使用虚拟单词文件重现我的问题。有可能以某种方式上传文件吗?我会尽快下载 pdffonts,因为它没有安装在我的电脑上,然后告诉你。 - AleV
我将我的示例文件上传到https://www.dropbox.com/sh/l3nmw23ycfs2s8e/W5bdqjXOik。 - AleV
2个回答

7
您可以尝试使用Ghostscript(但要使用最新版本,如9.05)“修复”您的pdftk合并PDF。在许多情况下,Ghostscript将能够将许多子集字体合并为较少数量的字体。
命令如下:
gswin32c.exe ^
    -o output.pdf ^
    -sDEVICE=pdfwrite ^
    -dPDFSETTINGS=/prepress ^
     input.pdf

请检查

pdffonts.exe  output.pdf
pdffonts.exe  input.pdf 

每个文件中各种字体子集的实例数(pdffonts.exe可在此处作为一小部分命令行工具包中获得)。
但是不要抱怨这个过程的“缓慢”——Ghostscript需要完全解释所有PDF输入文件以完成其任务,而pdftk文件连接则是一个更简单的过程...
更新: 您可以使用Ghostscript代替pdftk来合并输入的PDF文件。这可能可以避免您在后期使用Ghostscript对您的pdftk合并文件进行“修复”时所看到的问题。请注意,这会比“愚蠢的” pdftk 合并慢得多。但是,结果可能更加令人满意,特别是涉及字体处理和文件大小方面。
下面是一个可能的命令:
gswin32c.exe ^
    -o output.pdf ^
    -sDEVICE=pdfwrite ^
    -dPDFSETTINGS=/prepress ^
     input.pdf

您可以在Ghostscript CLI中添加更多选项,以更精细地控制合并和优化过程。最终,您将不得不在以下极端之间做出决定:
- '快速'的pdftk生成大型输出文件,与 - '缓慢'的gswin32c.exe(Ghostscript)生成瘦身的输出文件。
如果您能为一些合并过程的两种方法发布一些结果(执行时间和生成的文件大小),我会很感兴趣...
更新2:抱歉,我的先前版本中有一个错别字。不是-sPDFSETTINGS=...,而是必须是-dPDFSETTINGS=...(在s的位置上使用d)。
更新3:由于您的源文件是从模板创建的Excel表格(通常不使用许多不同的字体),因此您可以尝试使用一个技巧,以确保Ghostscript具有稍后要合并的所有PDF中使用的字体的所有所需字形:
- 对于每个字体和字形(标准、斜体、粗体、粗斜体),在您的模板工作表的左上角添加一个表单元格,该单元格位于您的打印区域的左上角。 - 使用ASCII字母表中的所有可打印字符和标点符号填写此表单元格:0123456789ABCD...XYZabc...xyz:-_;°%&$§")({}[]等。 - 将单元格(和字体大小)缩小到您需要的任何大小,以便不会干扰整体布局。使用白色来格式化单元格中的字符(这样它们在最终PDF中看起来是不可见的)。
这种方法有望确保每个PDF都使用相同的字形子集,从而避免您在使用Ghostscript合并文件时观察到的问题。(请注意,如果您使用Arial和Arial-Italic等,则必须创建2个这样的单元格:一个用标准Arial字体格式化,另一个用斜体格式化。

感谢pipitas:您的解决方案似乎非常有效,但是:1)在生成过程中会收到多个警告(警告:将“0000000000 XXXXX n”视为自由条目。)2)最后我得到了这个注释:此文件存在已修复或忽略的错误。 ****该文件由以下程序生成: **** >>>> itext-paulo(lowagie.com)[JDK1.1] - build 132 <<<< 3)当我在Acrobat Reader中打开文件时,我会收到“无法提取嵌入字体'ZJRYHZ + Calibri + Bold'。某些字符可能无法正确显示或打印”,实际上,一些字符没有显示。 - AleV
再次感谢pipitas:我尝试使用gs而不是pdftk来合并pdf,但结果是一样的:文件很小(就像excel->pdftk->gs过程中一样),但有些字符丢失了(更好的说法是它们存在,但没有呈现出来)。我使用了以下命令:gswin64 -sPDFSETTINGS=prepress -dBATCH -sDEVICE=pdfwrite -sOutputFile=output.pdf pdffile1.pdf pdffile2.pdf。我还尝试在第一页添加缺失的字符,然后它们会在整个文档中出现。我认为问题与字体被子集化(而不是嵌入)有关,正如KenS所解释的那样。 - AleV
@AleV: -sPDFSET... 是错误的语法,不会产生想要的效果。它必须-dPDFSET...。同时,在= /prepress之前必须有斜杠。 - Kurt Pfeifle
@AleV:你的Dropbox上的.bat文件仍需更正为使用-dPDFSETTINGS=/prepress。同时,使用gswin64c(c代表命令行),而不是gswin64(可能会弹出GS图形界面)。我建议完整的命令为:gswin64c.exe -dPDFSETTINGS=/prepress -sDEVICE=pdfwrite -o output_gs.pdf C:/TMP/testgs/a.pdf C:/TMP/testgs/b.pdf。(Ghostscript可以在Windows路径中接受单斜杠,并且-o(输出)更短,省去了添加-dBATCH -dNOPAUSE的步骤。) - Kurt Pfeifle
你的技巧很有效,谢谢。我仍然想知道在从Excel导出PDF时是否有一种嵌入(而不是子集化)字体的方法。我猜这会解决问题。无论如何,非常感谢您的支持,Ale。 - AleV
显示剩余3条评论

3

在创建PDF文件时,通常会对字体进行子集处理,以便它们只包含所需的字形。此外,编码也会被更改,使第一个使用的字形被分配字符代码1,第二个是2,依此类推。

因此,第一个PDF文件可能包含一个字体,其中0x01 = A,0x02 =空格,0x03 = t,0x04 = e和0x05 = s。第二个文件可能包含一个字体,其中0x01 = T,0x02 =e,0x03 = s,0x04 = t

为了避免混淆,在文档中添加了字体名称的前缀。Acrobat在显示字体嵌入时会去掉这个前缀,因此看起来好像有多个相同字体的实例。但是实际上它们是不同的字体,不能轻易地合并。

假设情况确实如此(我需要查看您的文件才能确定),则“可能”可以避免这种情况。如果您将PDF生成软件设置为不对字体进行子集处理,则pdftk可能能够合并文档,而无需多次包含相同的字体。我没有明确测试过,但是这可能有效。你的另一个选择是修改工作流程,使报告一开始就生成为多页文档。


谢谢KenS。对于我的情况,选项2不切实际:我尝试了1)将Excel单个报告合并为一个具有多个工作表的Excel文件-->由于存在数据透视表、表格、命名范围和链接图表,它成为了一场噩梦,它们的名称和引用会产生冲突或丢失。2)将范围粘贴到Word文档中-->它可以工作,但复制粘贴操作不令人满意。选项1似乎很有前途,但我不知道如何在创建PDF时嵌入(而不是子集化)字体:我在Excel另存为PDF选项中没有找到此选项(我没有Distiller)。 - AleV

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接