แบ่งหน้าใน pdf


67

ฉันมีไฟล์ PDF ที่สแกนซึ่งสแกนสองหน้าในหน้าเสมือนหนึ่งหน้า (หน้าในไฟล์ PDF)

ความละเอียดมีคุณภาพดี ปัญหาคือฉันต้องซูมเมื่ออ่านและลากจากซ้ายไปขวา
มีคำสั่ง ( convert,, pdftk... ) หรือสคริปต์ที่สามารถแปลงไฟล์ pdf นี้เป็นหน้าปกติ (หนึ่งหน้าจากหนังสือ = หนึ่งหน้าในไฟล์ pdf)?


1
A แม้ว่าจะไม่ใช่คำตอบที่ถูกโหวตมากที่สุด แต่อันนี้ทำให้ฉันประหลาดใจจริงๆ มันง่ายสั้นเร็วและสง่างาม ฉันคิดว่ามันคุ้มค่าที่จะพูดถึงมันนี่เป็นบางครั้งเราขี้เกียจเกินไปที่จะเลื่อนลงไปที่คำตอบอื่น ๆ ...
Peque

สำหรับเร็กคอร์ดการดำเนินการย้อนกลับ (การรวมหลายเพจ) สามารถรับได้จากบรรทัดคำสั่ง (แทนที่จะเป็น "print to file") ด้วยpdfnupจากpdfjamชุด
Skippy le Grand Gourou

คำตอบ:


46

นี่เป็นสคริปต์ Python ขนาดเล็กที่ใช้ไลบรารี PyPdfซึ่งทำงานได้อย่างเรียบร้อย บันทึกไว้ในสคริปต์ที่เรียกว่า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 ที่สแกน


ในกรณีที่มันมีประโยชน์ต่อไปนี้เป็นคำตอบก่อนหน้าของฉันซึ่งใช้การรวมกันของเครื่องมือสองอย่างบวกกับการแทรกแซงด้วยตนเอง:

  • Pdfjam (อย่างน้อยรุ่น 2.0) ขึ้นอยู่กับแพคเกจpdfpages LaTeX เพื่อครอบตัดหน้า
  • 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 ก็เพียงพอที่จะมีการติดตั้ง PDFLaTeX พร้อมแพ็คเกจ pdfpages (บน Ubuntu: คุณต้องมีtexlive-latex-recommended ติดตั้ง texlive-latex- แนะนำและบางที (บน Ubuntu: แนะนำให้ ติดตั้ง texlive-fonts- แนะนำใช้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 ทำงานได้สมบูรณ์แบบ ฉันเพียงเปลี่ยนมันเล็ก ๆ น้อย ๆและใช้กับงูหลาม conv_pdf.py res.pdf คุณจะเรียกใช้สคริปต์ shebang จาก commandline ได้อย่างไร
xralf

ฉันต้องการลองรุ่นด้วย pdfjam (เนื่องจากการปรับขนาดเล็กน้อย) ด้วย แต่หลังจากการติดตั้งแพคเกจ pdfjam เชลล์ของฉันจะไม่รู้จักpdfjamคำสั่ง
xralf

@xralf: สคริปต์ python ของฉันเพิ่งอ่านจากอินพุตมาตรฐานและเขียนไปยังเอาต์พุตมาตรฐาน รุ่น pdfjam ต้องใช้ pdfjam 2.0; มันเป็นเพียงเสื้อคลุมเล็ก ๆ รอบ ๆ pdfpages และฉันได้เพิ่มบิตของ LaTeX ที่สร้างขึ้นเพื่อให้คุณสามารถใช้งานได้โดยตรง ปัญหาการปรับสเกลอาจแก้ไขได้ด้วย pypdf อาจเป็นปัญหาขนาดหน้ากระดาษ (ฉันอาจหรืออาจไม่สามารถช่วยได้หากคุณให้รายละเอียดเพิ่มเติมเกี่ยวกับสิ่งที่เกิดขึ้นและโดยเฉพาะอย่างยิ่งขนาดหน้ากระดาษที่เกี่ยวข้อง)
Gilles

ขอบคุณความแตกต่างอยู่ในการแก้ไขที่แย่กว่าเล็กน้อยมาก แต่ก็ไม่สำคัญ ฉันจะหันกลับไปหามันเมื่อฉันรู้มากขึ้นเกี่ยวกับลาเท็กซ์ (มันซับซ้อนเกินไปสำหรับฉันตอนนี้และวิธีแก้ปัญหานั้นดีมากสำหรับ PyPdf)
xralf

1
@Gilles Versy สคริปต์ที่มีประโยชน์ ฉันคาดว่าจะเห็นบางอย่างเช่นนี้ใน pdfjam, pdftk อย่างไรก็ตามบางคนอาจต้องการแก้ไขเพื่อแยกหน้ามากกว่าแกนอื่น ๆ และใช้การเรียงลำดับที่แตกต่างกัน เป็นไปได้ที่จะมีการเปลี่ยนแปลงไม่กี่บรรทัดและใช้q.mediaBox.lowerRight = (w, h/2)
ony

52

เพียงเพิ่มเพราะฉันมีปัญหากับสคริปต์หลาม (และวิธีแก้ปัญหาอื่น ๆ ): สำหรับฉันmutoolทำงานได้ดี มันเป็นเรื่องเล็กและเรียบง่ายมาพร้อมกับmupdfเครื่องอ่านที่หรูหรา ดังนั้นคุณสามารถลอง:

mutool poster -y 2 input.pdf output.pdf

สำหรับการแยกแนวนอนแทนที่ด้วยy xและแน่นอนว่าคุณสามารถรวมสองสิ่งนี้เพื่อแก้ปัญหาที่ซับซ้อนมากขึ้น

มีความสุขจริงๆที่ได้พบสิ่งนี้ (หลังจากหลายปีของการใช้ mupdf ทุกวัน :)

mutoolมาพร้อมกับ mupdf เริ่มต้นจากรุ่น 1.4: http://www.mupdf.com/news


การติดตั้งmupdfและmutoolจากแหล่งที่มา:

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

2
ใช่ฉันก็พอใจกับความเร็วจริงๆ
martz

3
อันนี้ง่ายที่สุดและดีกว่า mutoolถูกสร้างขึ้นมาเพื่อสิ่งนี้ นอกจากนี้ระวังของผมคิดว่าในกรณีส่วนใหญ่สิ่งที่คุณต้องการคือ-y -x
fiatjaf

2
ยูทิลิตี้นี้เร็วมาก แต่ฉันมีปัญหากับการเรียงลำดับหน้า คำสั่งจัดสรรหน้าที่ถูกต้องที่ตำแหน่งแรกและหน้าซ้ายในหน้าที่สอง ใครสามารถช่วยฉันด้วยปัญหานี้
garciparedes


16

Imagemagick สามารถทำได้ในขั้นตอนเดียว:

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

1
ขอบคุณ ถ้าฉันเพิ่ม-density 400พารามิเตอร์` มันมีคุณภาพที่ดียิ่งขึ้น
xralf

11
ดูเหมือนว่าการแปลงใช้แรสเตอร์เป็นรูปแบบกลาง ซึ่งทำให้มองดูไม่ชัดแม้ PDF ต้นฉบับจะมีวัตถุเวกเตอร์
ony

ไม่มีใครรู้วิธีการทำเช่นนี้โดยไม่ต้อง rasterizing เนื้อหาของหน้าตลอดทาง ... หรืออย่างน้อยก็เพื่อตั้งความละเอียดสูงขึ้น?
Tomislav Nakic-Alfirevic

ข้อความที่แสดงผลนี้เป็นภาพและสร้างไฟล์ PDF จากภาพ อาจดีสำหรับรูป แต่ไม่มีประโยชน์สำหรับการแยกข้อความ
andrej

6

คำสั่งแปลงของ ImageMagick สามารถช่วยให้คุณครอบตัดไฟล์เป็น 2 ส่วน ดูhttp://www.imagemagick.org/Usage/crop/

ถ้าฉันเป็นคุณฉันจะเขียนสคริปต์ (เชลล์) เช่นนี้:

  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 แปลงไฟล์ให้เป็นรูปแบบเดิมหรือ และคุณควรอธิบายว่าส่วนสุดท้ายของแบบอินไลน์โดยเฉพาะอย่างยิ่งเพื่อประโยชน์ของผู้ที่ไม่ใช่ฟรองโคโฟนในกลุ่มผู้ชม
Gilles

เพราะคุณไม่จำเป็นต้องเข้าใจภาษาฝรั่งเศส มันแสดงให้เห็นว่าคุณสามารถใช้การแปลง, pdftk หรือ ghostscript (gs) ของ ImageMagick เพียงอย่างเดียวเพื่อให้บรรลุเป้าหมายนี้ได้อย่างไร ฉันชอบใช้ pdftk "Rastering" ไม่สำคัญเนื่องจากเป็นเอกสารที่สแกน
tiktak

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

นี่คือรูปแบบของรหัส PyPDF ที่โพสต์โดย Gilles ฟังก์ชั่นนี้จะทำงานไม่ว่าการวางหน้าจะเป็นอย่างไร

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

2

ทางออกที่ดีที่สุดคือ mutool ดูด้านบน:

sudo apt install mupdf-tools pdftk

แยก:

mutool poster -y 2 input.pdf output.pdf

แต่คุณจะต้องหมุนหน้าไปทางซ้าย:

pdftk output.pdf cat 1-endleft output rotated.pdf

ยังไม่ทับซ้อน ...
MUY เบลเยี่ยม

1

ขึ้นอยู่กับคำตอบโดยเบนจามินที่ AskUbuntu ผมจะแนะนำให้ใช้เครื่องมือที่เรียกว่า GUI gscan2pdf

  1. นำเข้าไฟล์สแกน PDF ไปยัง gscan2pdf โปรดทราบว่าไฟล์ PDF ที่ไม่ใช่รูปภาพอาจไม่ทำงาน สแกนได้ดีดังนั้นคุณไม่ต้องกังวล

    ป้อนคำอธิบายรูปภาพที่นี่

  2. อาจใช้เวลาสักครู่ขึ้นอยู่กับขนาดของเอกสาร รอจนกว่าจะโหลดขึ้น

  3. กดCtrl + Aเพื่อเลือกหน้าทั้งหมดจากนั้นหมุน (Ctrl + Shift + C)หากจำเป็น

    ป้อนคำอธิบายรูปภาพที่นี่

  4. ไปที่Tools >> ทำความสะอาด เลือกเค้าโครงเป็นคู่และหน้า # output = 2

    ป้อนคำอธิบายรูปภาพที่นี่

  5. กดOKและรอจนกว่างานจะเสร็จ

    ป้อนคำอธิบายรูปภาพที่นี่

  6. บันทึกไฟล์ PDF เสร็จสิ้น


ทดสอบแล้วล้มเหลวด้วยเอกสาร PDF ที่ซับซ้อนพร้อมด้วยรูปภาพขนาดใหญ่
MUY เบลเยี่ยม

0

วิธีการแก้ปัญหาของโมราไม่ได้ผลสำหรับฉัน ปัญหาหลักคือการคำนวณ x5 และ x6 ที่นี่จะต้องมีการพิจารณาชดเชยเช่นถ้าด้านล่างซ้ายไม่ได้อยู่ที่ (0,0)

ดังนั้นนี่คือรูปแบบอื่นที่มีการดัดแปลงเพิ่มเติมเพื่อใช้ PyPDF2 และ python 3:

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])
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.