诀窍是使用 Form XObjects 在单个页面中强加多个页面。Form XObjects 可以引用整个 PDF页面,并维护独立的剪辑。PyPDF2 不支持 Form XObjects,因此合并会统一所有输入页面的流,以便它们共享输出页面的剪辑/媒体框。我已经成功地使用了 pdflatex 和 pdfrw (python) - 测试程序在下面内联。由于 Form XObjects 源自类似的 postscript 2 级功能,正如KenS所建议的,应该可以使用“页面剪辑”在 ghostscript 中实现相同的目标。事实上,他在另一个答案中分享了一个 ghostscript 2x1 拼版脚本,但它看起来非常复杂。结合poppler的字体光栅化问题pdftops(即使兼容级别> 1.4),我已经放弃了ghostscript方法。
源自如何将两个 PDF 页面拼接成一个大页面的乳胶脚本?. 需要pdflatex:
\documentclass{article}
\usepackage{pdfpages}
\usepackage[paperwidth=8.5in, paperheight=11in]{geometry}
\usepackage[multidot]{grffile}
\pagestyle{plain}
\begin{document}
\setlength\voffset{+0.0in}
\setlength\hoffset{+0.0in}
\includepdf[ noautoscale=true
, frame=false
, pages={1}
]
{<file.pdf>}
\eject \paperwidth=17in \pdfpagewidth=17in \paperheight=11in \pdfpageheight=11in
\includepdf[ nup=2x1
, noautoscale=true
, frame=false
, pages={2-,}
]
{<file.pdf>}
\end{document}
pdfrw(python 脚本)派生自pdfrw:examples:booklet。需要 pdfrw >= 0.2:
#!/usr/bin/env python3
# Copyright:
# Yclept Nemo
# 2016
# License:
# GPLv3
import itertools
import argparse
import pdfrw
# from itertool recipes in the python documentation
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return itertools.zip_longest(*args, fillvalue=fillvalue)
def pagemerge(page, *pages):
merged = pdfrw.PageMerge() + page
for page in reversed(list(itertools.takewhile(lambda i: i is not None, reversed(pages)))):
merged = merged + page
merged[-1].x = merged[-2].x + merged[-2].w
return merged.render()
parser = argparse.ArgumentParser(description='Impose PDF files using Form XOBjects')
parser.add_argument\
( "source"
, help="PDF, source path"
, type=pdfrw.PdfReader
)
parser.add_argument\
( "-s", "--spacer"
, help="PDF, spacer path"
, type=lambda fp: next(iter(pdfrw.PdfReader(fp).pages), None)
)
parser.add_argument\
( "target"
, help="PDF, target path"
)
args = parser.parse_args()
pages = args.source.pages[:1]
for pair in grouper(args.source.pages[1:], 2):
assert pair[0] is not None
pages.append(pagemerge(pair[0], args.spacer, pair[1]))
# include metadata in target
target = pdfrw.PdfWriter()
target.addpages(pages)
target.trailer.Info = args.source.Info
target.write(args.target)
从 pdfrw 0.2 开始的一些特质:
- 请注意,操作
+=
和append
不是extend
为 pdfrw.PageMerge 定义的,即使它的行为类似于列表。此外,+
它还+=
修改了左侧对象。