สับหน้าของ PDF ลงในหลาย ๆ หน้า [ปิด]


16

ฉันมีไฟล์ PDF มากมายที่มีหน้า "ของจริง" สองหน้าไปยังหน้า PDF หน้าเดียว ฉันต้องการที่จะตัดครึ่งเหล่านี้และวางแต่ละครึ่งในหน้าแยก โดยพื้นฐานแล้วฉันต้องการสิ่งที่ตรงข้ามกับpdfnup(หรือpsnup) ความสำเร็จนี้จะสำเร็จได้อย่างไร

แพลตฟอร์มคือ Linux เป็นโอเพ่นซอร์สที่ต้องการ ในขณะที่ฉันมีจำนวนมากของสิ่งเหล่านี้ที่จะทำสิ่งที่สามารถเขียนสคริปต์ (ตรงข้ามกับ GUI) จะดีดังนั้นฉันจึงสามารถให้รายชื่อพวกเขาและให้มันเคี้ยว

สคริปต์ที่มีอยู่ก่อนไม่ใช่ตัวเลือกเดียวเช่นกัน หากมีโค้ดตัวอย่างเพื่อจัดการไฟล์ PDF ในลักษณะที่คล้ายกันกับห้องสมุดบุคคลที่สามฉันอาจแฮ็คข้อมูลดังกล่าวเพื่อทำสิ่งที่ฉันต้องการ


คำตอบ:


22

คุณสามารถแก้ปัญหานี้ได้ด้วยความช่วยเหลือของ Ghostscript pdftkเพียงอย่างเดียวไม่สามารถทำเช่นนั้น (เพื่อความรู้ของฉัน) ฉันจะให้ขั้นตอน commandline ให้คุณทำด้วยตนเอง มันจะง่ายต่อการสคริปต์นี้เป็นขั้นตอนยังมีพารามิเตอร์ที่แตกต่างกันสำหรับขนาดหน้าและหมายเลขหน้า แต่คุณบอกว่าคุณสามารถทำได้เอง ;-)

วิธีแก้ปัญหานี้ด้วยความช่วยเหลือของ Ghostscript ...

... และเพื่อความสนุกของมันฉันเพิ่งทำไปไม่ได้กับไฟล์อินพุตที่มีหน้า "double-up" แต่เป็นหน้าหนึ่งที่มี "treble-ups" คุณสามารถอ่านคำตอบสำหรับกรณีนี้ที่นี่

กรณีของคุณง่ายยิ่งขึ้น คุณดูเหมือนจะมีสิ่งที่คล้ายกับนี้:

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

คุณต้องการสร้าง 1 PDF ที่มี 4 หน้าซึ่งแต่ละอันมีขนาด 421 pt x 595 pt

ขั้นแรก

ก่อนอื่นให้แยกส่วนด้านซ้ายออกจากหน้าป้อนข้อมูลแต่ละหน้า:

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

พารามิเตอร์เหล่านี้ทำอะไร

ครั้งแรกที่รู้ว่าในรูปแบบไฟล์ PDF 1 นิ้ว == 72 จุด จากนั้นส่วนที่เหลือคือ:

  • -o ...............:ตั้งชื่อไฟล์เอาต์พุต Implicitely -dBATCH -dNOPAUSE -dSAFERยังใช้
  • -sDEVICE=pdfwrite : เราต้องการ PDF เป็นรูปแบบผลลัพธ์
  • -g................:กำหนดขนาดสื่อออกเป็นพิกเซล ความละเอียดเริ่มต้นของ pdfwrite คือ 720 dpi ดังนั้นคูณด้วย 10 เพื่อรับการจับคู่สำหรับ PageOffset
  • -c "..............:ขอให้ Ghostscript ประมวลผลข้อมูลโค้ด PostScript ที่กำหนดไว้ก่อนไฟล์อินพุตหลัก (ซึ่งต้องติดตามด้วย-f)
  • <</PageOffset ....:ชุดเลื่อนภาพหน้าบนสื่อ (แน่นอนสำหรับหน้าซ้ายการเปลี่ยนแปลงโดย[0 0]ไม่มีผลกระทบจริง)
  • -f ...............: ประมวลผลไฟล์อินพุตนี้

คำสั่งสุดท้ายที่ได้ผลสำเร็จใด?

อันนี้:

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

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

ขั้นตอนที่สอง

ถัดไปส่วนที่ถูกต้อง:

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

สังเกตค่าออฟเซ็ตเชิงลบเนื่องจากเราเลื่อนหน้าไปทางซ้ายในขณะที่รักษาพื้นที่การดูอยู่กับที่

ผลลัพธ์:

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

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

ขั้นตอนสุดท้าย

ตอนนี้เรารวมหน้าเป็นไฟล์เดียว เราสามารถทำได้ด้วย ghostscript เช่นกัน แต่เราจะใช้pdftkแทนเพราะเร็วกว่าสำหรับงานนี้:

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

เสร็จสิ้น นี่คือผลลัพธ์ที่ต้องการ 4 หน้าแตกต่างกันขนาด 421x595 pt

ผลลัพธ์:

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

@ ไม่ทราบ: ขอบคุณสำหรับ downvoting! คุณช่วยกรุณาเขียนความคิดเห็นเพื่อระบุเหตุผลบางอย่างได้ไหม?
Kurt Pfeifle

+1 สำหรับการใช้งาน ASCII ที่ยอดเยี่ยมและคำแนะนำที่ชัดเจนมาก แค่ทำให้ฉันเป็น CLI n00b แล้ว \ s จะหนีออกจากสายเพื่อให้อ่านง่ายขึ้น
Geek

@mullhausen: ขอบคุณสำหรับการแก้ไขคำที่พิมพ์ผิด ( 421-> -421) ;-)
Kurt Pfeifle

6

มีpdfposterเครื่องมือซึ่งสามารถใช้ในการสร้างไฟล์ PDF ที่มีหลายหน้าสำหรับหน้าเข้าหนึ่ง (เรียงหรือเรียงหน้า) มันคล้ายกับเครื่องมือposterซึ่งทำเช่นเดียวกันกับไฟล์ PostScript


pdfposter ไม่จัดการการพิมพ์เนื้อหาที่ทับกันที่ขอบเพื่อการประกอบโปสเตอร์ง่ายขึ้น มันเป็นสคริปต์ Perl แต่มันค่อนข้างง่ายที่จะเพิ่ม
Matthias Urlichs

3

ดังนั้นหลังจากค้นหามากขึ้น (ดูเหมือนว่า "หน้าตัด PDF" เป็นการค้นหาที่ดีกว่า) ฉันพบสคริปต์เล็กน้อยที่เรียกว่าunpnupใช้posterการแปลง PDF / PS และpdftkทำสิ่งที่ฉันต้องการ มันค่อนข้างไกล แต่ก็ไกลกว่าวิธีอื่น ๆ ที่ฉันค้นพบ (เช่นการใช้ imagemagick) เพราะมันไม่ทำให้หน้าเว็บกระจัดกระจายก่อนที่จะพ่นออกมา

ในกรณีที่ mobileread หายไปด้วยเหตุผลบางอย่างแกนกลางของสคริปต์ (ได้รับอนุญาตภายใต้ GPLv2 หรือใหม่กว่าโดย Harald Hackenberg <hackenberggmx.at>) มีดังนี้:

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
ต้องรักเมื่อมีคนตอบคำถามของตัวเอง อย่างไรก็ตามหากคุณต้องการใช้งานกับ GUI โดยเฉพาะอย่างยิ่งหากขนาดหน้ากระดาษไม่เท่ากันหรือคุณต้องการที่จะครอบตัดแต่ละด้านให้ตรวจสอบ Briss: briss.sourceforge.net
frabjous

คุณควรจะสามารถทำสิ่งที่คุณต้องการด้วย PDFTK ด้วยตัวเองโดยไม่มีการแปลงทั้งหมด
CarlF

@CarlF: ฉันคิดว่ามันเป็นไปได้ แต่ฉันไม่เห็นอะไรในหน้า PDFTK เพื่อจัดการเนื้อหาของหน้าเว็บ มีตัวชี้ใดสำหรับฉัน
womble

@frabjous: มีอะไรผิดปกติในการตอบคำถามของคุณเอง?
Kurt Pfeifle

1
@ womble: การแปลงของคุณผ่าน PS / EPS สิ่งนี้ถูกผูกไว้เพื่อนำไปสู่การสูญเสียคุณภาพ (แบบอักษรฝังตัวโปร่งใส ฯลฯ ) คำแนะนำของฉันหลีกเลี่ยงความเสี่ยงPDF => EPS => PDFเส้นทางและไปมีความปลอดภัยPDF => PDF => PDFทาง
Kurt Pfeifle

2

ฉันพบคำตอบของ Kurt Pfeifle ว่ามีประโยชน์มากสำหรับสถานการณ์ที่คล้ายกันของฉัน ฉันคิดว่าฉันอาจแบ่งปันการแก้ไขโซลูชันร่วมกับผู้อื่น ...

ฉันก็มี PDF สแกนที่มี 2 หน้าในแต่ละแผ่นงาน มันเป็นการสแกนขนาด 11 x 8.5 (นิ้ว) ของหนังสือเล่มเล็กที่เย็บอานซึ่งถูกเย็บไว้เมื่อสแกนต้นฉบับดังนั้น: PDF หน้า 1 = ด้านหลังและด้านหน้า PDF หน้า 2 = หน้า 2 และ 3 เป็นต้นนี่เป็นการอ่านบนหน้าจอที่ดี แต่คุณไม่สามารถพิมพ์และเย็บเล่มเพื่อทำสำเนาเล่มเพิ่มเติม

ฉันต้องการพิมพ์บนเครื่องถ่ายเอกสารสองหน้า; นั่นคือเปลี่ยนมันกลับเป็น PDF "กำหนด" พร้อมสำหรับการพิมพ์ ดังนั้นการใช้วิธีแก้ปัญหาของ Kurt ฉันทำสิ่งนี้ (อะแฮ่ม) "หนึ่งซับ" เพื่อแปลงกลับเป็นครึ่งหน้าตามลำดับหน้าที่ถูกต้องอีกครั้ง มันจะทำงานสำหรับความสูงและความกว้างและสำหรับจำนวนหน้าใด ๆ ในกรณีของฉันฉันมีหนังสือเล่มเล็ก 40 หน้า (สแกน 20 หน้าในรูปแบบ 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"

คุณต้องแก้ไขพารามิเตอร์สองสามตัวแรกในคำสั่งนี้เพื่อระบุ HEIGHT และ WIDTH และ ORIG_FILE_PATH ส่วนที่เหลือของคำสั่งจะคำนวณขนาดต่างๆและเรียก gs สองครั้งจากนั้น pdftk มันจะนับหน้าในการสแกนของคุณแล้วสร้างข้อกำหนดการเรียงลำดับที่ถูกต้อง (สำหรับสถานการณ์ที่ฉันให้)

มันแสดงความคืบหน้าเกี่ยวกับสิ่งที่กำลังทำซึ่งจะมีลักษณะเช่นนี้:

+++ 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

จากนั้นเพื่อให้ได้หน้าหนังสือที่คุณต้องการสำหรับหนังสือเล่มเล็กที่พิมพ์ออกมาคุณเพียงแค่ "สั่งพิมพ์" ได้รับคำสั่ง. pdf ในขนาดหน้ากระดาษที่กำหนดเองตามขนาดที่คุณต้องการ (ในตัวอย่างของฉันคือ 5.5 x 8.5) ส่งไปยัง "เครื่องมือ (ในกรณีของฉันฉันใช้ Create Booklet สำหรับ Mac ของ Christoph Vogelbusch จากhttp://download.cnet.com/Create-Booklet/3000-2088_4-86349.html )

PDF ที่เป็นผลลัพธ์จะกลับไปเป็นขนาดหน้าดั้งเดิมที่ 11 x 8.5 ด้วย 2 หน้าต่อแผ่น แต่การสั่งซื้อจะเป็นไปอย่างที่คุณสามารถพิมพ์ได้สองด้าน, การผูกขอบสั้นและvoilà! คุณจะมีงานพิมพ์ที่คุณสามารถถ่ายเอกสารและพับและเย็บร้อยทำซ้ำหนังสือเล่มเดิมโดยไม่ต้องแยกชิ้นส่วน (หรือจำเป็นต้องดู) ของต้นฉบับ

หวังว่านี่จะช่วยใครซักคน!

-ค


1

ตามคำตอบของ piptas 'ด้านบน:

บน windows สำหรับการแยก PDF ขนาดตัวอักษรด้วยภาพหน้าปกเดี่ยวตอนเริ่มต้นสิ่งต่อไปนี้ใช้งานได้ดีสำหรับฉัน (สังเกตการใช้ [-612 0] ในขั้นตอนที่สองเป็นค่าบวกสร้างหน้าว่างเพราะมันผลักผิดวิธี .)

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

สังเกตการใช้งาน-dFirstPage=2ที่สั่งให้ gs เริ่มต้นการประมวลผลในหน้า 2

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

สิ่งนี้จะสร้าง right-section.pdf ในลักษณะเดียวกัน และตอนนี้ภาพหน้าปก:

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

ถัดไปเนื่องจากฉันไม่ต้องการผสานกับ pdftk โดยใช้การป้อนข้อมูลด้วยตนเองฉันจึงแยกส่วนซ้ายและขวาเป็น PDF แยกต่างหากในไดเรกทอรีใหม่

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

จากนั้นฉันเข้าร่วมไฟล์ PDF ในไดเรกทอรีนั้นเรียงตามตัวอักษร (และโชคดีนั่นหมายความว่าพวกเขาเรียงลำดับถูกต้อง!) และฉันก็เรียกใช้ผลลัพธ์ผ่าน ghostscript อีกครั้งเพื่อแก้ไข "คำเตือน: หมายเลขรุ่นออกจากช่วง 0..65535 สมมติว่า 0." ข้อผิดพลาดที่ผลิตโดย pdftk ซึ่ง ghostscript เรียกว่า "itext-paulo-155 (itextpdf.sf.net-lawagie.com)" - มันเกิดขึ้นเพื่อลดขนาดไฟล์ลงครึ่งหนึ่งในการใช้งานของฉัน ด้วยต้นฉบับ 4.5MB ผลของ pdftk เท่ากับ 6.7MB และการปรับกระบวนการ gswin32c ลดลงเป็น 3.2 MB

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

และเราทำเสร็จแล้ว! โปรดลบโฟลเดอร์ input_file, cover.pdf, input_temp.pdf, right_sections.pdf และ left_sections.pdf ;-)


1

หากคุณเพียงแค่ต้องการส่งออกไฟล์ PDF ด้านซ้ายทั้งหมดในเอกสารเดียวและไฟล์ PDF ด้านขวามือทั้งหมดในเอกสารเอกสารจากนั้นสคริปต์ต่อไปนี้ซึ่งยึดตามคำตอบของ Kurt Pfeifle จะทำการหลอกลวง กว้าง):

$ 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"

จากนั้นเรียกใช้เช่น:

$ ./split.sh thepdftosplit.pdf
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.