pdf - 从大型 pdf 文件中删除矢量时出现 Ghostscript 问题
问题描述
我正在尝试从一些 pdf 文件中删除向量。Ghostscript (gs) 可与 -dFILTERVECTOR 选项配合使用:
gswin64c -o "test_out.pdf" -sDEVICE=pdfwrite -dFILTERVECTOR "test.pdf"
但是当我在大型 pdf 文件(大于 100MB 且超过 1000 页)上运行此命令时,我得到这样的错误,输出为空白 pdf 文件:
Page 1139
Page 1140
**** Error: can't process embedded font stream,
attempting to load the font using its name.
Output may be incorrect.
Querying operating system for font files...
Substituting font Courier for AVFCLE+CourierNewPSMT.
Can't find (or can't open) font file %rom%Resource/Font/NimbusMonoPS-Regular.
Can't find (or can't open) font file NimbusMonoPS-Regular.
Can't find (or can't open) font file %rom%Resource/Font/NimbusMonoPS-Regular.
Can't find (or can't open) font file NimbusMonoPS-Regular.
Didn't find this font on the system!
Unable to substitute for font.
**** Error reading a content stream. The page may be incomplete.
Output may be incorrect.
Error: /dictfull in --filter--
Operand stack:
--dict:7/15(L)-- --nostringval-- 9 F_2 26049 11 FontObject --dict:10/18(L)-- false --dict:4/12(L)-- --nostringval-- --nostringval--
Execution stack:
%interp_exit .runexec2 --nostringval-- filter --nostringval-- 2 %stopped_push --nostringval-- filter filter false 1 %stopped_push 1992 1 3 %oparray_pop 1991 1 3 %oparray_pop 1979 1 3 %oparray_pop 1980 1 3 %oparray_pop filter filter 1141 1 1277 filter %for_pos_int_continue 1983 1 7 %oparray_pop filter filter filter filter %array_continue filter filter filter filter filter %array_continue 1827 13 10 %oparray_pop
Dictionary stack:
--dict:734/1123(ro)(G)-- --dict:1/20(G)-- --dict:80/200(L)-- --dict:80/200(L)-- --dict:133/256(ro)(G)-- --dict:317/325(ro)(G)-- --dict:33/64(L)-- --dict:6/9(L)-- --dict:6/20(L)-- --dict:9/15(L)--
Current allocation mode is local
GPL Ghostscript 9.27: Unrecoverable error, exit code 1
Unrecoverable error: VMerror in --.systemvmSFD--
Operand stack:
--nostringval-- --nostringval-- 0
GPL Ghostscript 9.27: ERROR: A pdfmark destination page 1277 points beyond the last page 1139.
似乎该问题与第 1140 页上的字体问题有关。但实际上,如果我将文件视为 2 个部分,则每个部分都可以正常工作,没有问题:
第 1 部分:从 1 到 1000 页
gswin64c -o "test_part1.pdf" -sDEVICE=pdfwrite -dFILTERVECTOR -sPageList=-1000 "test.pdf"
第 2 部分:从 1001 到最后一页(大约 1900 年)
gswin64c -o "test_part2.pdf" -sDEVICE=pdfwrite -dFILTERVECTOR -sPageList=1001- "test.pdf"
所以,如果我理解得很好,似乎它与页数或pdf文件的大小有关
生成上述结果的pdf文件是私人的,所以我不能上传它们。但我创建了一个 175MB 的测试 pdf 文件(单击此处下载),它给出了一个类似的问题:
Page 1345
**** Error reading a content stream. The page may be incomplete.
Output may be incorrect.
**** Error: File did not complete the page properly and may be damaged.
Output may be incorrect.
Page 1346
*** ERROR: The font BCDEEE+Calibri is damaged and cannot be used. Switching to a
last-ditch fallback, text may not render correctly, or at all.
**** Error reading a content stream. The page may be incomplete.
Output may be incorrect.
**** Error: File did not complete the page properly and may be damaged.
Output may be incorrect.
Page 1347
**** Error: can't process embedded font stream,
attempting to load the font using its name.
Output may be incorrect.
Substituting font Helvetica for BCDEEE+Calibri.
**** Error reading a content stream. The page may be incomplete.
Output may be incorrect.
**** Error: File did not complete the page properly and may be damaged.
Output may be incorrect.
Page 1348
Error: /VMerror in --filter--
VM status: 4 43671928 45257592
Current allocation mode is local
Last OS error: 2
GPL Ghostscript 9.27: Unrecoverable error, exit code 1
知道我在 Windows 10 上使用的是最新版本的 Ghostscript 9.27 64 位,有什么想法可以解决这个问题吗?
解决方案
我“怀疑”这个问题与 -dFILTERVECTOR 的使用无关。如果您尝试将其从命令行中删除,会发生什么?
您还应该尝试最新的 Ghostscript 代码(尚未发布),它解决了可能存在的相关问题。
此提交解决了此错误报告,该报告与您在此处报告的内容相似。我怀疑您只是耗尽了内存(或者至少是 Ghostscript 可寻址的内存)。
[编辑]
测试了文件后,它在 17452 页之后使用 2GB 耗尽了我的内存(并且不需要 FILTERVECTOR 开关,正如我所料)。
对此没有解决方案。pdfwrite 设备需要在内存中保留大量内容以保持合理的处理性能。
此外,您的文件会在每一页上嵌入每种字体的新副本。即使这些字体中的每一个都具有相同的名称,我们也必须将它们视为唯一的字体。如果不这样做,就意味着我们可能会使用错误的字体。
所以你的文件有 1980 页,每页有 5 种字体,所以有 9,900 种字体。我强烈怀疑将所有这些字体副本保存在内存中的开销是非常消耗的。一个快速的估计(查看解压缩的字体流大小)是单独的字体将占用大约 792MB 的内存。一旦添加了编码、宽度数组等,这很容易成为内存使用的主要来源。
推荐阅读
- asp.net - WCF,Mtom 消息编码,已超出传入消息的最大消息大小配额 (65536)
- python - 使用 PyOpenGL 创建 GL_GEOMETRY_SHADER 时出错
- grpc - Tensorflow serving(docker):如何获取客户端发送的grpc请求日志?
- c - 为什么 strcmp 似乎不适用于 strtok 返回的字符串?
- columnstore - cstore 列式存储中的条件匹配
- mysql - 在 MySql 的其他列中使用新的派生列值
- python - 为什么 list[index] with for loop and pass 正在替换列表中的值
- jquery - 我们可以在 JSP 中不提交表单就进行会话管理吗?
- web - 当我尝试 Web 部署时出现 ERROR_SMO_NEEDED_FOR_SQL_PROVIDER
- angular - “http://192.168.0.137:8080”链接失效