Membagi halaman dalam pdf

67

Saya memiliki file pdf yang dipindai yang telah memindai dua halaman pada satu halaman virtual (halaman dalam file pdf).

Resolusi dengan kualitas yang baik. Masalahnya adalah saya harus memperbesar saat membaca dan menarik dari kiri ke kanan.
Apakah ada perintah ( convert,, pdftk...) atau skrip yang dapat mengkonversi file pdf ini dengan halaman normal (satu halaman dari buku = satu halaman dalam file pdf)?

xralf
sumber
1
Meskipun ini bukan jawaban yang paling bagus, jawaban ini benar-benar mengejutkan saya. Sederhana, pendek, cepat, dan elegan. Saya pikir itu layak untuk disebutkan di sini, karena kadang-kadang kita terlalu malas untuk menggulir ke bawah ke jawaban lain ...
Peque
Untuk catatan, operasi terbalik (menggabungkan beberapa halaman) dapat diperoleh dari baris perintah (daripada "mencetak ke file") dengan pdfnup, dari pdfjamsuite.
Skippy le Grand Gourou

Jawaban:

46

Berikut skrip Python kecil menggunakan pustaka PyPdf yang melakukan pekerjaan dengan rapi. Simpan dalam skrip bernama un2up(atau apa pun yang Anda suka), jadikan itu executable ( chmod +x un2up), dan jalankan sebagai filter ( 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)

Abaikan peringatan penghentian apa pun; hanya pengelola PyPdf yang perlu peduli dengan hal itu.

Jika input berorientasi dengan cara yang tidak biasa, Anda mungkin perlu menggunakan koordinat yang berbeda saat memotong halaman. Lihat Mengapa kode saya tidak membagi setiap halaman dengan benar dalam pdf yang dipindai?


Kalau-kalau berguna, inilah jawaban saya sebelumnya yang menggunakan kombinasi dua alat ditambah beberapa intervensi manual:

  • Pdfjam (setidaknya versi 2.0), berdasarkan paket pdfpages LaTeX, untuk memotong halaman;
  • Pdftk , untuk menyatukan kembali bagian kiri dan kanan.

Kedua alat diperlukan karena sejauh yang saya tahu pdfpages tidak dapat menerapkan dua transformasi berbeda ke halaman yang sama dalam satu aliran. Dalam panggilan ke pdftk, ganti 42 dengan jumlah halaman dalam dokumen input ( 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

Jika Anda tidak memiliki pdfjam 2.0, cukup memiliki instalasi PDFLaTeX dengan paket pdfpages (di Ubuntu: Anda memerlukan texlive-latex-recommended Instal texlive-latex-recommended dan mungkin (di Ubuntu: texlive-fonts-recommended Instal texlive-font-direkomendasikan ), dan gunakan driver berikut ini file 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}

Kemudian jalankan perintah berikut, ganti 42 dengan jumlah halaman dalam file input (yang harus dipanggil 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
Gilles 'SANGAT berhenti menjadi jahat'
sumber
Pustaka PyPdf bekerja dengan sempurna. Saya hanya mengubahnya sedikit dan menjalankannya dengan python conv_pdf.py res.pdf . Bagaimana Anda menjalankan skrip shebang dari commandline?
xralf
Saya ingin mencoba versi dengan pdfjam (karena skala kecil) juga, tetapi setelah instalasi paket pdfjam shell saya tidak akan mengenali pdfjamperintah.
xralf
@ xralf: Skrip python saya baru saja membaca dari input standar dan menulis ke output standar. Versi pdfjam membutuhkan pdfjam 2.0; itu hanya pembungkus kecil di sekitar pdfpages, dan saya telah menambahkan sedikit LaTeX yang dihasilkannya sehingga Anda dapat menggunakannya secara langsung. Masalah penskalaan mungkin dapat dipecahkan dengan pypdf, ini bisa berupa masalah ukuran halaman (saya mungkin atau mungkin tidak dapat membantu jika Anda memberikan rincian lebih lanjut tentang apa yang terjadi dan terutama ukuran halaman yang terlibat).
Gilles 'SO- stop being evil'
Terima kasih, perbedaannya ada pada resolusi yang sedikit lebih buruk, tetapi ini tidak masalah. Saya akan kembali ke sana ketika saya tahu lebih banyak tentang Lateks (terlalu rumit untuk saya sekarang dan solusinya sangat bagus dengan PyPdf).
xralf
1
@Gilles Versy skrip yang bermanfaat. Saya berharap melihat sesuatu seperti itu di pdfjam, pdftk. Bagaimanapun, beberapa orang mungkin menginginkan beberapa modifikasi untuk membagi halaman di atas sumbu lain dan menggunakan urutan berbeda. Hal ini dimungkinkan dengan mengganti beberapa baris dan menggunakanq.mediaBox.lowerRight = (w, h/2)
ony
52

Hanya tambahan karena saya punya masalah dengan skrip python (dan beberapa solusi lainnya): bagi saya mutoolbekerja dengan baik. Ini tambahan sederhana dan kecil yang dikirimkan bersama mupdfpembaca yang elegan . Jadi, Anda dapat mencoba:

mutool poster -y 2 input.pdf output.pdf

Untuk pemisahan horizontal, ganti ydengan x. Dan Anda tentu saja dapat menggabungkan keduanya untuk solusi yang lebih kompleks.

Sangat senang telah menemukan ini (setelah bertahun-tahun penggunaan mupdf setiap hari :)

mutoolhadir dengan mupdf mulai dari versi 1.4: http://www.mupdf.com/news


Menginstal mupdfdan mutooldari sumber:

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

Atau buka halaman unduhan untuk menemukan versi yang lebih baru.

martz
sumber
3
Saya punya djvu ... Saya mengubahnya menjadi postscript (cukup cepat), kemudian menjadi pdf (kura-kura lambat) - dan akhirnya mutool memotongnya begitu cepat saya pikir itu tidak berhasil - itu!
Julien Puydt
2
ya, saya juga sangat senang dengan kecepatannya.
martz
3
Yang ini paling mudah dan lebih baik. mutooldibuat untuk ini. Juga, waspadalah -y, saya pikir dalam banyak kasus apa yang Anda inginkan -x.
fiatjaf
2
Utilitas ini sangat cepat, namun saya memiliki masalah dengan urutan halaman. Perintah mengalokasikan halaman kanan di posisi pertama dan halaman kiri di yang kedua. Adakah yang bisa membantu saya dengan masalah ini?
garciparedes
16

Imagemagick dapat melakukannya dalam satu langkah:

$ convert in.pdf -crop 50%x0 +repage out.pdf
tomas
sumber
1
Terima kasih. Jika saya menambahkan -density 400parameter` bahkan memiliki kualitas yang lebih baik.
xralf
11
Sepertinya konversi menggunakan raster sebagai format perantara. Itu menyebabkan tampilan kabur bahkan ketika PDF asli berisi objek vektor.
ony
Adakah yang tahu cara melakukan ini tanpa meraster konten halaman sepanjang jalan ... atau setidaknya untuk menetapkan resolusi yang lebih tinggi?
Tomislav Nakic-Alfirevic
ini membuat teks menjadi gambar dan membuat pdf dari gambar. Mungkin bagus untuk foto tetapi tidak berguna untuk ekstraksi teks.
andrej
6

Perintah Konversi ImageMagick dapat membantu Anda memotong file Anda menjadi 2 bagian. Lihat http://www.imagemagick.org/Usage/crop/

Jika saya jadi Anda, saya akan menulis skrip (shell) seperti ini:

  1. Membagi file Anda dengan pdfsam : 1 halaman = 1 file pada disk (Format tidak masalah. Pilih satu yang ImageMagick tahu. Saya hanya mengambil PS atau PDF.
  2. Untuk setiap halaman, pangkas paruh pertama dan masukkan ke file bernama $ {PageNumber} A

  3. Pangkas babak kedua dan masukkan ke file bernama $ {PageNumber} B.

    Anda mendapatkan 1A.pdf, 1B.pdf, 2A.pdf, 2B.pdf, dll.

  4. Sekarang, kumpulkan ini lagi dalam PDF baru. Ada banyak metode untuk melakukan ini.
tiktak
sumber
1
Tidak akan menggunakan ImageMagick meraster file? Dan Anda harus menjelaskan bagian terakhir itu sebaris, terutama untuk kepentingan non-francophones di antara hadirin.
Gilles 'SANGAT berhenti menjadi jahat'
Karena Anda tidak perlu mengerti bahasa Prancis. Itu hanya menunjukkan bagaimana Anda dapat menggunakan konversi ImageMagick, pdftk, atau ghostscript (gs) sendirian untuk mencapai tujuan ini. Saya suka menggunakan pdftk. "Rastering" tidak masalah karena ini adalah dokumen yang dipindai.
tiktak
6

Berdasarkan jawaban dari Gilles dan bagaimana menemukan jumlah halaman PDF yang saya tulis

#!/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

Jadi saya bisa lari

./split.sh my.pdf 50 1.2

di mana 50 untuk menyesuaikan margin dan 1,2 untuk skala.

Anton Bessonov
sumber
4

Berikut variasi kode PyPDF yang diposting oleh Gilles. Fungsi ini akan berfungsi apa pun orientasinya:

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()
moraes
sumber
2

Solusi terbaik adalah mutool lihat di atas:

sudo apt install mupdf-tools pdftk

perpisahan:

mutool poster -y 2 input.pdf output.pdf

tetapi kemudian Anda perlu memutar halaman yang tersisa:

pdftk output.pdf cat 1-endleft output rotated.pdf
Eduard Florinescu
sumber
Masih tidak tumpang tindih ...
MUY Belgium
1

Berdasarkan jawaban oleh Benjamin di AskUbuntu, saya akan merekomendasikan menggunakan alat GUI yang disebut gscan2pdf .

  1. Impor file pindai PDF ke gscan2pdf. Perhatikan bahwa file PDF non-gambar mungkin tidak berfungsi. Pemindaian baik-baik saja, jadi Anda tidak perlu khawatir.

    masukkan deskripsi gambar di sini

  2. Mungkin butuh beberapa saat tergantung pada ukuran dokumen. Tunggu sampai itu memuat.

  3. Tekan Ctrl + A untuk memilih semua halaman lalu putar (Ctrl + Shift + C) jika perlu.

    masukkan deskripsi gambar di sini

  4. Pergi ke Alat >> Bersihkan . Pilih Tata Letak sebagai dua kali lipat dan # halaman keluaran = 2 .

    masukkan deskripsi gambar di sini

  5. Tekan OK dan tunggu sampai pekerjaan selesai.

    masukkan deskripsi gambar di sini

  6. Simpan file PDF. Selesai.

Nanashi No Gombe
sumber
Diuji, gagal dengan dokumen pdf kompleks dengan sejumlah besar gambar.
MUY Belgium
0

solusi moraes tidak bekerja untuk saya. Masalah utama adalah perhitungan x5 dan x6. Di sini offset harus dipertimbangkan, yaitu jika lowerLeft tidak di (0,0)

Jadi di sini adalah variasi lain, dengan adaptasi tambahan untuk menggunakan PyPDF2 dan 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])
vbar
sumber