为什么我的代码无法正确拆分扫描PDF的每一页?

9 投票
3 回答
2817 浏览
提问于 2025-04-16 23:31

更新: 感谢 stardt 的脚本可以正常工作!这个 PDF 是另一个 PDF 的一页。我在另一个 PDF 上试了这个脚本,它也能正确分开每一页,但页码的顺序有时候对,有时候错。例如,在这个 PDF 文件的第 25-28 页中,打印出来的页码是 14、15、17,还有 16。我在想这是为什么?整个 PDF 可以从 http://download304.mediafire.com/u6ewhjt77lzg/bgf8uzvxatckycn/3.pdf 下载。

原始内容: 我有一个扫描的 PDF,其中两页纸并排放在一个 PDF 页面里。我想把这个 PDF 页面分成两部分,左边的部分变成新 PDF 页面的前半部分。这个 PDF 看起来像 enter image description here

这是我写的一个 Python 脚本,叫做 un2up,灵感来自 Gilles

#!/usr/bin/env python
import copy, sys
from pyPdf import PdfFileWriter, PdfFileReader
input = PdfFileReader(sys.stdin)
output = PdfFileWriter()
for p in [input.getPage(i) for i in range(0,input.getNumPages())]:
    q = copy.copy(p)
    (w, h) = p.mediaBox.upperRight

    p.mediaBox.upperLeft = (0, h/2)
    p.mediaBox.upperRight = (w, h/2)
    p.mediaBox.lowerRight = (w, 0)
    p.mediaBox.lowerLeft = (0, 0)

    q.mediaBox.upperLeft = (0, h)
    q.mediaBox.upperRight = (w, h)
    q.mediaBox.lowerRight = (w, h/2)
    q.mediaBox.lowerLeft = (0, h/2)

    output.addPage(q)
    output.addPage(p)
output.write(sys.stdout)

我在终端上用命令 un2up < page.pdf > out.pdf 试了这个脚本,但输出的 out.pdf 没有正确分开。

我还检查了变量 wh 的值,以及 p.mediaBox.upperRight 的输出,它们分别是 5141224,根据它们的实际比例看起来不太对。

这个文件可以从 http://download851.mediafire.com/bdr4sv7v5nzg/raci13ct5w4c86j/page.pdf 下载。

3 个回答

0

我想补充一点,你需要注意的是,mediaBox 这个变量在 pq 这两个副本之间是不会共享的。

这种情况很容易发生,比如你在复制之前就从 p.mediaBox 读取了数据。

如果这样做的话,像是写入 p.mediaBox.upperRight 可能会影响到 q.mediaBox,反之亦然。

@moraes 的解决方案通过明确地复制 mediaBox 来解决这个问题。

1

@stardt 的代码非常有用,但我在处理一批不同方向的 PDF 文件时遇到了问题。这里有一个更通用的函数,无论页面方向如何都能正常工作:

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()
7

你的代码假设 p.mediaBox.lowerLeft 是 (0,0),但实际上它是 (0, 497)

这个在你提供的文件中是有效的:

#!/usr/bin/env python
import copy, sys
from pyPdf import PdfFileWriter, PdfFileReader
input = PdfFileReader(sys.stdin)
output = PdfFileWriter()
for i in range(input.getNumPages()):
    p = input.getPage(i)
    q = copy.copy(p)

    bl = p.mediaBox.lowerLeft
    ur = p.mediaBox.upperRight

    print >> sys.stderr, 'splitting page',i
    print >> sys.stderr, '\tlowerLeft:',p.mediaBox.lowerLeft
    print >> sys.stderr, '\tupperRight:',p.mediaBox.upperRight

    p.mediaBox.upperRight = (ur[0], (bl[1]+ur[1])/2)
    p.mediaBox.lowerLeft = bl

    q.mediaBox.upperRight = ur
    q.mediaBox.lowerLeft = (bl[0], (bl[1]+ur[1])/2)
    if i%2==0:
        output.addPage(q)
        output.addPage(p)
    else:
        output.addPage(p)
        output.addPage(q)

output.write(sys.stdout)

撰写回答