合并 PDF 的 Ghostscript 压缩结果

Posted

技术标签:

【中文标题】合并 PDF 的 Ghostscript 压缩结果【英文标题】:Ghostscript to merge PDFs compresses the result 【发布时间】:2011-12-30 19:26:26 【问题描述】:

我发现这个巧妙的命令可以使用 Ghostscript 将多个 PDF 合并为一个:

gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile=out.pdf in1.pdf in2.pdf

生成的大小小于 2 个 PDF 的总大小。

以单个文件作为输入运行命令仍会导致输出文件更小。

Ghostscript 上是否有一个选项,可以在合并时复制页面而不进行任何压缩?

如果不是,是不是因为 Ghostscript 的压缩效果好到完全没有质量损失?

【问题讨论】:

【参考方案1】:

我在 ios 终端上成功使用了以下代码递归压缩多个 PDF。我发布它是因为我无法通过简单的复制和粘贴找到适合我的内容。

find . -name '*.pdf' | while read pdf; do gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook -dNOPAUSE -dQUIET -dBATCH -sOutputFile="$pdf_new.pdf" "$pdf"; done

请注意,您可能需要不同的输出质量,因此您可以更改 -dPDFSETTINGS 参数,如下所示:

-dPDFSETTINGS=/screen:质量较低,尺寸较小。-dPDFSETTINGS=/ebook:质量更好,但 pdf 文件稍大。-dPDFSETTINGS=/prepress:输出类似于 Acrobat Distiller“印前优化”设置。-dPDFSETTINGS=/printer:选择类似于 Acrobat Distiller“打印优化”设置的输出。-dPDFSETTINGS=/default:选择旨在用于各种用途的输出,可能以牺牲更大的输出文件为代价。

【讨论】:

【参考方案2】:

您观察到的一些尺寸优化可能来自 Ghostscript 对未使用对象的清理、最近获得的字体优化改进(您使用的是最新版本的 GS 吗?!?)以及可能的图像重新采样/下采样这可能已经发生了。

Ghostscript,如果用于PDF -> PDF 转换,基本上是这样操作的:

    读入输入文件及其所有对象,并将它们转换为图形页面表示的内部格式。 对内部格式的页面内容进行在命令行上要求的操作。 编写一个全新的 PDF。

这意味着对于大多数 PDF -> PDF 操作,您将对 PDF 对象有不同的排序和编号,甚至对象的内部代码也可能已更改(即使您的眼睛没有发现输入和输出 PDF 之间的任何差异)。

默认情况下,Ghostscript 还会压缩原始文件中未压缩的任何对象流(但这是无损压缩)。

现在对于您非常简单的命令行不包含任何操作愿望,Ghostscript 假设您想使用-dPDFSETTINGS=/default,隐式设置此参数并进行相应操作。

现在什么/default PDFSETTINGS?!您有两种选择:

    阅读手册。大号table in middle of this section 给出了概述。您可以看到-dPDFSETTINGS=/default 本身只是它所代表的其他几十个更具体设置的简写。给定文档的链接是针对开发代码的当前 HEAD当然您实际使用的版本可能不同

    查询(您自己的)Ghostscript 以了解此设置的详细含义。 我对问题 'Querying Ghostscript for the default options/settings of an output device...' 和问题 'What are PostScript dictionaries, and how can they be accessed (via Ghostscript)?' 的回答对此进行了详细说明。简而言之,要查询 Ghostscript 以了解其 /default PDFSETTINGS 的详细信息,请运行以下命令:

     gs \
       -q \
       -dNODISPLAY \
       -c ".distillersettings /default get exch ==only ( ) print === forall quit"
    

    你应该得到一个非常相似的结果:

      /Optimize false
      /DoThumbnails false
      /PreserveEPSInfo true
      /ColorConversionStrategy /LeaveColorUnchanged
      /DownsampleMonoImages false
      /EmbedAllFonts true
      /CannotEmbedFontPolicy /Warning
      /PreserveOPIComments true
      /GrayACSImageDict << /HSamples [2 1 1 2] /VSamples [2 1 1 2] /QFactor 0.9 /Blend 1 >>
      /DownsampleColorImages false
      /PreserveOverprintSettings true
      /CreateJobTicket false
      /AutoRotatePages /PageByPage
      /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]
      /ColorACSImageDict << /HSamples [2 1 1 2] /VSamples [2 1 1 2] /QFactor 0.9 /Blend 1 >>
      /DownsampleGrayImages false
      /UCRandBGInfo /Preserve
    

    其中唯一突出的一点是:您可能希望将 /AutoRotagePages/PageByPage 更改为 /None。在命令行上,你可以把它写成-dAutoRotatePages=/None

    为您提供一个完整的参数列表,这些参数将专门告诉 Ghostscript 通过添加这些参数来尽可能多地使用 passthrough 模式到输入 PDF:

      -dAntiAliasColorImage=false \
      -dAntiAliasGrayImage=false \
      -dAntiAliasMonoImage=false \
      -dAutoFilterColorImages=false \
      -dAutoFilterGrayImages=false \
      -dDownsampleColorImages=false \
      -dDownsampleGrayImages=false \
      -dDownsampleMonoImages=false \
      -dColorConversionStrategy=/LeaveColorUnchanged \
      -dConvertCMYKImagesToRGB=false \
      -dConvertImagesToIndexed=false \
      -dUCRandBGInfo=/Preserve \
      -dPreserveHalftoneInfo=true \
      -dPreserveOPIComments=true \
      -dPreserveOverprintSettings=true \
    

所以你可以试试这个命令:

gs                                              \
 -o output.pdf                                  \
 -sDEVICE=pdfwrite                              \
 -dAntiAliasColorImage=false                    \
 -dAntiAliasGrayImage=false                     \
 -dAntiAliasMonoImage=false                     \
 -dAutoFilterColorImages=false                  \
 -dAutoFilterGrayImages=false                   \
 -dDownsampleColorImages=false                  \
 -dDownsampleGrayImages=false                   \
 -dDownsampleMonoImages=false                   \
 -dColorConversionStrategy=/LeaveColorUnchanged \
 -dConvertCMYKImagesToRGB=false                 \
 -dConvertImagesToIndexed=false                 \
 -dUCRandBGInfo=/Preserve                       \
 -dPreserveHalftoneInfo=true                    \
 -dPreserveOPIComments=true                     \
 -dPreserveOverprintSettings=true               \
  input1.pdf                                    \
  input2.pdf

最后,正如 Chris Haas 已经暗示的那样:如果您特别不想要 Ghostscript 默认应用的任何优化,您也可以使用 pdftkpdftk 根本无法做这样的事情,你会因为它相对笨拙的操作而获得相当多的速度(但也可能比从 Ghostscript 输出的文件大小要大得多)。

【讨论】:

pdftk 自 2016 年 3 月起不适用于 CentOS/RHEL 7。 您能否应用-dPDFSETTINGS= 设置之一,然后稍后在命令行中使用-d* 设置(在您的答案中)仅覆盖其中的一部分? @CMCDragonkai:是的,你可以。 (不过我还没有测试过。但是如果这不起作用,那将是一个错误。) 这里有一个重新打包的 pdftk 版本,适用于 Centos 7 linuxglobal.com/pdftk-works-on-centos-7【参考方案3】:

这里有一些additional options 可以在使用pdfwrite 作为您的设备时传递。根据该页面,如果您没有通过任何东西,那么-dPDFSETTINGS 将设置为接近/screen,尽管它没有变得更具体。您可以尝试将其设置为 -dPDFSETTINGS=/prepress,它只能压缩 300 dpi 以上的内容。

gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress -sOutputFile=out.pdf in1.pdf in2.pdf

另一种选择是pdftk:

pdftk in1.pdf in2.pdf cat output out.pdf

【讨论】:

感谢您推荐 pdftk。对于 PDF 文件的简单连接,它似乎是完美的。 FWIW: pdftk 不适用于 CentOS/RHEL 7。 我碰巧丢失了页面,并且gs 的大小增加了 10 倍。 pdftk 无需修改即可连接,而且速度更快。

以上是关于合并 PDF 的 Ghostscript 压缩结果的主要内容,如果未能解决你的问题,请参考以下文章

Ghostscript 将图像/表单与文本文件合并

pdf的Ghostscript合并导致方向翻转

Ghostscript 在合并 PDF 时跳过字符

Ghostscript PDF批量压缩

如何使用 ghostscript 从 S3 合并 PDF

Ghostscript:如何在 Windows 上将 PDF 与通配符合并