user319854
user319854

Reputation: 4126

Resize pdf pages in Python

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

Answers (7)

Dara O h
Dara O h

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

Ricky Levi
Ricky Levi

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

Alexandr Dragunkin
Alexandr Dragunkin

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

Ascyron
Ascyron

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

Ahsin Shabbir
Ahsin Shabbir

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

RobW
RobW

Reputation: 309

You can also apply scaling, rotation or translation directly in the merge function call, by using the functions:

  • mergePage()
  • mergeRotatedPage()
  • mergeRotatedScaledPage()
  • mergeRotatedScaledTranslatedPage()
  • mergeScaledPage()
  • mergeScaledTranslatedPage()
  • mergeTransformedPage()
  • mergeTranslatedPage()

Or use addTransformation() on a page object.

Upvotes: 2

Zach Kelling
Zach Kelling

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

Related Questions