Reputation: 4126
I am using python to crop pdf pages. Everything works fine, but how do I change the page size(width)?
This is my crop code:
input = PdfFileReader(file('my.pdf', 'rb'))
p = input.getPage(1)
(w, h) = p.mediaBox.upperRight
p.mediaBox.upperRight = (w/4, h)
output.addPage(p)
When I crop pages, I need to resize them as well, how can I do this?
Upvotes: 4
Views: 27969
Reputation: 149
I was having a similar issue with merging multiple PDFs of different page sizes. Below works and also creates bookmarks for each merged PDF.
from pathlib import Path
import shutil
from pypdf import PaperSize, PdfReader, PdfWriter
def resize_pages_2_a4(mydir:Path, temp_dir:Path) -> None:
shutil.rmtree(temp_dir, ignore_errors=True)
shutil.copytree(mydir, temp_dir, dirs_exist_ok=True)
for fname in temp_dir.glob("*.pdf"):
pdf = PdfReader(fname)
writer = PdfWriter()
a4_width = PaperSize.A4[0]
for page in pdf.pages:
scale = page.mediabox[2] / a4_width
page.scale_to(page.mediabox[2] / scale, page.mediabox[3] / scale)
writer.add_page(page)
writer.write(fname)
writer.close()
def pdf_merge():
"""for each folder in current directory that contains pdf files create a
merged pdf, with bookmarks, using the directory name ie.
dir1:
a.pdf
b.pdf
dir2:
c.pdf
d.pdf
e.pdf
will result in 2 merged pdfs called dir1.pdf and dir2.pdf with all pages at a4 widths
NOTE: merge_scaled_page fn can be cleaner but has issues with complex pages
"""
temp_dir = Path("./temp")
for mydir in Path().glob("./**"):
print(mydir)
if mydir.name and not (fname := Path(f"{mydir.name}.pdf")).exists():
merger = PdfWriter()
# uses tempdir so that original pdf files are unaltered in case of script error
resize_pages_2_a4(mydir, temp_dir)
for pdf in temp_dir.glob("*.pdf"):
merger.append(pdf, pdf.stem)
with open(fname, "wb") as new_file:
merger.write(new_file)
pdf_merge()
Upvotes: 0
Reputation: 8007
In pypdf
(Python 3.9.6
) you can also scale by width and height like so:
from pypdf import PdfReader
from pypdf import PaperSize
pdf = PdfReader('some.pdf')
for page in pdf.pages:
page.scale_to(*PaperSize.A4)
Upvotes: 2
Reputation: 477
I did this. Python3.7
def pdf_scale_page(page: 'PageObject', size: float = 297)->None:
"""Scale page to specified size mm"""
(w, h) = page.mediabox[2:]
# Units of measurement are not "points". The units of measurement are user defined and default to 1/72 inch. See section 4.2.1 Coordinate spaces of the PDF specification.
# If we have a page width of 297 mm and at points 1 inch = 25.4 mm
pmm = (1/72*25.4)
ks = size / (max((w, h)) * pmm)
page.scale_by(ks)
Upvotes: 0
Reputation: 11
Ahsin Shabbir's answer works perfectly for PyPDF2, however as of October 2023 that module is deprecated and pypdf has returned to its original name. Here's a version of their answer, updated for pypdf v3.8.0:
import pypdf
pdf_path = r'YOUR_FILE_PATH\YOUR_FILE_NAME.PDF'
output_path = r'OUTPUT_FILE_PATH\OUTPUT_FILE_NAME.PDF'
pdf = pypdf.PdfReader(pdf_path)
writer = pypdf.PdfWriter()
page0 = pdf.pages[0]
# scale_by(0.71) reduces from e.g. A4 to A5. scale_by(0.5) reduces from A4 to A6
page0.scale_by(0.71)
writer.add_page(page0)
with open(output_path, "wb+") as f:
writer.write(f)
Upvotes: 1
Reputation: 305
This answer is really long overdue, and maybe the older versions of PyPDF2 didn't have this functionality, but its actually quite simple with version 1.26.0
import PyPDF2
pdf = "YOUR PDF FILE PATH.pdf"
pdf = PyPDF2.PdfFileReader(pdf)
page0 = pdf.getPage(0)
page0.scaleBy(0.5) # float representing scale factor - this happens in-place
writer = PyPDF2.PdfFileWriter() # create a writer to save the updated results
writer.addPage(page0)
with open("YOUR OUTPUT PDF FILE PATH.pdf", "wb+") as f:
writer.write(f)
Upvotes: 10
Reputation: 309
You can also apply scaling, rotation or translation directly in the merge function call, by using the functions:
Or use addTransformation() on a page object.
Upvotes: 2
Reputation: 53879
Do you want to scale the image after you crop it? You can use p.scale(factor_x, factor_y)
to do that.
Upvotes: 2