将PDF页面分成多页[关闭]


16

我有一堆包含两个“真实”页面到一个PDF页面的PDF文件。我想将它们切成两半,然后将每半放在单独的页面上。本质上,我需要做与pdfnup(或psnup)相反的事情。如何实现这一壮举?

平台是Linux,首选开源;因为我有很多这样的东西可以做一些可以编写脚本(而不是GUI)的脚本,所以我可以给它们列出一个清单,并加以补充。

既不是预先存在的脚本也不是唯一的选择。如果有使用第三方库以类似方式操作PDF的示例代码,我可能可以破解它来做我想要的事情。


Answers:


22

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

如何借助Ghostscript解决此问题...

...并且为了它的乐趣,我最近不是用一个具有“双倍”页面的输入文件来完成它,而是使用一个“高倍率”页面来完成它。您可以在这里阅读此案例的答案。

您的情况甚至更简单。您似乎有类似以下内容:

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

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

第一步

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

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

这些参数是做什么的?

首先,要知道在PDF中1英寸== 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磅。

结果:

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

@Unknown:感谢您的不赞成!您是否愿意写评论说明某些原因?
Kurt Pfeifle

+1是ASCII语言的绝佳用法,而且指令非常清晰。只是因为我是CLI n00b,\会跳过行,因此更易于阅读,对吧?
Journeyman Geek

@mullhausen:感谢纠正错字(421-> -421)。;-)
Kurt Pfeifle12年

6

有一个pdfposter工具,可用于为一个输入页面(平铺或切碎页面)创建具有多个页面的PDF。它与工具相似poster,对PostScript文件执行相同的操作。


pdfposter不会处理边缘重叠的内容,以简化海报组装。不过,这是一个Perl脚本,因此添加起来相当容易。
Matthias Urlichs 2013年

3

因此,在进行了更多搜索(似乎“ PDF剪切页”是一个更好的搜索)之后,我发现了一个名为的小脚本unpnup,它使用poster,PDF / PS转换并pdftk完全满足我的需要。它有很长的路要走,但是它比我发现的其他方法(例如使用imagemagick)要优越得多,因为它不会在将页面吐出之前对其进行栅格化。

万一mobileread由于某种原因而消失,脚本的核心如下(由GPLv2许可,或后来由Harald Hackenberg许可<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

1
当人们回答自己的问题时,一定会喜欢它。但是,如果您需要使用GUI进行操作,尤其是在页面大小不均匀
frabjous 2010年

您应该能够单独使用PDFTK进行所需的操作,而无需进行所有转换。
CarlF 2010年

@CarlF:我认为有可能,但是在PDFTK手册页中看不到任何可操纵页面内容的内容。有什么建议给我吗?
womble 2010年

@frabjous:回答自己的问题怎么了?
Kurt Pfeifle

1
@womble:您的转换通过PS / EPS进行。这势必会导致质量下降(嵌入式字体,透明胶片等)。我的建议是避免冒险的PDF => EPS => PDF路线,而是走更安全的PDF => PDF => PDF路。
Kurt Pfeifle

2

我发现Kurt Pfeifle的答案对我的类似情况非常有帮助。我想我可以和其他人分享我对解决方案的修改...

我也有一个扫描的PDF,每张纸上有2页。这是对一本骑马钉装订小册子的11 x 8.5(英寸)扫描,该小册子在最初扫描时就装订了,因此:PDF第1页=封面和封底;PDF第2页=第2页和第3页,依此类推。这在屏幕上看起来不错,但是您无法打印然后装订以制作更多手册。

我需要能够在双面复印机上进行打印。即,将其转回为“拼版” PDF,以供打印。因此,使用Kurt的解决方案,我使这个(糟糕的)“单面纸”可以再次以正确的页面顺序将其转换回半页。它适用于任何高度和宽度,也适用于任何数量的页面。就我而言,我有一本40页的小册子(PDF中扫描了20页)。

HEIGHT=8.5 WIDTH=11 ORIG_FILE_PATH="original.pdf" \
count=$(set -xe; \
gs -o left.pdf -sDEVICE=pdfwrite \
-g$(perl -e "print(($WIDTH / 2) * 720)")x$(perl -e "print($HEIGHT * 720)") \
-c "<</PageOffset [0  0]>> setpagedevice" \
-f "$ORIG_FILE_PATH" >/dev/null; \
gs -o right.pdf -sDEVICE=pdfwrite \
-g$(perl -e "print(($WIDTH / 2) * 720)")x$(perl -e "print($HEIGHT * 720)") \
-c "<</PageOffset [-$(perl -e "print(($WIDTH / 2) * 72)")  0]>> setpagedevice" \
-f "$ORIG_FILE_PATH" | grep Page | wc -l ); \
echo '>>>>>' Re-ordering $count pages...; \
(set -xe; pdftk A=right.pdf B=left.pdf cat \
A1 `set +xe; for x in $(seq 2 $count); do echo B$x A$x; done` B1 \
output ordered.pdf); \
echo "Done. See ordered.pdf"

您只需要更改此命令中的前几个参数即可指定HEIGHT和WIDTH以及ORIG_FILE_PATH。该命令的其余部分将计算各种大小,并两次调用gs,然后调用pdftk。它甚至会计算您扫描中的页数,然后生成正确的排序规范(针对我给出的方案)。

它输出有关其操作的一些进展,如下所示:

+++ perl -e 'print((11 / 2) * 720)'
+++ perl -e 'print(8.5 * 720)'
++ gs -o left.pdf -sDEVICE=pdfwrite -g3960x6120 -c '<</PageOffset [0  0]>> setpagedevice' -f original.pdf
++ wc -l
++ grep Page
+++ perl -e 'print((11 / 2) * 720)'
+++ perl -e 'print(8.5 * 720)'
+++ perl -e 'print((11 / 2) * 72)'
++ gs -o right.pdf -sDEVICE=pdfwrite -g3960x6120 -c '<</PageOffset [-396  0]>> setpagedevice' -f original.pdf
>>>>> Re-ordering 20 pages...
++ set +xe
+ pdftk A=right.pdf B=left.pdf cat A1 B2 A2 B3 A3 B4 A4 B5 A5 B6 A6 B7 A7 B8 A8 B9 A9 B10 A10 B11 A11 B12 A12 B13 A13 B14 A14 B15 A15 B16 A16 B17 A17 B18 A18 B19 A19 B20 A20 B1 output ordered.pdf
Done. See ordered.pdf

接下来,要获得印刷小册子所需的页面拼版,只需在与您所需大小完全相同的自定义页面大小上“打印” ordered.pdf(在我的示例中为5.5 x 8.5),然后将其发送到“小册子制作”工具(在我的案例中,我使用了Christoph Vogelbusch的Mac版“创建手册”,网址http://download.cnet.com/Create-Booklet/3000-2088_4-86349.html)。

现在,生成的PDF将恢复为11 x 8.5的原始页面大小,每张纸可打印2页,但排序方式为可以双面打印,短边装订和打印!您将获得一份打印件,可以影印,折叠和骑马装订,可以在不拆卸(甚至不必看)原始文件的情况下复制原始小册子。

希望这对某人有帮助!

-C


1

根据上述piptas的回答:

在Windows上,要在开始时用单个封面图像分割字母大小的PDF,以下对我非常有用(请注意,在第二步中使用[-612 0],正值会产生空白页,因为它以错误的方式推送了)

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

请注意-dFirstPage=2第2页上使用哪个命令指示gs开始处理。

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

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

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。;-)


1

如果您只需要在一个文档中全部输出左侧pdf,而在一个文档中全部输出右侧pdf,则以下基于Kurt Pfeifle答案的脚本可以解决问题(适用于任何高度和高度宽度):

$ cat split.sh
#!/bin/bash                                                                     

dims=$(pdfinfo "$1" | grep -i "page size:" | cut -d ":" -f2)                    
width=$(echo "$dims" | cut -d " " -f7)                                          
height=$(echo "$dims" | cut -d " " -f9)                                         
half_width=$(echo "$width * 0.5" | bc -l | cut -d "." -f1)                      
half_widthtt=$(echo "$width * 5" | bc -l | cut -d "." -f1)                      
heighttt=$(echo "$height * 10" | bc -l | cut -d "." -f1)                        

echo "pdf $1 has height $height and width $width"                               

gs -o "left-$1" -sDEVICE=pdfwrite -g"$half_widthtt"x"$heighttt" -c "<</PageOffset [0 0]>> setpagedevice" -f "$1"
gs -o "right-$1" -sDEVICE=pdfwrite -g"$half_widthtt"x"$heighttt" -c "<</PageOffset [-$half_width 0]>> setpagedevice" -f "$1"

然后像这样运行它:

$ ./split.sh thepdftosplit.pdf
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.