Memotong halaman PDF menjadi beberapa halaman [ditutup]


16

Saya punya banyak file PDF yang berisi dua halaman "asli" untuk satu halaman PDF; Saya ingin memotong ini menjadi dua dan menempatkan masing-masing setengah pada halaman terpisah. Pada dasarnya, saya butuh sesuatu yang melakukan kebalikan dari pdfnup(atau psnup). Bagaimana hal ini bisa dicapai?

Platform adalah Linux, open source lebih disukai; karena saya punya banyak tumpukan ini untuk melakukan sesuatu yang dapat dituliskan (sebagai lawan GUI) akan menyenangkan, jadi saya bisa memberikan daftar mereka dan mengunyahnya.

Skrip yang sudah ada sebelumnya bukan satu-satunya pilihan; jika ada kode sampel untuk memanipulasi PDF dengan cara yang mirip dengan perpustakaan pihak ketiga, saya mungkin bisa meretasnya untuk melakukan apa yang saya inginkan.


Jawaban:


22

Anda dapat menyelesaikan ini dengan bantuan Ghostscript. pdftksendiri tidak bisa melakukan itu (sejauh pengetahuan saya). Saya akan memberi Anda langkah-langkah commandline untuk melakukan ini secara manual. Ini akan mudah untuk skrip ini sebagai prosedur, juga dengan parameter berbeda untuk ukuran halaman dan nomor halaman. Tetapi Anda mengatakan bahwa Anda dapat melakukannya sendiri ;-)

Cara mengatasi ini dengan bantuan Ghostscript ...

... dan untuk bersenang-senang, saya baru-baru ini melakukannya bukan dengan file input yang menampilkan halaman "ganda", tetapi satu dengan "treble-up". Anda dapat membaca jawabannya untuk kasus ini di sini .

Kasing Anda bahkan lebih sederhana. Anda sepertinya memiliki sesuatu yang mirip dengan ini:

+------------+------------+   ^
|            |            |   |
|      1     |      2     |   |
|            |            | 595 pt
|            |            |   |
|            |            |   |
|            |            |   |
+------------+------------+   v
             ^
            fold
             v
+------------+------------+   ^
|            |            |   |
|      3     |      4     |   |
|            |            | 595 pt
|            |            |   |
|            |            |   |
|            |            |   |
+------------+------------+   v
<---------- 842 pt -------->

Anda ingin membuat 1 PDF dengan 4 halaman, masing-masing memiliki ukuran 421 pt x 595 pt.

Langkah pertama

Pertama mari kita ekstrak bagian kiri dari masing-masing halaman input:

gs \
    -o left-sections.pdf \
    -sDEVICE=pdfwrite \
    -g4210x5950 \
    -c "<</PageOffset [0 0]>> setpagedevice" \
    -f double-page-input.pdf

Apa yang dilakukan parameter ini?

Pertama, ketahuilah bahwa dalam PDF 1 inci == 72 poin . Maka sisanya adalah:

  • -o ...............:Nama file keluaran. Secara implisit juga menggunakan -dBATCH -dNOPAUSE -dSAFER.
  • -sDEVICE=pdfwrite : kami ingin PDF sebagai format output.
  • -g................:mengatur ukuran media keluaran dalam piksel. Resolusi default pdfwrite adalah 720 dpi. Maka kalikan dengan 10 untuk mendapatkan kecocokan untuk PageOffset.
  • -c "..............:meminta Ghostscript untuk memproses cuplikan kode PostScript yang diberikan tepat sebelum file input utama (yang perlu diikuti -f).
  • <</PageOffset ....:mengatur pemindahan gambar halaman pada media. (Tentu saja, untuk halaman kiri pergantian oleh [0 0]tidak memiliki efek nyata.)
  • -f ...............: memproses file input ini.

Hasil apa yang dicapai perintah terakhir?

Yang ini:

Output file: left-sections.pdf, page 1
+------------+  ^
|            |  |
|     1      |  |
|            |595 pt
|            |  |
|            |  |
|            |  |
+------------+  v

Output file: left-sections.pdf, page 2
+------------+  ^
|            |  |
|     3      |  |
|            |595 pt
|            |  |
|            |  |
|            |  |
+------------+  v
<-- 421 pt -->

Tahap kedua

Selanjutnya, bagian yang tepat:

gs \
    -o right-sections.pdf \
    -sDEVICE=pdfwrite \
    -g4210x5950 \
    -c "<</PageOffset [-421 0]>> setpagedevice" \
    -f double-page-input.pdf

Perhatikan offset negatif karena kami menggeser halaman ke kiri sambil menjaga area tampilan tetap.

Hasil:

Output file: right-sections.pdf, page 1
+------------+  ^
|            |  |
|     2      |  |
|            |595 pt
|            |  |
|            |  |
|            |  |
+------------+  v

Output file: right-sections.pdf, page 2
+------------+  ^
|            |  |
|     4      |  |
|            |595 pt
|            |  |
|            |  |
|            |  |
+------------+  v
<-- 421 pt -->

Langkah terakhir

Sekarang kita menggabungkan halaman menjadi satu file. Kita bisa melakukannya dengan ghostscript juga, tetapi kita akan menggunakannya pdftksebagai gantinya, karena lebih cepat untuk pekerjaan ini:

pdftk \
  A=right-sections.pdf \
  B=left-sections.pdf \
  shuffle \
  output single-pages-output.pdf
  verbose

Selesai Inilah hasil yang diinginkan. 4 halaman berbeda, berukuran 421x595 pt.

Hasil:

+------------+ +------------+ +------------+ +------------+   ^
|            | |            | |            | |            |   |
|     1      | |     2      | |     3      | |     4      |   |
|            | |            | |            | |            |5595 pt
|            | |            | |            | |            |   |
|            | |            | |            | |            |   |
|            | |            | |            | |            |   |
+------------+ +------------+ +------------+ +------------+   v
<-- 421 pt --> <-- 421 pt --> <-- 421 pt --> <-- 421 pt -->

@ Tidak Diketahui: Terima kasih untuk downvoting! Apakah Anda mau menulis komentar yang menunjukkan beberapa alasan untuk ini?
Kurt Pfeifle

+1 untuk penggunaan seni ASCII yang luar biasa, dan instruksi yang sangat jelas. Hanya karena saya seorang CLI n00b, itu lolos dari garis sehingga lebih mudah dibaca, kan?
Journeyman Geek

@ Mullull: terima kasih telah memperbaiki kesalahan ketik ( 421-> -421). ;-)
Kurt Pfeifle

6

Ada alat pdfposter yang dapat digunakan untuk membuat PDF dengan beberapa halaman untuk satu halaman input (ubin atau memotong halaman). Ini mirip dengan alat poster, yang melakukan hal yang sama untuk file PostScript.


pdfposter tidak menangani pencetakan konten yang tumpang tindih di bagian tepinya, untuk memudahkan pemasangan poster. Ini skrip Perl, jadi cukup mudah untuk ditambahkan.
Matthias Urlichs

3

Jadi, setelah pencarian yang lebih banyak (tampaknya "halaman memotong PDF" adalah pencarian yang jauh lebih baik), saya menemukan skrip kecil yang disebut unpnupyang menggunakan poster, konversi PDF / PS, dan pdftkuntuk melakukan apa yang saya butuhkan. Ini agak jauh, tetapi jauh lebih unggul daripada metode lain yang saya temukan (seperti menggunakan imagemagick) karena tidak merasterisasi halaman sebelum meludahkannya.

Kalau-kalau mobileread hilang karena suatu alasan, inti skrip (dilisensikan di bawah GPLv2 atau yang lebih baru oleh Harald Hackenberg <hackenberggmx.at>) adalah sebagai berikut:

pdftk "$1" burst
for file in pg*.pdf;
do
    pdftops -eps $file
    poster -v -pA4 -mA5 -c0% `basename $file .pdf`.eps > `basename $file .pdf`.tps
    epstopdf `basename $file .pdf`.tps
done
pdftk pg*.pdf cat output ../`basename $1 .pdf`_unpnuped.pdf

1
Harus menyukainya ketika orang menjawab pertanyaan mereka sendiri. Namun, jika Anda perlu melakukannya dengan GUI, terutama jika ukuran halamannya tidak genap atau Anda ingin memotong setiap sisi lebih jauh, lihat Briss: briss.sourceforge.net
frabjous

Anda harus dapat melakukan apa yang Anda inginkan dengan PDFTK dengan sendirinya, tanpa semua konversi.
CarlF

@CarlF: Saya pikir itu mungkin, tapi saya tidak bisa melihat apa pun di halaman manual PDFTK untuk memanipulasi konten halaman. Punya petunjuk untuk saya?
womble

@frabjous: Apa yang salah dengan menjawab pertanyaan Anda sendiri?
Kurt Pfeifle

1
@ womble: konversi Anda dilakukan melalui PS / EPS. Hal ini pasti akan menyebabkan penurunan kualitas (font yang disematkan, transparansi, dll.). Saran saya menghindari PDF => EPS => PDFrute yang berisiko dan menempuh PDF => PDF => PDFjalan yang lebih aman .
Kurt Pfeifle

2

Saya menemukan jawaban oleh Kurt Pfeifle sangat membantu untuk situasi saya yang serupa. Saya pikir saya mungkin berbagi modifikasi solusi saya dengan yang lain ...

Saya juga memiliki pindaian PDF yang memiliki 2 halaman di setiap lembar. Itu adalah scan 11 x 8,5 (inci) dari buklet yang dijahit pelana yang dibiarkan dijepit ketika awalnya dipindai, jadi: PDF halaman 1 = sampul belakang dan depan; Halaman PDF 2 = halaman 2 dan 3, dll. Ini berbunyi di layar baik tetapi Anda tidak dapat mencetaknya dan kemudian menjepretnya untuk membuat lebih banyak salinan buklet.

Saya harus bisa mencetak ini pada mesin fotokopi duplex; yaitu mengubahnya KEMBALI ke PDF "dipaksakan", siap untuk dicetak. Jadi dengan menggunakan solusi Kurt, saya membuat (ahem) ini "satu baris" untuk mengubahnya kembali menjadi setengah halaman, dalam urutan halaman yang benar lagi. Ini akan bekerja untuk semua HEIGHT dan WIDTH, dan juga untuk sejumlah halaman. Dalam kasus saya, saya memiliki buklet 40 halaman (20 halaman yang dipindai dalam PDF.)

HEIGHT=8.5 WIDTH=11 ORIG_FILE_PATH="original.pdf" \
count=$(set -xe; \
gs -o left.pdf -sDEVICE=pdfwrite \
-g$(perl -e "print(($WIDTH / 2) * 720)")x$(perl -e "print($HEIGHT * 720)") \
-c "<</PageOffset [0  0]>> setpagedevice" \
-f "$ORIG_FILE_PATH" >/dev/null; \
gs -o right.pdf -sDEVICE=pdfwrite \
-g$(perl -e "print(($WIDTH / 2) * 720)")x$(perl -e "print($HEIGHT * 720)") \
-c "<</PageOffset [-$(perl -e "print(($WIDTH / 2) * 72)")  0]>> setpagedevice" \
-f "$ORIG_FILE_PATH" | grep Page | wc -l ); \
echo '>>>>>' Re-ordering $count pages...; \
(set -xe; pdftk A=right.pdf B=left.pdf cat \
A1 `set +xe; for x in $(seq 2 $count); do echo B$x A$x; done` B1 \
output ordered.pdf); \
echo "Done. See ordered.pdf"

Anda hanya perlu mengubah beberapa parameter pertama dalam perintah ini untuk menentukan HEIGHT dan WIDTH dan ORIG_FILE_PATH. Sisa dari perintah menghitung berbagai ukuran dan memanggil gs dua kali, lalu pdftk. Bahkan akan menghitung halaman dalam pemindaian Anda dan kemudian menghasilkan spesifikasi sortir yang benar (untuk skenario yang saya berikan).

Ini menampilkan beberapa kemajuan tentang apa yang dilakukannya, yang akan terlihat seperti ini:

+++ perl -e 'print((11 / 2) * 720)'
+++ perl -e 'print(8.5 * 720)'
++ gs -o left.pdf -sDEVICE=pdfwrite -g3960x6120 -c '<</PageOffset [0  0]>> setpagedevice' -f original.pdf
++ wc -l
++ grep Page
+++ perl -e 'print((11 / 2) * 720)'
+++ perl -e 'print(8.5 * 720)'
+++ perl -e 'print((11 / 2) * 72)'
++ gs -o right.pdf -sDEVICE=pdfwrite -g3960x6120 -c '<</PageOffset [-396  0]>> setpagedevice' -f original.pdf
>>>>> Re-ordering 20 pages...
++ set +xe
+ pdftk A=right.pdf B=left.pdf cat A1 B2 A2 B3 A3 B4 A4 B5 A5 B6 A6 B7 A7 B8 A8 B9 A9 B10 A10 B11 A11 B12 A12 B13 A13 B14 A14 B15 A15 B16 A16 B17 A17 B18 A18 B19 A19 B20 A20 B1 output ordered.pdf
Done. See ordered.pdf

Selanjutnya, untuk mendapatkan pembebanan halaman yang Anda butuhkan untuk buklet tercetak, Anda cukup "mencetak" dipesan. "tool (dalam kasus saya, saya menggunakan Booklet Buat Christoph Vogelbusch untuk Mac dari http://download.cnet.com/Create-Booklet/3000-2088_4-86349.html ).

PDF yang dihasilkan sekarang akan kembali ke ukuran halaman asli 11 x 8,5 dengan 2 halaman per lembar, tetapi pemesanan akan sedemikian rupa sehingga Anda dapat mencetaknya dua sisi, penjilidan tepi pendek, dan voila! Anda akan memiliki hasil cetak yang dapat Anda fotokopi dan lipat dan sadel-menjahit, mereproduksi buklet asli tanpa pernah membongkar (atau bahkan harus melihat) yang asli.

Semoga ini bisa membantu seseorang!

-c


1

Berdasarkan jawaban piptas di atas:

Di windows, untuk memisahkan PDF ukuran-huruf dengan gambar sampul tunggal di awal, berikut ini bekerja sangat baik untuk saya (perhatikan penggunaan [-612 0] pada langkah kedua, nilai positif membuat halaman kosong karena mendorong cara yang salah .)

gswin32c -o left-sections.pdf -sDEVICE=pdfwrite -dFirstPage=2 -g6120x7920 -c "<</PageOffset [0 0]>> setpagedevice" -f input.pdf

Perhatikan penggunaan -dFirstPage=2yang memerintahkan gs untuk mulai memproses pada halaman 2.

gswin32c -o right-sections.pdf -sDEVICE=pdfwrite -dFirstPage=2 -g6120x7920 -c "<</PageOffset [-612 0]>> setpagedevice" -f input.pdf

Ini menciptakan bagian-kanan.pdf dengan cara yang sama. Dan sekarang gambar sampul:

gswin32c -o cover.pdf -sDEVICE=pdfwrite -dLastPage=1 -g6120x7920 -c "<</PageOffset [0 0]>> setpagedevice" -f input.pdf

Selanjutnya, karena saya tidak ingin bergabung dengan pdftk menggunakan input halaman manual, saya membagi bagian kiri dan kanan menjadi PDF terpisah di direktori baru.

mkdir input_file
copy cover.pdf input_file\0000.pdf
pdftk left-sections.pdf burst output input_file\%04d_A.pdf
pdftk right-sections.pdf burst output input_file\%04d_B.pdf

Lalu saya bergabung dengan PDF di direktori itu, secara alfabet (dan untungnya itu berarti mereka diurutkan dalam urutan yang benar!) Dan saya juga menjalankan hasilnya melalui ghostscript lagi untuk memperbaiki "Peringatan: Nomor generasi di luar kisaran 0,65535, dengan asumsi 0. " kesalahan yang dihasilkan oleh pdftk yang ghostscript disebut "itext-paulo-155 (itextpdf.sf.net-lawagie.com)" - itu juga terjadi memotong ukuran file menjadi setengah dalam penggunaan saya. Dengan aslinya 4,5MB, hasil pdftk adalah 6,7MB dan pemrosesan ulang gswin32c menguranginya menjadi 3,2 MB.

pdftk input_file\*.pdf cat output input_temp.pdf
gswin32c -o final_output.pdf -sDEVICE=pdfwrite -f input_temp.pdf

Dan kita selesai! Jangan ragu untuk menghapus folder input_file, cover.pdf, input_temp.pdf, right_sections.pdf dan left_sections.pdf. ;-)


1

jika Anda hanya perlu menampilkan pdf sisi kiri semua dalam satu dokumen, dan pdf sisi kanan semua dalam satu dokumen, maka skrip berikut berdasarkan jawaban Kurt Pfeifle akan melakukan trik (berfungsi untuk ketinggian berapa pun dan lebar):

$ cat split.sh
#!/bin/bash                                                                     

dims=$(pdfinfo "$1" | grep -i "page size:" | cut -d ":" -f2)                    
width=$(echo "$dims" | cut -d " " -f7)                                          
height=$(echo "$dims" | cut -d " " -f9)                                         
half_width=$(echo "$width * 0.5" | bc -l | cut -d "." -f1)                      
half_widthtt=$(echo "$width * 5" | bc -l | cut -d "." -f1)                      
heighttt=$(echo "$height * 10" | bc -l | cut -d "." -f1)                        

echo "pdf $1 has height $height and width $width"                               

gs -o "left-$1" -sDEVICE=pdfwrite -g"$half_widthtt"x"$heighttt" -c "<</PageOffset [0 0]>> setpagedevice" -f "$1"
gs -o "right-$1" -sDEVICE=pdfwrite -g"$half_widthtt"x"$heighttt" -c "<</PageOffset [-$half_width 0]>> setpagedevice" -f "$1"

kemudian jalankan seperti ini:

$ ./split.sh thepdftosplit.pdf
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.