Как преобразовать 1-страничный PDF-файл в двухстраничный PDF-файл?

Я хотел бы напечатать PDF-файл, чтобы на первой странице были первые две страницы, на задней - третья и четвертая, и так далее.

-----------------          -----------------
|       |       |          |       |       |
|       |       |          |       |       |
|   1   |   2   |          |   3   |   4   |    . . .
|       |       |          |       |       |
|_______|_______|          |_______|_______|

 page 1 - front             page 1 - back

Поскольку мой принтер, использующий Linux, не поддерживает двустороннюю печать вручную, я подумал, что, возможно, я мог бы отредактировать PDF соответствующим образом.

Но как?

12 ответов

Решение

В дополнение к тому, что было упомянуто, PDFjam включает в себя инструмент командной строки, pdfnup который делает это. (Он использует пакет pdfpages для PDFLaTeX, который вы также можете использовать.)

Если вы предпочитаете графический интерфейс, jPDFtweak является еще одним вариантом.

Используйте pdfnup:

$ pdfnup file.pdf

Это создаст новый файл PDF точно так, как вы просили.

Это достаточно старый вопрос, чтобы думать, что имеющиеся у нас варианты в то время отсутствовали, но, возможно, оно заслуживает современного решения.

Программы просмотра PDF в Linux обычно используют параметры / свойства печати, чтобы установить макет страницы, и там можно распечатать несколько страниц на листе / стороне. Идея состоит в том, чтобы использовать их для печати в формате PDF.

Evince может сделать это, также qpdfview. Больше здесь.


qpdfview


выказывать


PDF Studio Viewer

Другие программы просмотра PDF должны иметь аналогичные параметры.

Для тех, кто хочет взять 1 или 2 pg pdf и превратить его в pdf с 2 копиями этого бок о бок в альбомной ориентации (отлично подходит для печати листовок), сделайте:

  1. Превратите ввод в 1 или 2 pg pdf в вывод, содержащий дублированную копию этих страниц (1-pg pdf -> 2-pg pdf, 2-pg pdf -> 4-pg pdf и т. Д.):

    pdfunite in.pdf in.pdf out.pdf
    
  2. Объедините этот файл с дубликатами-копиями в файл формата 2 страницы на сторону в альбомной ориентации, например, для печати листовок:

    pdfnup out.pdf
    

Или все в одной строке:

pdfunite in.pdf in.pdf out.pdf && pdfnup out.pdf

Обратите внимание, что out.pdf является вкладом в pdfnup, Полученный выходной файл из pdfnup будет называться " out-nup.pdf ".

Кроме того, смотрите вывод pdfnup команда, и вы увидите подробную форму команды, которую она на самом деле выполняет, что дает вам некоторое представление о параметрах, которые вы можете передать в нее. По всей видимости pdfnup использования pdfjam под капотом:

pdfjam: эффективный вызов для этого прогона pdfjam:

/usr/bin/pdfjam --suffix nup --nup '2x1' --landscape -- out.pdf -

Пример:

Оригинальный PDF (1 обычный pg в книжной ориентации), " in.pdf ":

Окончательный PDF (2 строчки бок о бок в альбомной ориентации), " out-nup.pdf ":
- теперь можно разрезать пополам по середине, чтобы раздать как листовки

Простая функция Bash: make_flyer

Скопируйте и вставьте эту функцию bash в конец файла "~/.bashrc", чтобы получить доступ к простой и удобной в использовании команде. make flyer:

# Description: outputs a landscape-oriented flyer pdf ("my/pdf/input--flyer.pdf") for each 1 or more pg input pdf ("my/pdf/input.pdf")
#   - 1-pg input PDFs are converted to a 1-sided landscape, printable flyer that you cut down the center to make 
#     2 flyers
#   - 2-pg input PDFs are converted to a 2-sided landscape, printable flyer (flip on short edge when printing 
#     double-sided), and also cut down the middle to make 2 flyers
#   - **3+ pg input PDFs**: using `pdfnup` directly in this case would make more sense, since this function will
#     otherwise unneccessarily create 2 copies
#   - 3 and 4-pg input PDFs are converted to a single piece of paper, double-sided, flipped on short edge, x 2 copies. 
#     No cutting is necessary
#   - 5+ pg input PDFs simply require half as much paper to print is all since you get 2 pages per side of paper;
#     they do NOT print like booklets, but rather just as a landscape-printed, flipped-on-short-edge bundle of pages
#     (like a deck of slides). You get *2 copies* per print though, so just print half the pages. 
make_flyer() {
    num_args=$# # see: https://stackoverflow.com/questions/4423306/how-do-i-find-the-number-of-arguments-passed-to-a-bash-script/4423321#4423321
    suffix="flyer"

    loop_cnt=0
    for inputpdf in "$@"
    do
        ((loop_cnt++))
        echo "==== CONVERTING PDF $loop_cnt OF $num_args ===="
        echo "     INPUT:  \"$inputpdf\""

        # Strip off the .pdf extension from the input path, while retaining the rest of the path
        # - See: https://stackoverflow.com/questions/12152626/how-can-i-remove-the-extension-of-a-filename-in-a-shell-script/32584935#32584935
        input_path_base="$(echo "$inputpdf" | rev | cut -f 2- -d '.' | rev)"
        input_file_base="$(basename "$inputpdf" .pdf)"
        temp_pdf="${input_path_base}-.pdf" # is "input_path_base-.pdf"

        echo "     OUTPUT: \"$(pwd)/${input_file_base}--${suffix}.pdf\""

        # Convert a single 1-pg pdf into a temporary 2-pg pdf
        pdfunite "$inputpdf" "$inputpdf" "$temp_pdf"

        # Lay out the temporary 2-pg pdf into a side-by-side 1-sided flyer to print; creates "input_path_base--flyer.pdf"
        # Note that `pdfnup` places the output from this operation in the location from where you call this script
        # (ie: in your `pwd` [Present Working Directory])!--NOT the location where temp_pdf is located!
        pdfnup "$temp_pdf" --suffix $suffix

        # Delete the temporary 2-pg pdf, called "input_path_base-.pdf", thereby leaving only the original 
        # "input_path_base.pdf" and the new "input_path_base--flyer.pdf"
        rm "$temp_pdf"
    done
}
alias make_flyer_help='echo -e "Ex usage: make_flyer \"path/to/inputpdf.pdf\" - Creates a landscape-side-by-side flyer version called \"inputpdf--flyer.pdf\"\n          *in your pwd* from a 1 or 2 pg input pdf called \"path/to/inputpdf.pdf\". Accepts multiple arguments. Ex:\n          make_flyer \"path/to/inputpdf1.pdf\" \"path/to/inputpdf2.pdf\""'

Пример использования:

make_flyer "path/to/inputpdf1.pdf" "path/to/inputpdf2.pdf"

См. Справочную информацию:

make_flyer_help

Выход:

$ make_flyer_help   
Ex usage: make_flyer "path/to/inputpdf.pdf" - Creates a landscape-side-by-side flyer version called "inputpdf--flyer.pdf"  
          *in your pwd* from a 1 or 2 pg input pdf called "path/to/inputpdf.pdf". Accepts multiple arguments. Ex:  
          make_flyer "path/to/inputpdf1.pdf" "path/to/inputpdf2.pdf"

Рекомендации:

  1. /questions/938052/kak-preobrazovat-1-stranichnyij-pdf-fajl-v-dvuhstranichnyij-pdf-fajl/938069#938069
  2. https://stackoverflow.com/a/11280219/4561887

Связанный:

  1. https://askubuntu.com/questions/214538/printing-in-booklet-format/1095789

Bash Рекомендации:

  1. Bash Как передать аргументы в функцию bash: https://bash.cyberciti.biz/guide/Pass_arguments_into_a_function
  2. Конкатенация строк в Bash: https://linuxize.com/post/bash-concatenate-strings/
  3. Bash выполнить cmd, хранящийся в виде строки! https://stackoverflow.com/questions/2005192/how-to-execute-a-bash-command-stored-as-a-string-with-quotes-and-asterisk
  4. Перебрать Bash по всем входным данным в cmd: https://stackoverflow.com/questions/255898/how-to-iterate-over-arguments-in-a-bash-script/255913
  5. Bash передавая параметры в функцию: https://stackoverflow.com/questions/6212219/passing-parameters-to-a-bash-function/6212408
  6. Как преобразовать 1-pg pdf во флаер [мои собственные ответы!]: Как преобразовать 1-страничный PDF-файл в 2-страничный PDF-файл на листе?

Вы можете сделать это с помощью PyPDF2. Приведенный ниже код не является идеальным решением вашей проблемы, но, надеюсь, он поможет другим, пришедшим сюда из Google.

#!/usr/bin/env python

# requires PyPdf2 library, version 1.26 or above -
# its homepage is https://pythonhosted.org/PyPDF2/index.html
# running: ./this-script-name output.pdf file-with-pdf-list

import copy, sys
from PyPDF2 import PdfFileWriter, PdfFileReader, pdf
output = PdfFileWriter()
output_page_number = 0
alignment = 6 # align on 6 pages for printing 6 up
for filename in sys.argv[2:]:

    page = pdf.PageObject.createBlankPage(None, 850, 1100)
    input = PdfFileReader(open(filename, "rb"))

    position = 0
    for i in range(0, input.getNumPages()):
        x = 0
        # Two Up
        # if position == 0:
        #    position = 1
        #    page.mergeScaledTranslatedPage(input.getPage(i), 0.5, 100, 650)
        #else:
        #    page.mergeScaledTranslatedPage(input.getPage(i), 0.5, 100, 100)
        #    output.addPage(page)
        #    page = pdf.PageObject.createBlankPage(output)
        #    position = 0
        # 6 Up
        scale = 0.25
        col1 = 100
        col2 = 450
        sep = 130
        row3 = sep + 25
        row2 = row3 + sep + 215
        row1 = row2 + sep + 215
        if position == 0:
           position = 1
           page.mergeScaledTranslatedPage(input.getPage(i), scale, col1, row1)
        elif position == 1:
           position = 2
           page.mergeScaledTranslatedPage(input.getPage(i), scale, col2, row1)
        elif position == 2:
           position = 3
           page.mergeScaledTranslatedPage(input.getPage(i), scale, col1, row2)
        elif position == 3:
           position = 4
           page.mergeScaledTranslatedPage(input.getPage(i), scale, col2, row2)
        elif position == 4:
           position = 5
           page.mergeScaledTranslatedPage(input.getPage(i), scale, col1, row3)
        else:
           page.mergeScaledTranslatedPage(input.getPage(i), scale, col2, row3)
           output.addPage(page)
           page = pdf.PageObject.createBlankPage(output)
           position = 0
    if position != 0:
        output.addPage(page)

output.write(open(sys.argv[1], "wb"))

Очень быстрый и грязный вариант, если у вас есть браузер Google Chrome, - это использовать встроенный PDF-принтер / средство просмотра и функцию "сохранить как PDF".

  1. Откройте / перетащите PDF-файл на вкладку Chrome (если отображается окно сохранения файла, вам необходимо включить опцию внутреннего просмотра PDF-файлов, перейдите на эту страницу в своем браузере http://chrome://settings/content/pdfDocuments)

  2. Щелкните правой кнопкой мыши и выберите "Печать".

  3. На панели печати выберите "Сохранить как PDF".

  4. Выберите количество страниц в "Страницах на листе".

ПРИМЕЧАНИЕ: у него может быть несколько причуд, если страницы не ровные или разное соотношение сторон, а также, насколько я могу судить, формат страницы - A4, и я не могу найти очевидного способа его изменить.

Кроме того, если у вас установлен Adobe Acrobat, вы можете использовать принтер Adobe PDF, в этом случае будут доступны дополнительные и расширенные параметры.

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

Я потерял приложение, которое использовал, так что никакой помощи там нет, но из быстрого поиска я вижу программу под названием pdfshuffler ( http://sourceforge.net/projects/pdfshuffler/), которая может быть тем, что вам нужно. Имеет графический интерфейс, поэтому вряд ли будет автоматическим, но это интерфейс для другого инструмента...

Это программное обеспечение, которое я тестировал в операционной системе Solaris 11.2, может создать такую ​​схему, которая называется 2-up, обычно используемая для раздаточного материала в аудиториях или на собраниях. Возможно изготовление других схем; например, раздавать 3 или 4 или более страниц на одном листе или на обеих сторонах листа. Его можно запустить из терминала, так как это JAR-файл, или просто запустить графический интерфейс для облегчения доступа. Помимо Solaris также совместимы другие дистрибутивы Linux, которые запускают программное обеспечение как "исполняемые" с привилегиями суперпользователя. Помните, что не используйте "Открыть архив". Он также работает на любых Windows и Mac, где уже установлена ​​Java Runtime Environment (JRE), как это происходит в большинстве случаев. Программное обеспечение является Dysprosium Imposition и является бесплатным для загрузки и использования.

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

@mokasin: Вы не сказали, какой читатель PDF вы используете. Если вы используете версию Acrobat/Adobe Reader для Linux: есть возможность напечатать "2-вверх" прямо в диалоговом окне печати. Вы также можете распечатать только нечетные или четные страницы, поэтому комбинирование этого поможет вам достичь желаемого результата.

решение сpython(PyPDF2версия 3.0.1)

вход (слева)/выход (справа)

Применение

Скорее всего вам нужно установить PyPDF2 (в указанной версии) с помощью

pip install PyPDF2==3.0.1

Затем вы можете выполнить скрипт с помощью

python create_multipage_pdf.py demo.pdf

код

Интервал и количество страниц (n_rows, n_cols) настраиваются. Вы также можете перевести выходной PDF-файл в альбомный режим, выполнивROTATE_OUTPUT = 90.

create_multipage_pdf.py

      PAGE_SHAPE_OUT = (297, 210)  # width, height
PAGES_PER_SHEET = (2, 2)  # n_rows, n_cols
PAD_LEFT = 20
PAD_RIGHT = 20
PAD_TOP = 20
PAD_BOTTOM = 20
WSPACE = 10
HSPACE = 20
ROTATE_OUTPUT = 0

FN_OUT_SEP = "_"
FN_OUT_SUFFIX = "multipage.pdf"

import sys
import PyPDF2
from math import prod

def add_page(doc_out, page, rects):
    """add page to PdfWriter and draw rectangle around subpages"""
    doc_out.add_page(page.rotate(ROTATE_OUTPUT))
    for rect in rects:
        # rect boarder is drawn inside
        pad = 1
        rect_padded = (rect[0] - pad, rect[1] - pad, rect[2] + pad, rect[3] + pad)
        doc_out.add_annotation(-1, PyPDF2.generic.AnnotationBuilder.rectangle(rect=rect_padded))

def main():
    global FNS_IN

    if len(sys.argv) > 1:
        FNS_IN = sys.argv[1:]

    fn_out = FN_OUT_SUFFIX
    if len(sys.argv) == 2:
        fn_out = FNS_IN[0][:-4] + FN_OUT_SEP + FN_OUT_SUFFIX
    doc_out = PyPDF2.PdfWriter()

    pos = 0
    page = None
    for filename in FNS_IN:

        doc_in = PyPDF2.PdfReader(open(filename, "rb"))
        for pp in range(0, len(doc_in.pages)):


            if pos % prod(PAGES_PER_SHEET) == 0:
                if page is not None:
                    add_page(doc_out, page, rects)
                page = PyPDF2.PageObject.create_blank_page(None, *PAGE_SHAPE_OUT)
                rects = []



            page_in = doc_in.pages[pp]

            # scale
            page_in_width = float(page_in.mediabox[2])
            page_in_height = float(page_in.mediabox[3])
            page_in_width_available = (
                (PAGE_SHAPE_OUT[0] - PAD_LEFT - PAD_RIGHT - WSPACE*(PAGES_PER_SHEET[0] - 1))
                / PAGES_PER_SHEET[0]
            )
            page_in_height_available = (
                (PAGE_SHAPE_OUT[1] - PAD_TOP - PAD_BOTTOM - HSPACE*(PAGES_PER_SHEET[1] - 1))
                / PAGES_PER_SHEET[1]
            )
            scale = min(page_in_width_available/page_in_width, page_in_height_available/page_in_height)
            page_in_width_scaled = page_in_width * scale
            page_in_height_scaled = page_in_height * scale

            # pos
            pos_page = pos % prod(PAGES_PER_SHEET)
            pos_row = pos_page // PAGES_PER_SHEET[1]
            pos_col = pos_page % PAGES_PER_SHEET[1]
            pos_x = PAD_LEFT + (WSPACE + page_in_width_available) * pos_col
            pos_y = PAD_BOTTOM + (HSPACE + page_in_height_available) * (PAGES_PER_SHEET[1] - 1 - pos_row)

            # rects
            rects += [(pos_x, pos_y, pos_x + page_in_width_scaled, pos_y + page_in_height_scaled)]

            tansformation = PyPDF2.Transformation().scale(scale).translate(tx=pos_x, ty=pos_y)
            page_in.add_transformation(tansformation)
            page.merge_page(page_in)
            pos += 1

    add_page(doc_out=doc_out, page=page, rects=rects)
    doc_out.write(open(fn_out, "wb"))

if __name__ == "__main__":
    assert len(sys.argv) >= 2, "call python script with at least one argument (pdfs to be multipaged)"
    main()

Информация

pdfnup устарел или исчез из дистрибутивов.

Но pdfautonup — замечательная замена, которая работает так же просто:

pdfautonup foo.pdf

Другие вопросы по тегам