我有大量 PDF 文件,其中一页有两张幻灯片(用于打印)。
格式为 A4 页,每页有两张幻灯片,如下所示:
-----------
| slide 1 |
-----------
| slide 2 |
-----------
如何生成每页一张幻灯片的新 PDF 文件?
乐于使用 GUI、CLI、脚本甚至与某种语言的 PDF 库交互;但我确实需要幻灯片上的文本仍然可供选择。
PDF 剪刀 允许我批量分割(裁剪)PDF 中的所有页面。
您可以使用名为 PyPDF 的 Python 库。无论页面方向如何,此功能都会拆分双页:
import copy
import math
import pyPdf
def split_pages(src, dst):
src_f = file(src, 'r+b')
dst_f = file(dst, 'w+b')
input = pyPdf.PdfFileReader(src_f)
output = pyPdf.PdfFileWriter()
for i in range(input.getNumPages()):
p = input.getPage(i)
q = copy.copy(p)
q.mediaBox = copy.copy(p.mediaBox)
x1, x2 = p.mediaBox.lowerLeft
x3, x4 = p.mediaBox.upperRight
x1, x2 = math.floor(x1), math.floor(x2)
x3, x4 = math.floor(x3), math.floor(x4)
x5, x6 = math.floor(x3/2), math.floor(x4/2)
if x3 > x4:
# horizontal
p.mediaBox.upperRight = (x5, x4)
p.mediaBox.lowerLeft = (x1, x2)
q.mediaBox.upperRight = (x3, x4)
q.mediaBox.lowerLeft = (x5, x2)
else:
# vertical
p.mediaBox.upperRight = (x3, x4)
p.mediaBox.lowerLeft = (x1, x6)
q.mediaBox.upperRight = (x3, x6)
q.mediaBox.lowerLeft = (x1, x2)
output.addPage(p)
output.addPage(q)
output.write(dst_f)
src_f.close()
dst_f.close()
Briss 是“一个简单的跨平台(Linux、Windows、Mac OSX)应用程序,用于裁剪 PDF 文件。简单的用户界面可让您通过在视觉上重叠的页面上拟合矩形来精确定义裁剪区域。”它是开源的(GPL)。
对我来说效果很好。 GUI 很小,但功能齐全。也可以从命令行使用它。
感谢 Matt Gumbley 提供的 Python 脚本。我修改了该 Python 脚本,现在它也可以处理包含纵向和横向页面以及裁剪页面的 PDF:
# -*- coding: utf-8 -*-
"""
Created on Thu Feb 26 08:49:39 2015
@author: Matt Gumbley (stackoverflow)
changed by Hanspeter Schmid to deal with already cropped pages
"""
import copy
import math
from PyPDF2 import PdfFileReader, PdfFileWriter
def split_pages2(src, dst):
src_f = file(src, 'r+b')
dst_f = file(dst, 'w+b')
input = PdfFileReader(src_f)
output = PdfFileWriter()
for i in range(input.getNumPages()):
# make two copies of the input page
pp = input.getPage(i)
p = copy.copy(pp)
q = copy.copy(pp)
# the new media boxes are the previous crop boxes
p.mediaBox = copy.copy(p.cropBox)
q.mediaBox = copy.copy(p.cropBox)
x1, x2 = p.mediaBox.lowerLeft
x3, x4 = p.mediaBox.upperRight
x1, x2 = math.floor(x1), math.floor(x2)
x3, x4 = math.floor(x3), math.floor(x4)
x5, x6 = x1+math.floor((x3-x1)/2), x2+math.floor((x4-x2)/2)
if (x3-x1) > (x4-x2):
# horizontal
q.mediaBox.upperRight = (x5, x4)
q.mediaBox.lowerLeft = (x1, x2)
p.mediaBox.upperRight = (x3, x4)
p.mediaBox.lowerLeft = (x5, x2)
else:
# vertical
p.mediaBox.upperRight = (x3, x4)
p.mediaBox.lowerLeft = (x1, x6)
q.mediaBox.upperRight = (x3, x6)
q.mediaBox.lowerLeft = (x1, x2)
p.artBox = p.mediaBox
p.bleedBox = p.mediaBox
p.cropBox = p.mediaBox
q.artBox = q.mediaBox
q.bleedBox = q.mediaBox
q.cropBox = q.mediaBox
output.addPage(q)
output.addPage(p)
output.write(dst_f)
src_f.close()
dst_f.close()
这是我用
pdfrw
做到的:
import sys, os, pdfrw
writer = pdfrw.PdfWriter()
for page in pdfrw.PdfReader('input.pdf').pages:
for y in [0, 0.5]:
newpage = pdfrw.PageMerge()
newpage.add(page, viewrect=(0, y, 1, 0.5))
writer.addpages([newpage.render()])
writer.write('output.pdf')
又短又有效!
如果你想要旋转(例如:输入A4纵向,输出2个A5纵向而不是横向):
import sys, os, pdfrw
writer = pdfrw.PdfWriter()
for page in pdfrw.PdfReader('input.pdf').pages:
for y in [0, 0.5]:
newpage = pdfrw.PageMerge()
newpage.add(page, viewrect=(0, y, 1, 0.5))
p = newpage.render()
p.Rotate = 270
writer.addpages([p])
writer.write('output.pdf')
尝试BRISS。
它可以让您将每个页面拆分为任意数量的子页面 使用 GUI 定义区域。它将所有相似的页面分组 为您服务,因此您可以为该组定义一次区域。
它是跨平台、免费且开源的。
如果使用 Java 或 .Net 库适合您,则可以使用 iText / iTextSharp。
平铺现有文档的示例可以在《iText in Action》一书中找到,第二版,免费提供的第 6 章:TilingHero.java / TilingHero.cs。
就我而言,生成的 PDF 在 Adobe Reader 和 Mac 预览中看起来不错,但在 iOS 上查看时似乎根本没有被分割成单独的页面。
我使用了Python 2.7.8和PyPDF2,并按如下方式修改了脚本,效果很好(并且对页面进行了左/右重新排序,而不是右/左)。
import copy
import math
from PyPDF2 import PdfFileReader, PdfFileWriter
def split_pages(src, dst):
src_f = file(src, 'r+b')
dst_f = file(dst, 'w+b')
input = PdfFileReader(src_f)
output = PdfFileWriter()
for i in range(input.getNumPages()):
p = input.getPage(i)
q = copy.copy(p)
q.mediaBox = copy.copy(p.mediaBox)
x1, x2 = p.mediaBox.lowerLeft
x3, x4 = p.mediaBox.upperRight
x1, x2 = math.floor(x1), math.floor(x2)
x3, x4 = math.floor(x3), math.floor(x4)
x5, x6 = math.floor(x3/2), math.floor(x4/2)
if x3 > x4:
# horizontal
p.mediaBox.upperRight = (x5, x4)
p.mediaBox.lowerLeft = (x1, x2)
q.mediaBox.upperRight = (x3, x4)
q.mediaBox.lowerLeft = (x5, x2)
else:
# vertical
p.mediaBox.upperRight = (x3, x4)
p.mediaBox.lowerLeft = (x1, x6)
q.mediaBox.upperRight = (x3, x6)
q.mediaBox.lowerLeft = (x1, x2)
p.artBox = p.mediaBox
p.bleedBox = p.mediaBox
p.cropBox = p.mediaBox
q.artBox = q.mediaBox
q.bleedBox = q.mediaBox
q.cropBox = q.mediaBox
output.addPage(q)
output.addPage(p)
output.write(dst_f)
src_f.close()
dst_f.close()
这是更新到 python 3.10.9 和 PyPDF2 3.0.1 的 Hanspeter Schmid 答案:
import copy
import math
from PyPDF2 import PdfReader, PdfWriter
def split_pages2(src, dst):
with open(src, 'r+b') as src_f, open(dst, 'w+b') as dst_f:
input = PdfReader(src_f)
output = PdfWriter()
for i in range(len(input.pages)):
# make two copies of the input page
pp = input.pages[i]
p = copy.copy(pp)
q = copy.copy(pp)
# the new media boxes are the previous crop boxes
p.mediabox = copy.copy(p.cropbox)
q.mediabox = copy.copy(p.cropbox)
x1, x2 = p.mediabox.lower_left
x3, x4 = p.mediabox.upper_right
x1, x2 = math.floor(x1), math.floor(x2)
x3, x4 = math.floor(x3), math.floor(x4)
x5, x6 = x1+math.floor((x3-x1)/2), x2+math.floor((x4-x2)/2)
if (x3-x1) > (x4-x2):
# horizontal
q.mediabox.upper_right = (x5, x4)
q.mediabox.lower_left= (x1, x2)
p.mediabox.upper_right = (x3, x4)
p.mediabox.lower_left = (x5, x2)
else:
# vertical
p.mediabox.upper_right = (x3, x4)
p.mediabox.lower_left= (x1, x6)
q.mediabox.upper_right = (x3, x6)
q.mediabox.lower_left= (x1, x2)
p.artbox = p.mediabox
p.bleedbox = p.mediabox
p.cropbox = p.mediabox
q.artbox = q.mediabox
q.bleedbox = q.mediabox
q.cropbox = q.mediabox
output.add_page(q)
output.add_page(p)
output.write(dst_f)
src_f.close()
dst_f.close()
使用
mupdf-1.8-windows-x64
,在win10 CMD中,需要在水平参数(-x)之前有'poster'(后面跟空格,不带引号)。
例如,将双页扫描为 PDF:
mutool海报-x 2 -y 1 C:\Users lfie\Documents\SNM\The_Ultimate_Medicine.pdf C:\Users lfie\Documents books\The_Ultimate_Medicine.pdf
多么美妙的工具啊!谢谢无限!.. (输出文件 ~9MB 仅比原始文件大 52KB!)