Posiekaj strony plików PDF na wiele stron [zamknięte]

16

Mam kilka plików PDF, które zawierają dwie „prawdziwe” strony na jednej stronie PDF; Chciałbym je pokroić na pół i położyć każdą połowę na osobnej stronie. Zasadniczo potrzebuję czegoś, co robi dokładnie odwrotność pdfnup(lub psnup). Jak można to osiągnąć?

Platformą jest Linux, preferowane oprogramowanie typu open source; ponieważ mam ich mnóstwo, aby zrobić coś, co da się napisać w skrypcie (w przeciwieństwie do GUI), byłoby miło, więc mogę po prostu podać ich listę i przeżuć.

Istniejący skrypt nie jest jedyną opcją; jeśli istnieje przykładowy kod do manipulowania plikami PDF w podobny sposób za pomocą biblioteki innej firmy, prawdopodobnie mogę włamać go do robienia tego, co chcę.

womble
źródło
Możliwy duplikat Jak mogę podzielić strony PDF na środek?
Skippy le Grand Gourou

Odpowiedzi:

22

Możesz to rozwiązać za pomocą Ghostscript. pdftksam nie może tego zrobić (o ile mi wiadomo). Dam ci kroki linii poleceń, aby to zrobić ręcznie. Będzie to łatwe do skryptu jako procedury, również z różnymi parametrami rozmiarów stron i numerów stron. Ale powiedziałeś, że możesz to zrobić sam ;-)

Jak rozwiązać ten problem za pomocą Ghostscript ...

... i dla zabawy, ostatnio zrobiłem to nie z plikiem wejściowym zawierającym strony „podwójne”, ale z „potrójnymi”. Możesz przeczytać odpowiedź na ten przypadek tutaj .

Twoja sprawa jest jeszcze prostsza. Wygląda na to, że masz coś podobnego do tego:

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

Chcesz utworzyć 1 plik PDF z 4 stronami, z których każda ma rozmiar 421 pkt x 595 pkt.

Pierwszy krok

Najpierw wyodrębnij lewe sekcje z każdej strony wejściowej:

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

Co zrobiły te parametry?

Po pierwsze, wiedz, że w PDF 1 cal == 72 punkty . Reszta to:

  • -o ...............:Plik wyjściowy z nazwami. Niejawnie używa również -dBATCH -dNOPAUSE -dSAFER.
  • -sDEVICE=pdfwrite : chcemy PDF jako format wyjściowy.
  • -g................:ustawia rozmiar nośnika wyjściowego w pikselach. Domyślna rozdzielczość pdfwrite to 720 dpi. Dlatego pomnóż przez 10, aby uzyskać dopasowanie do PageOffset.
  • -c "..............:prosi Ghostscript o przetworzenie podanego fragmentu kodu PostScript tuż przed głównym plikiem wejściowym (który musi nastąpić -f).
  • <</PageOffset ....:ustawia przesunięcie obrazu strony na nośniku. (Oczywiście dla lewej strony przesunięcie o [0 0]nie ma żadnego rzeczywistego efektu).
  • -f ...............: przetworzyć ten plik wejściowy.

Jaki wynik osiągnęła ostatnia komenda?

Ten:

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

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

Drugi krok

Następnie odpowiednie sekcje:

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

Zwróć uwagę na przesunięcie ujemne, ponieważ przesuwamy stronę w lewo, utrzymując nieruchomy obszar wyświetlania.

Wynik:

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

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

Ostatni krok

Teraz łączymy strony w jeden plik. Moglibyśmy to zrobić również za pomocą ghostscript, ale użyjemy pdftktego, ponieważ jest szybszy dla tej pracy:

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

Gotowy. Oto pożądany wynik. 4 różne strony o wymiarach 421 x 595 pkt.

Wynik:

+------------+ +------------+ +------------+ +------------+   ^
|            | |            | |            | |            |   |
|     1      | |     2      | |     3      | |     4      |   |
|            | |            | |            | |            |5595 pt
|            | |            | |            | |            |   |
|            | |            | |            | |            |   |
|            | |            | |            | |            |   |
+------------+ +------------+ +------------+ +------------+   v
<-- 421 pt --> <-- 421 pt --> <-- 421 pt --> <-- 421 pt -->
Kurt Pfeifle
źródło
@Nieznany: Dzięki za oddanie głosu! Czy zechciałby Pan napisać komentarz wskazujący jakiś powód tego?
Kurt Pfeifle
+1 za niesamowite wykorzystanie grafiki ASCII i bardzo jasne instrukcje. Po prostu dlatego, że jestem CLI n00b, uciec od linii, więc jest łatwiejszy do odczytania, prawda?
Journeyman Geek
@mullhausen: dzięki za poprawienie literówki ( 421-> -421). ;-)
Kurt Pfeifle
6

Istnieje narzędzie pdfposter, którego można użyć do tworzenia plików PDF z kilkoma stronami dla jednej strony wejściowej (układanie lub krojenie stron). Jest podobny do narzędzia poster, które robi to samo w przypadku plików PostScript.

Philipp Wendler
źródło
pdfposter nie obsługuje drukowania nakładających się treści na krawędziach, co ułatwia montaż plakatu. Jest to jednak skrypt Perla, więc można go dość łatwo dodać.
Matthias Urlichs
3

Tak więc po dużo więcej wyszukiwaniu (wydaje się, że „strony wycinane PDF” są znacznie lepszym wyszukiwaniem), znalazłem mały skrypt o nazwie, unpnupktóry używa poster, konwersji PDF / PS i pdftkrobienia dokładnie tego, czego potrzebuję. To trochę długa droga, ale znacznie przewyższa inne metody, które znalazłem (takie jak użycie imagemagick), ponieważ nie rasteryzuje stron przed ich wypluciem.

Na wypadek, gdyby mobileread z jakiegoś powodu zniknął, rdzeń skryptu (licencjonowany na licencji GPLv2 lub nowszej przez Haralda Hackenberga <hackenberggmx.at>) jest następujący:

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
womble
źródło
1
Uwielbiam, gdy ludzie odpowiadają na własne pytania. Jeśli jednak musisz to zrobić za pomocą GUI, zwłaszcza jeśli rozmiary stron nie są równe lub chcesz dalej przycinać każdą stronę, sprawdź Briss: briss.sourceforge.net
frabjous
Powinieneś być w stanie robić to, co chcesz z samym PDFTK, bez wszystkich konwersji.
CarlF
@CarlF: Myślałem, że to możliwe, ale nie widzę niczego na stronie podręcznika PDFTK, aby manipulować zawartością stron. Masz dla mnie jakieś wskazówki?
womble
@frabjous: Co jest złego w odpowiadaniu na własne pytania?
Kurt Pfeifle
1
@womble: Twoje konwersje przechodzą przez PS / EPS. To z pewnością doprowadzi do utraty jakości (osadzone czcionki, folie itp.). Moja sugestia omija ryzykowną PDF => EPS => PDFtrasę i idzie bezpieczniej PDF => PDF => PDF.
Kurt Pfeifle
2

Odpowiedź Kurta Pfeifle'a była bardzo pomocna w mojej podobnej sytuacji. Pomyślałem, że mogę udostępnić moją modyfikację rozwiązania innym ...

Ja również miałem zeskanowany plik PDF, który miał 2 strony na każdym arkuszu. Był to skan 11 x 8,5 (cala) broszury zszytej siodłowo, która została zszyta podczas skanowania, więc: strona 1 PDF = tylna i przednia okładka; PDF strona 2 = strony 2 i 3 itd. Czyta się dobrze na ekranie, ale nie można go wydrukować, a następnie zszyć, aby wykonać więcej kopii broszury.

Musiałem być w stanie wydrukować to na dwustronnej kopiarce; tzn. zamień go z powrotem w „narzucony” plik PDF, gotowy do drukowania. Tak więc, korzystając z rozwiązania Kurta, stworzyłem ten (ahm) „jednowierszowy”, aby ponownie przekonwertować go na pół strony, w odpowiedniej kolejności. Będzie działać dla dowolnej WYSOKOŚCI i SZEROKOŚCI, a także dla dowolnej liczby stron. W moim przypadku miałem 40-stronicową broszurę (20 zeskanowanych stron w pliku 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"

Musisz tylko zmienić kilka pierwszych parametrów w tym poleceniu, aby określić HEIGHT i WIDTH oraz ORIG_FILE_PATH. Pozostała część polecenia oblicza różne rozmiary i wywołuje gs dwa razy, a następnie pdftk. Policzy nawet strony w skanie, a następnie wygeneruje poprawną specyfikację sortowania (dla podanego przeze mnie scenariusza).

Daje pewien postęp w tym, co robi, co będzie wyglądać następująco:

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

Następnie, aby uzyskać impozycję strony potrzebną do wydrukowania broszury, wystarczy „wydrukować” zamówienie.pdf na niestandardowym rozmiarze strony dokładnie takiego rozmiaru, jakiego potrzebujesz (w moim przykładzie 5,5 x 8,5), wysyłając go do „tworzenia broszury” ”(w moim przypadku użyłem Utwórz broszurę Christopha Vogelbuscha dla Maca ze strony http://download.cnet.com/Create-Booklet/3000-2088_4-86349.html ).

Wynikowy plik PDF powróci teraz do pierwotnego rozmiaru strony 11 x 8,5 z 2 stronami na arkusz, ale kolejność będzie taka, że ​​możesz wydrukować go dwustronnie, z krótką krawędzią i voilà! otrzymasz wydruk, który możesz skopiować, zszyć i zszyć zeszytowo, odtwarzając oryginalną broszurę bez rozbierania (a nawet koniecznego oglądania) oryginału.

Mam nadzieję, że to komuś pomoże!

-do

Chris Thorman
źródło
1

Na podstawie powyższej odpowiedzi piptas :

W systemie Windows do dzielenia plików PDF o rozmiarze listu na początku z jednym obrazem okładki, poniższe działały dla mnie świetnie (zwróć uwagę na użycie [-612 0] w drugim kroku, wartość dodatnia utworzyła puste strony, ponieważ popchnęła w niewłaściwy sposób .)

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

Zwróć uwagę, którego użycie -dFirstPage=2nakazuje gs rozpocząć przetwarzanie na stronie 2.

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

Spowoduje to utworzenie odpowiednich sekcji.pdf w ten sam sposób. A teraz zdjęcie okładki:

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

Następnie, ponieważ nie chciałem łączyć się z pdftk przy użyciu ręcznego wprowadzania strony, podzieliłem lewą i prawą sekcję na osobne pliki PDF w nowym katalogu.

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

Następnie dołączam pliki PDF w tym katalogu alfabetycznie (i na szczęście oznacza to, że są one posortowane we właściwej kolejności!), A także ponownie uruchamiam wynik za pomocą ghostscript, aby naprawić „Ostrzeżenie: Numer generacji poza zakresem 0..65535, przy założeniu 0. ” błędy generowane przez pdftk, który ghostscript o nazwie „itext-paulo-155 (itextpdf.sf.net-lawagie.com)” - zdarzyło mi się również zmniejszyć rozmiar pliku o połowę w moim użyciu. Przy 4,5 MB oryginału wynik pdftk wynosił 6,7 MB, a przetwarzanie gswin32c zmniejszyło go do 3,2 MB.

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

I skończone! Usuń folder plik_wejściowy, cover.pdf, input_temp.pdf, right_sections.pdf i left_sections.pdf. ;-)

Louis
źródło
1

jeśli potrzebujesz tylko wydrukować pliki PDF z lewej strony wszystko w jednym dokumencie, a pliki PDF z prawej strony wszystko w jednym dokumencie, to załatwi następujący skrypt oparty na odpowiedzi Kurta Pfeifle'a (działa na dowolnej wysokości i szerokość):

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

następnie uruchom go tak:

$ ./split.sh thepdftosplit.pdf
Mulllhausen
źródło