Lerak
Lerak

Reputation: 61

Adding a margin to pdf pages with PyPDF2

I am creating a python script that can modify a pdf file to be printed in book sections. As there is no such functionality in the ubuntu printing settings.

PyPDF2 is a wonderful tool with which I have been able to do everything I wanted except adding a margin.

For example consider this book.
http://www.edwardothorp.com/sitebuildercontent/sitebuilderfiles/beatthemarket.pdf It requires some margins so that there is some room for binding them in a book. I have found how to shift the content a few pixels, but the size of the "canvas" doesn't change so some content is cut off.

I am able to adjust the "page size" with PyPDF2 by changing the mediabox size but I an only crop the pages, I cannot increase their size. And to add margins, I have to increase the size. I also can't shrink the content, because then for some reason the page size shrinks with it.

Here is the script if you want to print a book. http://pastebin.com/LGYhKYu1 Of course, it only works with pdfs with already some margins so you only need to shift the content.

I would be most grateful if someone could point out how to add margins to a pdf with PyPDF2 , I must be overlooking something.

Thank you!

Upvotes: 6

Views: 7242

Answers (3)

Dan
Dan

Reputation: 595

I assume for instance you say ODD pages shall have more margin on the left side than on the right side, and EVEN pages shall have more margin on the right side than on the left side. I used primary variable for bigger side margin and secondary variable for regular side margin, top and bottom margins for to and bottom. I used this script to prepare pdf for book hardcover printing, where book starts with odd page on the right hand side (so left margin is bigger than right) and opposite goes for even pages.

import argparse
from PyPDF2 import PdfReader, PdfWriter

def to_points(x):
    return x * 72 if measure == "inch" else x * 28.8

def add_margins(input_pdf, output_pdf, primary=0, secondary=0, top=0, bottom=0):
    with open(input_pdf, 'rb') as f:
        reader = PdfReader(f)
        writer = PdfWriter()

        for i, page in enumerate(reader.pages):
            i = i + 1

            if i % 2 == 0:
                page.mediabox.lower_left = (float(page.mediabox.lower_left[0]) - secondary, float(page.mediabox.lower_left[1]) - bottom)
                page.mediabox.lower_right = (float(page.mediabox.lower_right[0]) + primary, float(page.mediabox.lower_right[1]) - bottom)
                page.mediabox.upper_left = (float(page.mediabox.upper_left[0]) - secondary, float(page.mediabox.upper_left[1]) + top)
                page.mediabox.upper_right = (float(page.mediabox.upper_right[0]) + primary, float(page.mediabox.upper_right[1]) + top)
            else:
                page.mediabox.lower_left = (float(page.mediabox.lower_left[0]) - primary, float(page.mediabox.lower_left[1]) - bottom)
                page.mediabox.lower_right = (float(page.mediabox.lower_right[0]) + secondary, float(page.mediabox.lower_right[1]) - bottom)
                page.mediabox.upper_left = (float(page.mediabox.upper_left[0]) - primary, float(page.mediabox.upper_left[1]) + top)
                page.mediabox.upper_right = (float(page.mediabox.upper_right[0]) + secondary, float(page.mediabox.upper_right[1]) + top)

            writer.add_page(page)

        with open(output_pdf, 'wb') as out:
            writer.write(out)

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Add margins to a PDF file.")
    parser.add_argument('input_pdf', type=str, help="Input PDF file path")
    parser.add_argument('output_pdf', type=str, help="Output PDF file path")
    parser.add_argument('--side_p', type=float, default=0, help="Margin of primary side")
    parser.add_argument('--side_s', type=float, default=0, help="Margin of secondary side")
    parser.add_argument('--top', type=float, default=0, help="Top margin")
    parser.add_argument('--bottom', type=float, default=0, help="Bottom margin")
    parser.add_argument('--measure', type=str, default=0, help="cm or inch")

    args = parser.parse_args()
    measure = args.measure

    add_margins(
        args.input_pdf,
        args.output_pdf,
        to_points(args.side_p),
        to_points(args.side_s),
        to_points(args.top),
        to_points(args.bottom)
    )

Launch in cmd: python add-margings-pdf.py linear-algebra-printing.pdf out-linear-algebra-printing.pdf --side_p 0.75 --side_s 0.5 --top 0.5 --bottom 0.5 --measure inch

Upvotes: 0

Anand kumar
Anand kumar

Reputation: 11

I myself was trying to figure out this. My objective was to crop a B5 page content and fit in A4 for booklet

bind_margin = 60
for pnum in tqdm(range(numpage)):
    page = inpdf.getPage(pnum)

    # Trim margins from right and left
    page.trimBox.lowerLeft = tuple([a+b for a, b in zip(page.trimBox.lowerLeft, (50, 0))])
    page.trimBox.upperRight = tuple([a-b for a, b in zip(page.trimBox.upperRight, (50, 0))])
    page.cropBox.lowerLeft = tuple([a+b for a, b in zip(page.cropBox.lowerLeft, (50, 0))])
    page.cropBox.upperRight = tuple([a-b for a, b in zip(page.cropBox.upperRight, (50, 0))])

    # create empty A4 size page
    emptyPage = pdf.PageObject.createBlankPage(width=tarw, height=tarh)
    margin_available = tarw + page.mediaBox.lowerLeft[0] - page.mediaBox.upperRight[0]

    if pnum%2==0:
            tx = bind_margin
    else:
            tx = margin_available - bind_margin

    emptyPage.mergeTranslatedPage(page, tx, 180)

    outpdf.addPage(emptyPage)

Upvotes: 1

brembo
brembo

Reputation: 91

It seems there is no dedicated method, but you can create an empty page of the desired size, then merge your content with the empty page

page = PageObject.createBlankPage(
        yourPage.mediaBox.getWidth () + 2 * margin,  
        yourPage.mediaBox.getHeight() + 2 * margin)
page.mergeScaledTranslatedPage( yourPage, scale, leftMargin, bottomMargin)    
...
output = PdfFileWriter()
output.addPage(page)

Upvotes: 8

Related Questions