我有一个“正常”的 input.pdf(许多页面的方向和方向都相同),我想创建一个可以任意重新排列输入页面的新 pdf
例如:
我只需要旋转和缩放。每个输入页面都将作为输出的某个组件完整呈现。我不需要摆弄文本、颜色、裁剪等。
在伪代码中,这些是我需要的所有功能:
in = open_pdf("input.pdf")
out = new_pdf ()
p = createpage (size)
p.add (in.get_page(123), origin=(0,100), scale=(0.5,0.5), angle=degrees(270))
p.add (...)
out.add(p)
out.save("output.pdf")
Run Code Online (Sandbox Code Playgroud)
我可以在 Python 中做到这一点吗?
如果不是 Python,还有其他一些对 linux 友好的脚本语言?
使用PyPDF2,您可以编写一个脚本来完成与您的伪代码非常相似的任务。
这是一些示例代码,使用同伦类型理论教科书的每晚构建作为输入:
#!/usr/bin/env python3
from PyPDF2 import PdfFileReader, PdfFileWriter
# matrix helper class
class AfMatrix:
""" A matrix of a 2D affine transform. """
__slots__ = ('__a', '__b', '__c', '__d', '__e', '__f')
def __init__(self, a, b, c, d, e, f):
self.__a = float(a)
self.__b = float(b)
self.__c = float(c)
self.__d = float(d)
self.__e = float(e)
self.__f = float(f)
def __iter__(self):
yield self.__a
yield self.__b
yield self.__c
yield self.__d
yield self.__e
yield self.__f
def __hash__(self):
return hash(tuple(self))
def __eq__(self, other):
return tuple(self) == tuple(other)
@classmethod
def compose(cls, *what):
a, b, c, d, e, f = (
1, 0,
0, 1,
0, 0,
)
for rhs in what:
A, B, C, D, E, F = rhs
a, b, c, d, e, f = (
a * A + b * C,
a * B + b * D,
c * A + d * C,
c * B + d * D,
e * A + f * C + E,
e * B + f * D + F,
)
return cls(
a, b,
c, d,
e, f
)
@classmethod
def translate(cls, x=0, y=0):
return cls(
1, 0,
0, 1,
x, y
)
def __takes_origin(func):
def translated_func(cls, *args, origin=(0, 0), **kwargs):
if origin == (0, 0):
return func(cls, *args, **kwargs)
return cls.compose(
cls.translate(-origin[0], -origin[1]),
func(cls, *args, **kwargs),
cls.translate(origin[0], origin[1])
)
return translated_func
@classmethod
@__takes_origin
def shear(cls, x=1, y=1):
return cls(
x, 0,
0, y,
0, 0
)
@classmethod
@__takes_origin
def rotate(cls, angle):
from math import cos, sin, radians
angle = radians(angle)
C = cos(angle)
S = sin(angle)
return cls(
C, S,
-S, C,
0, 0
)
#
reader = PdfFileReader('hott-online-1272-ga50f9bd.pdf')
writer = PdfFileWriter()
ipgs = [reader.getPage(i) for i in range(8)]
# page 1
writer.addPage(ipgs[0])
# page 2
opg1src = ipgs[2:5]
opg1 = writer.addBlankPage(0, 0)
yaccum = 0
for ipg in opg1src:
opg1.mergeTransformedPage(ipg, AfMatrix.compose(
AfMatrix.rotate(90),
AfMatrix.translate(x=ipg.mediaBox.getHeight(), y=yaccum)
), expand=True)
yaccum += ipg.mediaBox.getWidth()
# page 3
opg2 = writer.addBlankPage(
ipgs[6].mediaBox.getWidth(),
ipgs[6].mediaBox.getHeight()
)
opg2.mergeTransformedPage(ipgs[6], (
AfMatrix.shear(x=1/3)
), expand=True)
opg2.mergeTransformedPage(ipgs[7], AfMatrix.compose(
AfMatrix.translate(
x=-opg2.mediaBox.getWidth() / 8,
y=-opg2.mediaBox.getHeight() / 8
),
AfMatrix.rotate(-15, origin=(opg2.mediaBox.getWidth(), 0)),
AfMatrix.shear(x=0.75, y=0.75, origin=(opg2.mediaBox.getWidth(), 0))
), expand=False)
# output
with open('sample.pdf', 'wb') as ostream:
writer.write(ostream)
Run Code Online (Sandbox Code Playgroud)
这是输出:
关于变换矩阵的注意事项:在 PDF 和 PostScript 中,X 坐标向右增长,Y 坐标向上增长,就像在数学自定义中一样(与计算机图形中的自定义不同,Y 坐标向下增长)。与数学习惯不同,点被视为行向量而不是列向量,因此出现在矩阵乘法的左侧。这意味着矩阵变换是从左到右而不是从右到左组成的:首先应用最左边的操作。此外,为了使正角度旋转以逆时针方式出现(再次像数学习惯一样),上面的旋转矩阵似乎转置为其通常的形式。
转换页面时,注意掉出原页面页面边界的内容;在新页面上,它实际上可能会呈现。(我还没有找到解决方案。)
| 归档时间: |
|
| 查看次数: |
393 次 |
| 最近记录: |