Разделить страницы PDF-файлов на несколько страниц [закрыто]

16

У меня есть куча файлов PDF, которые содержат две "настоящие" страницы на одной странице PDF; Я хотел бы нарезать их пополам и поместить каждую половину на отдельную страницу. По сути, мне нужно что-то, что делает полную противоположность pdfnup(или psnup). Как можно достичь этого подвига?

Платформа Linux, с открытым исходным кодом; так как у меня есть большая куча из них, было бы неплохо сделать что-то, что может быть написано в сценарии (в отличие от графического интерфейса), так что я могу просто дать ему список их и сделать это.

Существующий сценарий также не единственный вариант; если есть пример кода для управления PDF-файлами аналогичным образом со сторонней библиотекой, я, вероятно, смогу взломать его и сделать то, что я хочу.

Уомбл
источник
Возможный дубликат Как я могу разделить страницы PDF по центру?
Skippy le Grand Gourou

Ответы:

22

Вы можете решить это с помощью Ghostscript. pdftkодин не может сделать это (насколько мне известно). Я дам вам шаги командной строки, чтобы сделать это вручную. Это будет легко запрограммировать как процедуру, также с различными параметрами для размеров страницы и номеров страниц. Но вы сказали, что можете сделать это сами ;-)

Как решить эту проблему с помощью Ghostscript ...

... и ради забавы, я недавно сделал это не с помощью входного файла с двойными страницами, а с тройными. Вы можете прочитать ответ для этого случая здесь .

Ваш случай еще проще. Кажется, у вас есть что-то похожее на это:

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

Вы хотите создать 1 PDF с 4 страницами, каждая из которых имеет размер 421 пт х 595 пт.

Первый шаг

Давайте сначала извлечем левые разделы из каждой входной страницы:

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

Что сделали эти параметры?

Во-первых, знайте, что в PDF 1 дюйм == 72 балла . Тогда остальное:

  • -o ...............:Имена выходного файла. Неявно также использует -dBATCH -dNOPAUSE -dSAFER.
  • -sDEVICE=pdfwrite : мы хотим PDF в качестве выходного формата.
  • -g................:устанавливает размер выходного носителя в пикселях. Стандартное разрешение pdfwrite - 720 точек на дюйм. Следовательно, умножьте на 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 разных страницы размером 421х595 пт.

Результат:

+------------+ +------------+ +------------+ +------------+   ^
|            | |            | |            | |            |   |
|     1      | |     2      | |     3      | |     4      |   |
|            | |            | |            | |            |5595 pt
|            | |            | |            | |            |   |
|            | |            | |            | |            |   |
|            | |            | |            | |            |   |
+------------+ +------------+ +------------+ +------------+   v
<-- 421 pt --> <-- 421 pt --> <-- 421 pt --> <-- 421 pt -->
Курт Пфайфл
источник
@ Неизвестно: Спасибо за голосование! Не могли бы вы написать комментарий, указывающий причину этого?
Курт Пфайфл
+1 за потрясающее использование ASCII-искусства и очень четкие инструкции. Просто потому, что я CLI n00b, \ S избежать строк, так что его легче читать, верно?
Подмастерье Компьютерщик
@mullhausen: спасибо за исправление опечатки ( 421-> -421). ;-)
Курт Пфайфл
6

Существует инструмент pdfposter, который можно использовать для создания PDF-файлов с несколькими страницами для одной входной страницы (мозаика или разделка страниц). Это похоже на инструмент poster, который делает то же самое для файлов PostScript.

Philipp Wendler
источник
pdfposter не поддерживает печать перекрывающегося содержимого по краям, что упрощает сборку постеров. Это скрипт на Perl, поэтому его довольно легко добавить.
Матиас Урлич
3

Итак, после гораздо большего поиска (кажется, что «PDF-вырезанные страницы» - намного лучший поиск), я нашел небольшой скрипт, unpnupкоторый использует posterпреобразование PDF / PS и pdftkделает именно то, что мне нужно. Это немного долгий путь, но он намного превосходит другие методы, которые я нашел (например, использование imagemagick), потому что он не растеризует страницы перед тем, как их выплюнуть.

На случай, если mobileread по какой-то причине исчезнет, ​​ядро ​​сценария (лицензированное по GPLv2 или более поздней версии Харальдом Хакенбергом <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
Должен любить, когда люди отвечают на свои вопросы. Однако, если вам нужно было сделать это с графическим интерфейсом, особенно если размеры страниц были неравномерными или вы хотели обрезать каждую из сторон, посмотрите Briss: briss.sourceforge.net
frabjous
Вы должны быть в состоянии сделать то, что вы хотите с PDFTK самостоятельно, без всех преобразований.
CarlF
@CarlF: я думал, что это будет возможно, но я не вижу ничего на справочной странице PDFTK, чтобы манипулировать содержимым страниц. Есть какие-нибудь указатели для меня?
Уомбл
@frabjous: Что не так, отвечая на свои вопросы?
Курт Пфайфл
1
@womble: ваши конверсии проходят через PS / EPS. Это должно привести к снижению качества (встроенные шрифты, прозрачные пленки и т. Д.). Мое предложение избегает рискованного PDF => EPS => PDFмаршрута и идет более безопасным PDF => PDF => PDFпутем.
Курт Пфайфл
2

Я нашел ответ Курта Пфайли очень полезным для моей аналогичной ситуации. Я думал, что мог бы поделиться своей модификацией решения с другими ...

У меня тоже был отсканированный PDF, в котором было по 2 страницы на каждом листе. Это был отсканированный в брошюру буклет размером 11 x 8,5 (дюйм), который был оставлен сшитым при первоначальном сканировании, поэтому: страница PDF 1 = задняя и передняя обложка; Страница PDF 2 = страницы 2 и 3 и т. Д. На экране это хорошо читается, но вы не можете распечатать его, а затем сшить, чтобы сделать больше копий буклета.

Мне нужно было распечатать это на дуплексном копире; то есть превратить его НАЗАД в «навязанный» PDF, готовый к печати. Таким образом, используя решение Курта, я сделал это (гм) "однострочным", чтобы преобразовать его обратно в полстраницы, в правильном порядке страниц снова. Он будет работать для любой высоты и ширины, а также для любого количества страниц. В моем случае у меня был 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

Затем, чтобы получить верстку страницы, необходимую для печатного буклета, вы просто «печатаете» файл order.pdf на нестандартный размер страницы именно того размера, который вам нужен (в моем примере, 5,5 x 8,5), отправляя его в «создание буклета "инструмент (в моем случае я использовал« Создание буклета Кристофа Фогельбуша для Mac »по адресу http://download.cnet.com/Create-Booklet/3000-2088_4-86349.html ).

Полученный PDF-файл теперь вернется к исходному размеру страницы 11 x 8,5 с 2 страницами на листе, но порядок будет таким, что вы можете напечатать его двухсторонним, переплетом по короткому краю и вуаля! у вас будет распечатка, которую вы сможете фотокопировать, а также сложить и вышить крестиком, воспроизводя оригинальный буклет, даже не разбирая (или даже не видя) оригинал.

Надеюсь, это поможет кому-то!

Крис Торман
источник
1

Основываясь на ответе пипт выше:

В 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,5 МБ результат pdftk составил 6,7 МБ, а повторная обработка gswin32c уменьшила его до 3,2 МБ.

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 с правой стороны, все в одном документе, то следующий скрипт, основанный на ответе Курта Пфайфла, сделает свое дело (работает для любой высоты и ширина):

$ 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
mulllhausen
источник