如何旋转 PDF 页面以便设置 *Box(它不只是使用 rot=90)

How to rotate a PDF page so that *Box is set (and it doesn't just use rot=90)

我们用 php 编写的网站从客户那里接收 PDF 文件。处理后,下一步是来自供应商的代码。该代码要求每个页面的纵向尺寸为 8.5x11"。该代码还要求该页面具有如下数据(从 pdfinfo 输出):

Page    1 size: 612 x 792 pts (letter)
Page    1 rot:  0
Page    1 MediaBox:     0.00     0.00   612.00   792.00
Page    1 CropBox:      0.00     0.00   612.00   792.00
Page    1 BleedBox:     0.00     0.00   612.00   792.00
Page    1 TrimBox:      0.00     0.00   612.00   792.00
Page    1 ArtBox:       0.00     0.00   612.00   792.00

有时客户给我们的 PDF 有一页或多页纵向。我们有使用 FPDI 重写文件的代码,将需要它的页面旋转 90 度:

$pdf->AddPage('L', array(215.9, 279.4), 90);

问题是只是设置了 rot=90 并且生成的文件有这个(来自 pdfinfo 的输出):

Page    3 size: 792 x 612 pts (letter)
Page    3 rot:  90
Page    3 MediaBox:     0.00     0.00   792.00   612.00
Page    3 CropBox:      0.00     0.00   792.00   612.00
Page    3 BleedBox:     0.00     0.00   792.00   612.00
Page    3 TrimBox:      0.00     0.00   792.00   612.00
Page    3 ArtBox:       0.00     0.00   792.00   612.00

我们的下一步代码无法识别 rot=90 并将其视为横向页面。

我可以用什么来改变页面特征,使其像第一组数据(肖像图像)?在我们的环境中,ghostscript 是可用的。可以用pdftk(难度更大)

已添加 我从帕特里克的 pdfrw 开始,但最终转向只使用 FPDF。我注意到一件奇怪的事情:当我使用 ghostscript 连接到其他文件时,我丢失了大多数文件的旋转修复,这些文件旋转为仅字母、纵向使用 FPDF 和 pdfrw。解决方案:我 运行 在用 gs 连接任何文件后再次 "fix rotation" 代码。

这是一个使用我的 Python 包 pdfrw 的示例。 pdfrw 可能已经安装在您的系统上,也可能尚未安装;如果没有,您可以使用通常的 pip 或 easy_install(甚至可能 apt-get install python-pdfrw)安装它,或者直接从 github.

中拉取它

这个例子使用了一个叫做 Form XObjects 的 PDF 功能。如果您的输出处理软件不支持这些,那么我们可以创建一个版本来重新创建 pdfrw 完成的数学运算,但更新实际的页面流。 (在我开始使用 Form XObjects 之前,我曾经这样做过,但后者通常更干净。)

另请注意,pdfrw 不支持加密的 PDF,因此必须先解密这些文件。如果这对您的 PDF 不起作用,请将示例发送给我,我会查看它。

抛开这些注意事项,这实际上比您要求的功能多一点——它会缩小太大的页面,并使太小的页面居中:

#!/usr/bin/env python


import sys
import os

from pdfrw import PdfReader, PdfWriter, PageMerge


# Change these constants to change output size or orientation

outbox = 0, 0, 8.5 * 72, 11 * 72

# Generic calculations from box

out_x = outbox[0]
out_y = outbox[1]
out_w = outbox[2] - out_x
out_h = outbox[3] - out_y
out_landscape = out_w > out_h

inpfn, = sys.argv[1:]
outfn = 'normalized.' + os.path.basename(inpfn)
inp = PdfReader(inpfn)
out = PdfWriter()

def fixpage():
    # Figure out the rotation requirement before instantiating 
    landscape = bool(rotate % 180) ^ (mbox[2] - mbox[0] > mbox[3] - mbox[1])
    rotation = 0 if landscape == out_landscape else 90

    # Create a canvas, add the page, and get a reference to the page rectangle
    canvas = PageMerge()
    canvas.add(page, rotate=rotation)
    rect = canvas[0]

    # Scale the page rectangle if it doesn't fit our output size
    scaling = max(rect.w / out_w, rect.h / out_h)
    if scaling > 1.0:
        rect.scale(1.0/scaling)

    # Center the page rectangle on the output
    rect.x = out_x + (out_w - rect.w) / 2
    rect.y = out_y + (out_h - rect.h) / 2
    canvas.mbox = outbox
    return canvas.render()

for page in inp.pages:
    rotate = int(page.inheritable.Rotate or 0)
    mbox = tuple(float(x) for x in page.inheritable.MediaBox)
    out.addpage(fixpage() if rotate or mbox != outbox else page)

out.write(outfn)

在使用 useTemplate() 之前,只需使用 this 脚本中的 Rotate() 函数,即可使用 FPDF 旋转导入的页面。无需切换到另一种语言。