如果要优化PDF文件并减小文件大小,Ghostscript是最佳 Select 吗?

我需要存储大量PDF文件,因此我需要尽可能优化和减少文件大小

有人有过Ghostscript和/或其他方面的经验吗?

command line

exec('gs -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dCompatibilityLevel=1.4
-dPDFSETTINGS=/screen -sOutputFile='.$file_new.' '.$file);

推荐答案

如果你正在寻找一个免费的(比如libre)软件,Ghostscript肯定是你最好的 Select .然而,它并不总是易于使用——它的一些(非常强大的)处理选项不容易找到.

看看这个答案,它解释了如何对图像分辨率下采样执行比通用-dPDFSETTINGS=/screen更详细的控制(它定义了一些总体默认值,您可能希望覆盖这些默认值):

基本上,它告诉您如何使Ghostscript将所有图像的采样降到72dpi的分辨率(这个值是-dPDFSETTINGS=/screen使用的——您可能希望降到更低):

-dDownsampleColorImages=true \
-dDownsampleGrayImages=true \
-dDownsampleMonoImages=true \
-dColorImageResolution=72 \
-dGrayImageResolution=72 \
-dMonoImageResolution=72 \

如果您想try Ghostscript是否也能够"取消嵌入"所使用的字体(有时有效,有时无效——取决于嵌入字体的复杂程度,还有on the font type used),您可以try 将以下内容添加到gs命令中:

gs \
  -o output.pdf \
   [...other options...] \
  -dEmbedAllFonts=false \
  -dSubsetFonts=true \
  -dConvertCMYKImagesToRGB=true \
  -dCompressFonts=true \
  -c ".setpdfwrite <</AlwaysEmbed [ ]>> setdistillerparams" \
  -c ".setpdfwrite <</NeverEmbed [/Courier /Courier-Bold /Courier-Oblique /Courier-BoldOblique /Helvetica /Helvetica-Bold /Helvetica-Oblique /Helvetica-BoldOblique /Times-Roman /Times-Bold /Times-Italic /Times-BoldItalic /Symbol /ZapfDingbats /Arial]>> setdistillerparams" \
  -f input.pdf

Note:请注意,降低采样图像分辨率肯定会降低质量(不可逆转),而不嵌入字体将使显示和打印PDF变得困难或不可能,除非机器上安装了相同的字体....


使现代化

我在最初的回答中忽略了一个选项,那就是添加

-dDetectDuplicateImages=true

转到命令行.此参数会导致Ghostscript多次try 检测PDF中嵌入的任何图像.如果使用图像作为徽标或页面背景,并且PDF生成软件未针对这种情况进行优化,则可能会发生这种情况.OpenOffice/LibreOffice的旧版本曾经是这样(我测试了LibreOffice的最新版本v4.3.5.2,它不再做这种愚蠢的事情).

如果在pdftk的帮助下连接PDF文件,也会发生这种情况.为了向您展示效果,以及如何发现它,让我们看一个示例PDF文件:

pdfinfo p1.pdf

 Producer:       libtiff / tiff2pdf - 20120922
 CreationDate:   Tue Jan  6 19:36:34 2015
 ModDate:        Tue Jan  6 19:36:34 2015
 Tagged:         no
 UserProperties: no
 Suspects:       no
 Form:           none
 JavaScript:     no
 Pages:          1
 Encrypted:      no
 Page size:      595 x 842 pts (A4)
 Page rot:       0
 File size:      20983 bytes
 Optimized:      no
 PDF version:    1.1

Poppler的pdfimages实用程序的最新版本增加了对-list参数的支持,该参数可以列出PDF文件中包含的所有图像:

pdfimages -list p1.pdf

 page num  type width height color comp bpc  enc interp objectID x-ppi y-ppi size ratio
 --------------------------------------------------------------------------------------
    1   0 image    423   600   rgb    3   8 jpeg     no     7  0    52    52 19.2K 2.6%

此示例PDF是一个单页文档,包含一个图像,该图像使用JPEG压缩,宽度为423像素,高度为600像素,在页面上以52 PPI的分辨率呈现.

如果我们在pdftk的帮助下连接此文件的3个副本,就像这样:

pdftk p1.pdf p1.pdf p1.pdf cat output p3.pdf

然后,结果通过pdfimages -list显示这些图像属性:

pdfimages -list p3.pdf

 page num  type width height color comp bpc  enc interp objectID x-ppi y-ppi size ratio
 --------------------------------------------------------------------------------------
    1   0 image   423    600   rgb    3   8 jpeg     no     4  0    52    52 19.2K 2.6%
    2   1 image   423    600   rgb    3   8 jpeg     no     8  0    52    52 19.2K 2.6%
    3   2 image   423    600   rgb    3   8 jpeg     no    12  0    52    52 19.2K 2.6%

这表明现在有3个相同的PDF对象(ID为4、8和12)嵌入到p3.pdf中.p3.pdf由3页组成:

pdfinfo p3.pdf | grep Pages:

 Pages:          3

通过使用引用替换重复图像来优化PDF

现在我们可以在Ghostscript的帮助下应用上述优化

 gs -o p3-optim.pdf -sDEVICE=pdfwrite -dDetectDuplicateImages=true p3.pdf

判断:

 pdfimages -list p3-optim.pdf

 page num  type width height color comp bpc  enc interp objectID x-ppi y-ppi size ratio
 --------------------------------------------------------------------------------------
    1   0 image   423    600   rgb    3   8 jpeg     no    10  0    52    52 19.2K 2.6%
    2   1 image   423    600   rgb    3   8 jpeg     no    10  0    52    52 19.2K 2.6%
    3   2 image   423    600   rgb    3   8 jpeg     no    10  0    52    52 19.2K 2.6%

每页仍列出一张图像,但PDF对象ID现在始终不变:10.

 ls -ltrh p1.pdf p3.pdf p3-optim.pdf

   -rw-r--r--@ 1 kp  staff    20K Jan  6 19:36 p1.pdf
   -rw-r--r--  1 kp  staff    60K Jan  6 19:37 p3.pdf
   -rw-r--r--  1 kp  staff    16K Jan  6 19:40 p3-optim.pdf

如您所见,使用pdftk制作的"哑"凹面将原始文件大小增加到原始文件大小的三倍.Ghostscript的优化将其降低了相当多.

Ghostscript的最新版本甚至可以默认应用-dDetectDuplicateImages.(AFAIR, v9.02, which introduced it for the first time, didn't use it by default.)

Linux相关问答推荐

用户作用域在Linux内核密钥环(Golang)中是什么意思?

如何判断程序是在终端上运行还是在后台运行?

Docker运行错误:exec/app/backend/server:没有这样的文件或目录

Bash:将带有新行的字符串转换为带有逗号、内联的唯一值的字符串

使用文件名重新打开 linux 管道(仅从一侧)

在 bash 中获取目录或文件的基本名称的快速且正确的方法

如何使用 Bash 将随机数据块写入文件

`G++ 4.9.4` 中关于 WEXITSTATUS 的奇怪行为

为什么 perf 不报告缓存未命中?

使用 awk 或 sed 删除特定字符

为什么这个命令会杀死我的 shell?

qstat 和长作业(job)名称

如何在没有空格的情况下打印 awk?

如何对 /dev/random 或 /dev/urandom 进行 base64 编码?

根据文件名模式和文件内容列出文件名?

区分 Windows 和类 Unix 系统的 Makefile

解压tar tar.bz2 文件报错

在没有 python 命令的情况下在终端中运行 python 脚本

Docker:您是否try 连接到没有 TLS 的启用 TLS 的守护进程?

如何将初始输入通过管道传输到随后将是交互式的进程中?