如何在 Ghostscript 的帮助下解决这个问题......

如何在 Ghostscript 的帮助下解决这个问题......

我有一堆 PDF 文件,每个 PDF 页面包含两个“真实”页面;我想将它们分成两半,并将每半放在单独的页面上。本质上,我需要一些与pdfnup(或psnup) 完全相反的东西。如何实现这一壮举?

平台是 Linux,优先考虑开源;因为我有一大堆这样的平台,如果能用脚本来做(而不是 GUI)就好了,所以我可以给它一个列表,让它慢慢处理。

预先存在的脚本也不是唯一的选择;如果有使用第三方库以类似方式操作 PDF 的示例代码,我可能就可以对其进行破解,让它按照我想要的方式运行。

答案1

您可以借助 Ghostscript 解决此问题。pdftk仅凭 Ghostscript 无法做到这一点(据我所知)。我将为您提供手动执行此操作的命令行步骤。将其编写为一个过程很容易,还可以使用页面大小和页码的不同参数。但您说您可以自己做 ;-)

如何在 Ghostscript 的帮助下解决这个问题......

...为了好玩,我最近也这么做了不是输入文件包含“双页”页面,但包含“三页”。您可以阅读此案例的答案这里

你的情况更简单。你似乎有类似这样的情况:

+------------+------------+   ^
|            |            |   |
|      1     |      2     |   |
|            |            | 595 pt
|            |            |   |
|            |            |   |
|            |            |   |
+------------+------------+   v
             ^
            fold
             v
+------------+------------+   ^
|            |            |   |
|      3     |      4     |   |
|            |            | 595 pt
|            |            |   |
|            |            |   |
|            |            |   |
+------------+------------+   v
<---------- 842 pt -------->

您想要创建 1 个包含 4 页的 PDF,每页大小为 421 pt x 595 pt。

第一步

让我们首先从每个输入页面中提取左侧部分:

gs \
    -o left-sections.pdf \
    -sDEVICE=pdfwrite \
    -g4210x5950 \
    -c "<</PageOffset [0 0]>> setpagedevice" \
    -f double-page-input.pdf

这些参数起什么作用?

首先,要知道 PDF1 英寸 == 72 点。那么剩下的就是:

  • -o ...............:命名输出文件。隐式地也使用-dBATCH -dNOPAUSE -dSAFER
  • -sDEVICE=pdfwrite :我们希望 PDF 作为输出格式。
  • -g................:设置输出媒体大小(以像素为单位)。pdfwrite 的默认分辨率为 720 dpi。因此乘以 10 即可获得 PageOffset 的匹配值。
  • -c "..............:要求 Ghostscript 在主输入文件(需要跟在后面-f)之前处理给定的 PostScript 代码片段。
  • <</PageOffset ....:设置介质上页面图像的移位。(当然,对于左页,移位[0 0]没有实际效果。)
  • -f ...............:处理此输入文件。

最后一个命令实现了什么结果?

这个:

Output file: left-sections.pdf, page 1
+------------+  ^
|            |  |
|     1      |  |
|            |595 pt
|            |  |
|            |  |
|            |  |
+------------+  v

Output file: left-sections.pdf, page 2
+------------+  ^
|            |  |
|     3      |  |
|            |595 pt
|            |  |
|            |  |
|            |  |
+------------+  v
<-- 421 pt -->

第二步

接下来,正确的部分:

gs \
    -o right-sections.pdf \
    -sDEVICE=pdfwrite \
    -g4210x5950 \
    -c "<</PageOffset [-421 0]>> setpagedevice" \
    -f double-page-input.pdf

请注意负偏移,因为我们将页面向左移动,同时保持查看区域静止。

结果:

Output file: right-sections.pdf, page 1
+------------+  ^
|            |  |
|     2      |  |
|            |595 pt
|            |  |
|            |  |
|            |  |
+------------+  v

Output file: right-sections.pdf, page 2
+------------+  ^
|            |  |
|     4      |  |
|            |595 pt
|            |  |
|            |  |
|            |  |
+------------+  v
<-- 421 pt -->

最后一步

现在我们将页面合并为一个文件。我们也可以使用 ghostscript 来实现这一点,但我们将使用它pdftk,因为它可以更快地完成这项工作:

pdftk \
  A=right-sections.pdf \
  B=left-sections.pdf \
  shuffle \
  output single-pages-output.pdf
  verbose

完成。这是所需的结果。4 个不同的页面,大小为 421x595 pt。

结果:

+------------+ +------------+ +------------+ +------------+   ^
|            | |            | |            | |            |   |
|     1      | |     2      | |     3      | |     4      |   |
|            | |            | |            | |            |5595 pt
|            | |            | |            | |            |   |
|            | |            | |            | |            |   |
|            | |            | |            | |            |   |
+------------+ +------------+ +------------+ +------------+   v
<-- 421 pt --> <-- 421 pt --> <-- 421 pt --> <-- 421 pt -->

答案2

有一个工具pdf海报可用于将一个输入页面创建为多页 PDF(平铺或剪切页面)。它类似于工具poster,对 PostScript 文件执行相同操作。

答案3

因此,经过大量搜索(似乎“PDF 剪切页面”是一个更好的搜索),我找到了一个名为unpnup它使用posterPDF/PS 转换,并pdftk完全满足我的需要。这有点绕,但它比我发现的其他方法(例如使用 imagemagick)要好得多,因为它在输出页面之前不会对页面进行栅格化。

为了防止 mobileread 由于某种原因消失,脚本的核心(由 Harald Hackenberg 根据 GPLv2 或更高版本授权<hackenberggmx.at>)如下:

pdftk "$1" burst
for file in pg*.pdf;
do
    pdftops -eps $file
    poster -v -pA4 -mA5 -c0% `basename $file .pdf`.eps > `basename $file .pdf`.tps
    epstopdf `basename $file .pdf`.tps
done
pdftk pg*.pdf cat output ../`basename $1 .pdf`_unpnuped.pdf

答案4

基于piptas'答案如上所述:

在 Windows 上,为了在开始时拆分带有单个封面图像的 letter 大小的 PDF,下面的方法对我来说非常有效(请注意第二步中使用 [-612 0],正值会创建空白页,因为它推错了方向。)

gswin32c -o left-sections.pdf -sDEVICE=pdfwrite -dFirstPage=2 -g6120x7920 -c "<</PageOffset [0 0]>> setpagedevice" -f input.pdf

请注意其用法-dFirstPage=2指示 gs 从第 2 页开始处理。

gswin32c -o right-sections.pdf -sDEVICE=pdfwrite -dFirstPage=2 -g6120x7920 -c "<</PageOffset [-612 0]>> setpagedevice" -f input.pdf

以同样的方式创建 right-sections.pdf。现在是封面图片:

gswin32c -o cover.pdf -sDEVICE=pdfwrite -dLastPage=1 -g6120x7920 -c "<</PageOffset [0 0]>> setpagedevice" -f input.pdf

接下来,由于我不想使用手动页面输入与 pdftk 合并,因此我将左右部分拆分为新目录中的单独 PDF。

mkdir input_file
copy cover.pdf input_file\0000.pdf
pdftk left-sections.pdf burst output input_file\%04d_A.pdf
pdftk right-sections.pdf burst output input_file\%04d_B.pdf

然后我按字母顺序将该目录中的 PDF 合并(幸运的是,这意味着它们按正确的顺序排列!),并再次通过 ghostscript 运行结果以修复 pdftk 产生的“警告:代数超出 0..65535 范围,假设为 0。”错误,该 pdftk 称为“itext-paulo-155 (itextpdf.sf.net-lawagie.com)”——在我的使用中,它也恰好将文件大小减少了一半。对于 4.5MB 的原始文件,pdftk 的结果为 6.7MB,而 gswin32c 的重新处理将其减少到 3.2 MB。

pdftk input_file\*.pdf cat output input_temp.pdf
gswin32c -o final_output.pdf -sDEVICE=pdfwrite -f input_temp.pdf

我们完成了!请随意删除 input_file 文件夹、cover.pdf、input_temp.pdf、right_sections.pdf 和 left_sections.pdf。;-)

相关内容