How to convert a 1 page PDF to a 2 page per sheet PDF?
In addition to what's been mentioned, pdfjam-extras includes a command line tool, pdfnup
which does this. (It makes use of the pdfpages package for PDFLaTeX underneath, which you can also use.)
If you prefer a GUI, jPDFtweak is another option.
Use pdfnup:
$ pdfnup file.pdf
This will create a new pdf file exactly like you asked for.
This is a question old enough to think that the options we have now were absent at the time, but maybe it deserves an up-to-date solution.
Linux pdf viewers usually use the printing options/properties to set the page layout, and there you can print multiple pages per sheet/side. The idea is to use those to print to file as PDF.
Evince can do it, also qpdfview. More here.
qpdfview
Evince
PDF Studio Viewer
Other pdf viewers must have similar options.
For anyone wanting to take a 1 or 2 pg pdf and turn it into a pdf with 2 copies of that side-by-side in landscape view (great for printing flyers), do:
-
Turn the 1 or 2 pg pdf input into an output which contains a duplicated copy of those pages (1-pg pdf --> 2-pg pdf, 2-pg pdf --> 4-pg pdf, etc):
pdfunite in.pdf in.pdf out.pdf
-
Combine that duplicated-copy pdf into a 2-pages-per-side-in-landscape-view pdf, for printing flyers for example:
pdfnup out.pdf
Or (recommended) all on a single line:
pdfunite in.pdf in.pdf out.pdf && pdfnup out.pdf
Note that out.pdf
is the input to pdfnup
. The resulting output file from pdfnup
will be called "out-nup.pdf".
Also, watch the output of the pdfnup
command and you'll see the verbose form of the command it is actually running, which gives you some insight into the options you can pass into it. Apparently pdfnup
uses pdfjam
under the hood:
pdfjam: Effective call for this run of pdfjam:
/usr/bin/pdfjam --suffix nup --nup '2x1' --landscape -- out.pdf -
Example:
Original PDF (1 regular pg in Portrait view), "in.pdf":
Final PDF (2 pgs side-by-side in Landscape view), "out-nup.pdf":
- now can be cut in half down the middle to pass out as flyers
Simple Bash Function: make_flyer
Copy and paste this bash function to the bottom of your "~/.bashrc" file in order to get access to a simple and easy-to-use command 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\""'
Example usage:
make_flyer "path/to/inputpdf1.pdf" "path/to/inputpdf2.pdf"
See Help info:
make_flyer_help
Output:
$ 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"
References:
- https://superuser.com/a/948095/425838
- https://stackoverflow.com/a/11280219/4561887
Related:
- https://askubuntu.com/questions/214538/printing-in-booklet-format/1095789#1095789
Bash References:
- Bash How to pass arguments into a bash function: https://bash.cyberciti.biz/guide/Pass_arguments_into_a_function
- Bash Concatenate strings: https://linuxize.com/post/bash-concatenate-strings/
- Bash execute a cmd stored as a string! https://stackoverflow.com/questions/2005192/how-to-execute-a-bash-command-stored-as-a-string-with-quotes-and-asterisk
- Bash iterate over all inputs to a cmd: https://stackoverflow.com/questions/255898/how-to-iterate-over-arguments-in-a-bash-script/255913#255913
- Bash passing parameters to function: https://stackoverflow.com/questions/6212219/passing-parameters-to-a-bash-function/6212408#6212408
- How to convert a 1-pg pdf into a flyer [my own ans!]: How to convert a 1 page PDF to a 2 page per sheet PDF?
You can do this with PyPDF2. The code below is not a perfect solution to your problem, but it will hopefully help others who come here from 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"))