以pdf分割页面


67

我有一个扫描的pdf文件,已在一个虚拟页面(pdf文件中的页面)上扫描了两页。

分辨率良好。问题是我必须在阅读时进行缩放并从左向右拖动。
是否有一些命令(convert,,pdftk...)或脚本可以将此pdf文件转换为普通页面(书中的一页= pdf文件中的一页)?


1
尽管这不是最受好评的答案,但这个答案确实让我感到惊讶。它简单,简短,快速而优雅。我认为在这里值得一提,因为有时我们懒得向下滚动到其他答案……
Peque 2015年

对于记录,可以pdfnuppdfjam套件中通过命令行(而不是“打印到文件”)从命令行获得反向操作(连接多个页面)。
Skippy le Grand Gourou

Answers:


46

这是一个使用PyPdf库的小型Python脚本,可以很好地完成这项工作。将其保存在名为un2up(或您喜欢的脚本)的脚本中,使其可执行(chmod +x un2up),然后作为过滤器(un2up <2up.pdf >1up.pdf)运行。

#!/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.upperRight = (w/2, h)
    q.mediaBox.upperLeft = (w/2, h)
    output.addPage(p)
    output.addPage(q)
output.write(sys.stdout)

忽略任何弃用警告;只有PyPdf维护者需要关心这些。

如果输入的方向不正常,则在截断页面时可能需要使用不同的坐标。请参阅为什么我的代码无法正确地将扫描的pdf中的每一页分开?


万一有用,这是我之前的答案,它结合使用了两种工具和一些手动干预:

  • 基于pdfpages LaTeX软件包的Pdfjam(至少为2.0版)可裁剪页面;
  • Pdftk,将左右两半放回去。

这两个工具都是必需的,因为据我所知pdfpages不能在一个流中对同一页面应用两种不同的转换。在对的调用中pdftk,将42替换为输入文档(2up.pdf)中的页数。

pdfjam -o odd.pdf --trim '0cm 0cm 14.85cm 0cm' --scale 1.141 2up.pdf
pdfjam -o even.pdf --trim '14.85cm 0cm 0cm 0cm' --scale 1.141 2up.pdf
pdftk O=odd.pdf E=even.pdf cat $(i=1; while [ $i -le 42 ]; do echo O$i E$i; i=$(($i+1)); done) output all.pdf

如果您没有pdfjam 2.0,则只需安装带有pdfpages软件包的PDFLaTeX(在Ubuntu上:您需要texlive-latex-recommended 安装texlive-latex-recommended,也许(在Ubuntu上:texlive-fonts-recommended 安装texlive-fonts-推荐),并使用以下驱动程序文件driver.tex

\batchmode
\documentclass{minimal}
\usepackage{pdfpages}
\begin{document}
\includepdfmerge[trim=0cm 0cm 14.85cm 0cm,scale=1.141]{2up.pdf,-}
\includepdfmerge[trim=14.85cm 0cm 0cm 0cm,scale=1.141]{2up.pdf,-}
\end{document}

然后运行以下命令,用输入文件中的页面数替换42(必须调用2up.pdf):

pdflatex driver
pdftk driver.pdf cat $(i=1; pages=42; while [ $i -le $pages ]; do echo $i $(($pages+$i)); i=$(($i+1)); done) output 1up.pdf

PyPdf库运行完美。我只做了一点改动,并使用python conv_pdf.py res.pdf运行它。您将如何从命令行运行脚本shebang?
xralf 2011年

我也想尝试使用pdfjam的版本(由于略有缩放),但是在安装pdfjam软件包后,我的外壳将无法识别pdfjam命令。
xralf

@xralf:我的python脚本仅从标准输入读取并写入标准输出。pdfjam版本需要pdfjam 2.0;它只是围绕pdfpages的一个小包装,而且我还添加了它生成的LaTeX,因此您可以直接使用它。pypdf可能解决了缩放问题,这可能是页面大小的问题(如果您提供有关正在发生的事情的更多详细信息,尤其是涉及的页面大小,我可能会或可能无法提供帮助)。
吉尔(Gilles)

谢谢,区别在于分辨率稍差一些,但这无关紧要。当我对Latex有了更多的了解时,我将回到它(它对我来说太复杂了,PyPdf的解决方案真的很好)。
xralf

1
@Gilles Versy有用的脚本。我期望在pdfjam,pdftk中看到类似的内容。无论如何,有些人可能希望进行一些修改以在其他轴上拆分页面并使用不同的顺序。只需更改几行即可使用q.mediaBox.lowerRight = (w, h/2)
ony 2012年

52

由于我对python脚本(以及其他几个解决方案)有疑问,这只是一个补充:对我来说mutool很棒。这是优雅的mupdf阅读器附带的一个简单且小的附件。因此,您可以尝试:

mutool poster -y 2 input.pdf output.pdf

对于水平分割,请替换yx。当然,您可以将两者结合起来以获得更复杂的解决方案。

真的很高兴找到这个(多年使用mupdf多年:)

mutool从1.4版开始随附mupdf:http//www.mupdf.com/news


安装mupdfmutool从源头:

wget http://www.mupdf.com/downloads/mupdf-1.8-source.tar.gz
tar -xvf mupdf-1.8-source.tar.gz
cd mupdf-1.8-source
sudo make prefix=/usr/local install

或转到下载页面以找到较新的版本。


3
我有一个djvu ...我把它变成了一个后记(相当快),然后变成了一个pdf(乌龟变慢)-最终mutool剪切得如此之快,以至于我认为它不起作用-可以了!
Julien Puydt 2015年

2
是的,我也对速度感到非常满意。
martz 2015年

3
这是最简单和更好的。mutool为此。另外,请注意-y,在大多数情况下,我认为您想要的是-x
fiatjaf

2
该实用程序非常快,但是页面顺序有问题。该命令在第一个位置分配右页面,在第二个位置分配左页面。有人可以帮我解决这个问题吗?
garciparedes


16

Imagemagick可以一步完成:

$ convert in.pdf -crop 50%x0 +repage out.pdf

1
谢谢。如果我添加-density 400参数`,它将具有更好的质量。
xralf 2011年

11
看起来convert使用栅格作为中间格式。即使原始PDF包含矢量对象,这也会导致外观模糊。
2012年

有谁知道这样做的方法而不会沿途光栅化页面内容...或至少设置更高的分辨率?
Tomislav Nakic-Alfirevic

这样可以将文本渲染为图像,并根据图像创建pdf。也许对图片很好,但是对文本提取没用。
andrej

6

ImageMagick的Convert命令可以帮助您分两部分裁剪文件。参见http://www.imagemagick.org/使用情况/ crop /

如果我是你,我会写一个像这样的(shell)脚本:

  1. 使用pdfsam分割文件:1页= 1个磁盘上的文件(格式无关紧要。选择ImageMagick知道的文件。我只是选择PS或PDF。
  2. 对于每一页,裁剪前半部分并将其放入名为$ {PageNumber} A的文件中

  3. 裁剪后半部分,并将其放入名为$ {PageNumber} B的文件中。

    您将获得1A.pdf,1B.pdf,2A.pdf,2B.pdf等。

  4. 现在,再次将其组装成新的PDF。 有很多方法可以做到这一点。

1
不会使用ImageMagick栅格化文件吗?您应该内联解释最后一部分,尤其是为了使听众中的非法语人士受益。
吉尔斯

因为您不需要懂法语。它仅显示了如何单独使用ImageMagick的convert,pdftk或ghostscript(gs)来实现此目标。我喜欢使用pdftk。“光栅化”并不重要,因为它是扫描的文档。
tiktak 2011年

6

基于Gilles的回答以及我写的如何查找PDF页面数

#!/bin/bash

pdforiginal=$1
pdfood=$pdforiginal.odd.pdf
pdfeven=$pdforiginal.even.pdf
pdfout=output_$1
margin=${2:-0}
scale=${3:-1}

pages=$(pdftk $pdforiginal dump_data | grep NumberOfPages | awk '{print $2}')

pagesize=$(pdfinfo $pdforiginal | grep "Page size" | awk '{print $5}')
margin=$(echo $pagesize/2-$margin | bc -l)

pdfjam -o $pdfood --trim "0cm 0cm ${margin}pt 0cm" --scale $scale $pdforiginal
pdfjam -o $pdfeven --trim "${margin}pt 0cm 0cm 0cm" --scale $scale  $pdforiginal

pdftk O=$pdfood E=$pdfeven cat $(i=1; while [ $i -le $pages ]; do echo O$i E$i; i=$(($i+1)); done) output $pdfout

rm $pdfood $pdfeven

这样我就可以跑步

./split.sh my.pdf 50 1.2

其中50表示调整边距,1.2表示比例。


4

这是Gilles发布的PyPDF代码的变体。无论页面方向是什么,此功能都将起作用:

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


1

基于AskUbuntu 的Benjamin回答,我建议使用称为gscan2pdf的GUI工具。

  1. 将PDF扫描文件导入到gscan2pdf。请注意,非图像PDF文件可能不起作用。扫描很好,所以您不必担心。

    在此处输入图片说明

  2. 可能需要一段时间,具体取决于文档的大小。等到加载为止。

  3. Ctrl + A选择所有页面,然后根据需要旋转(Ctrl + Shift + C)

    在此处输入图片说明

  4. 转到工具>>清理。选择Layout作为double#输出页面= 2

    在此处输入图片说明

  5. OK,并等待,直到作业完成。

    在此处输入图片说明

  6. 保存 PDF文件。做完了


经过测试,由于包含大量图像的复杂pdf文档而失败。
MUY比利时

0

ora 解决方案对我不起作用。主要问题是x5和x6计算。这里必须考虑偏移量,即,如果lowerLeft不为(0,0)

所以这是另一个变体,使用PyPDF2和python进行了其他修改:

import copy
import math
import PyPDF2
import sys
import io 

def split_pages(src, dst):
    src_f = io.open(src, 'r+b')
    dst_f = io.open(dst, 'w+b')

    input = PyPDF2.PdfFileReader(src_f)
    output = PyPDF2.PdfFileWriter()

    for i in range(input.getNumPages()):
        p = input.getPage(i) 
        q = copy.copy(p)
        q.mediaBox = copy.copy(p.mediaBox)

        x1, x2 = p.cropBox.lowerLeft
        x3, x4 = p.cropBox.upperRight        

        x1, x2 = math.floor(x1), math.floor(x2)
        x3, x4 = math.floor(x3), math.floor(x4)

        x5 = math.floor((x3-x1) / 2 + x1)
        x6 = math.floor((x4-x2) / 2 + x2)

        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.lowerLeft = (x1, x6)
            p.mediaBox.upperRight = (x3, x4)

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

if __name__ == "__main__":
    if ( len(sys.argv) != 3 ):
        print ('Usage: python3 double2single.py input.pdf output.pdf')
        sys.exit(1)

    split_pages(sys.argv[1], sys.argv[2])
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.