Draw lines using PyPDF - python

I am currently merging two pages into a single page in PyPDF3 but I need to draw a line in the middle of the two pages. Is this possible? Below is the sample code for reference. Thanks in advance!
from PyPDF3 import PdfFileWriter, PdfFileReader
from PyPDF3.pdf import PageObject
pdf_file = "Plan.pdf"
inputPDF = PdfFileReader(open(pdf_file, "rb"), strict=False)
outputPDF = PdfFileWriter()
for x in range(0, inputPDF.numPages, 2):
page1 = inputPDF.getPage(x).rotateClockwise(90)
page2 = inputPDF.getPage(x + 1).rotateClockwise(90)
total_width = max([page1.mediaBox.upperRight[0],page2.mediaBox.upperRight[0]])
total_height = page1.mediaBox.upperRight[1] + page2.mediaBox.upperRight[1]
new_page = PageObject.createBlankPage(None, total_width, total_height)
new_page.mergeTranslatedPage(page1, 0, page1.mediaBox.upperRight[1])
new_page.mergeTranslatedPage(page2, 0, 0)
outputPDF.addPage(new_page.rotateCounterClockwise(90))
outputFile = "Merged_Plan.pdf"
outputPDF.write(open(outputFile, "wb"))

You can use the Line annotation: https://pypdf.readthedocs.io/en/latest/user/adding-pdf-annotations.html#line
It was recently added to pypdf. You might need to update your installed version.
I recommend to switch away from PyPDF2 / PyPDF3 / PyPDF4 towards pypdf.

Related

crop pdf and add them side by side using python

from PyPDF2 import PdfWriter, PdfReader
reader = PdfReader('my-aadhar-card.pdf')
writer = PdfWriter()
page = reader.pages[0]
page.cropbox.upper_right = (290,264)
page.cropbox.lower_left = (32,102)
writer.add_page(page)
with open('result1.pdf','wb') as fp:
writer.write(fp)
writer2 = PdfWriter()
page2 = reader.pages[0]
page2.cropbox.upper_left = (560,264)
page2.cropbox.lower_right = (302,102)
writer2.add_page(page)
with open('result2.pdf','wb') as fp2:
writer2.write(fp2)
Help: I am cropping 2 pieces of pdf from Aadhaar card PDF download from uidai, I need to combine result1.pdf and result2.pdf side by side like the below image, When I merge them its creating 2 pages and one below the other
thanks in Advance

Export to image not pdf in python PyPDF2 package

I have the following code that crops part of pdf file then save the output as PDF
from PyPDF2 import PdfFileWriter, PdfFileReader
with open("Sample.pdf", "rb") as in_f:
input1 = PdfFileReader(in_f)
output = PdfFileWriter()
numPages = input1.getNumPages()
print("Document Has %s Pages." % numPages)
for i in range(1):
page = input1.getPage(i)
print(page.mediaBox.getUpperRight_x(), page.mediaBox.getUpperRight_y())
page.trimBox.lowerLeft = (280, 280)
page.trimBox.upperRight = (220, 200)
page.cropBox.lowerLeft = (100, 720)
page.cropBox.upperRight = (220, 800)
output.addPage(page)
with open("Output.pdf", "wb") as out_f:
output.write(out_f)
How can I save as an image not as PDF?
I found this code but the output is not at high quality. How can I improve the quality of the image output?
import fitz
pdffile = "Output.pdf"
doc = fitz.open(pdffile)
page = doc.loadPage(0)
pix = page.getPixmap()
output = "Output.jpg"
pix.writePNG(output)
Hi There You Could Use The pdf2image library for achieving so.
You Could Use The Following Code At The End:
from pdf2image import convert_from_path
images = convert_from_path('Output.pdf')
for i in range(len(images)):
images[i].save('Output'+ str(i) +'.jpg', 'JPEG')
Then If You Wish You Could Use The os library to delete the pdf you made using the following code in order to avoid the hassle of deleting the pdf yourself.
import os
os.remove("Output.pdf")
This solves the problem but I welcome any advanced ideas and improvements
import fitz
pdffile = "Output.pdf"
doc = fitz.open(pdffile)
zoom = 2 # zoom factor
mat = fitz.Matrix(zoom, zoom)
page = doc.loadPage(0)
pix = page.getPixmap(matrix = mat)
output = "Output.jpg"
pix.writePNG(output)

How to get Pdf Orientation using PyPDF2

I'm using Python/Django.
PyPDF2 to read my current pdf.
I want to read a pdf that I have saved and get the orientation of a single page within the pdf.
I'm expecting to be able to determine if the page is either landscape or portrait.
tempoutpdffilelocation = settings.TEMPLATES_ROOT + nameOfFinalPdf
pageOrientation = pageToEdit.mediaBox
pdfOrientation = PdfFileReader(file(temppdffilelocation, "rb"))
# tempPdfOrientationPage = pdfOrientation.getPage(numberOfPageToEdit).mediaBox
print("existing pdf width: ")
# print(existing_pdf.getPage(numberOfPageToEdit).getWidth)
# print("get page size with rotation")
# print(tempPdfOrientationPage.getPageSizeWithRotation)
existing_pdf = pdfOrientation.getPage(numberOfPageToEdit).mediaBox
# print(pageOrientation)
if pageOrientation.getUpperRight_x() - pageOrientation.getUpperLeft_x() > pageOrientation.getUpperRight_y() - pageOrientation.getLowerRight_y():
print('Landscape')
print(pageOrientation)
# print(pdfOrientation.getWidth())
else:
print('Portrait')
print(pageOrientation)
# print(pdfOrientation.getWidth())
# create a new PDF with Reportlab
can = canvas.Canvas(packet, pagesize=letter)
The last line setting the pagesize=letter what I want to determine based on my current pdf.
And here's my imports:
from PyPDF2 import PdfFileWriter, PdfFileReader
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter, landscape
import urllib
I've tried pyPdf .mediaBox but that always returns the same value of the expected file size, not the actual size. And pyPdf is outdated.
As you can see I've also tried getWidth and withRotation.
I would think there's be an easy way for PyPDF2 PdfFileReader to determine the orientation of a selected object.
Any help is appreciated. Thanks.
I used simply "/Rotate" attribute of the page:
OrientationDegrees = pdf.getPage(numberOfPageToEdit).get('/Rotate')
it can be 0, 90, 180, 270 or None
The rotate attribute will override the mediaBox settings. To account for this, check the page rotation before making final judgement. Note the text too can be rotated.
from PyPDF2 import PdfFileReader
pdf_path = 'yourPDFname.pdf'
pdf_reader = PdfFileReader(pdf_path)
deg = pdf_reader.getPage(0).get('/Rotate')
page = pdf_reader.getPage(0).mediaBox
if page.getUpperRight_x() - page.getUpperLeft_x() > page.getUpperRight_y() -page.getLowerRight_y():
if deg in [0,180,None]:
print('Landscape')
else:
print('Portrait')
else:
if deg in [0,180,None]:
print('Portrait')
else:
print('Landscape')
You can detect it by using this code snippet:
from PyPDF2 import PdfFileReader
pdf = PdfFileReader(file('example.pdf'))
page = pdf.getPage(0).mediaBox
if page.getUpperRight_x() - page.getUpperLeft_x() > page.getUpperRight_y() -
page.getLowerRight_y():
print('Landscape')
else:
print('Portrait')
This one works, fully tested:
import PyPDF2
from PyPDF2 import PdfFileReader
pdf = PdfFileReader(open('YourPDFname.pdf', 'rb'))
page = pdf.getPage(0).mediaBox
if page.getUpperRight_x() - page.getUpperLeft_x() > page.getUpperRight_y() -
page.getLowerRight_y():
print('Landscape')
else:
print('Portrait')

How to split/crop a pdf along the middle using pyPdf

I have a pdf that looks like this and i'd like to crop all the text out, almost right down the middle of the page. I found this script that does something simmilar:
def splitHorizontal():
from pyPdf import PdfFileWriter, PdfFileReader
input1 = PdfFileReader(file("in.pdf", "rb"))
output = PdfFileWriter()
numPages = input1.getNumPages()
print "document has %s pages." % numPages
for i in range(numPages):
page = input1.getPage(i)
print page.mediaBox.getUpperRight_x(), page.mediaBox.getUpperRight_y()
page.trimBox.lowerLeft = (25, 25)
page.trimBox.upperRight = (225, 225)
page.cropBox.lowerLeft = (50, 50)
page.cropBox.upperRight = (200, 200)
output.addPage(page)
outputStream = file("out.pdf", "wb")
output.write(outputStream)
outputStream.close()
However these crop dimensions are tuned to that specific example.
Can anyone show me how to find the correct crop dimensions.
I originally got the script from here --> Cropping pages of a .pdf file.
I read more into what the author had said, finally realizing that he had said:
The resulting document has a trim box that is 200x200 points and starts at 25,25 points inside the media box. The crop box is 25 points inside the trim box.
meaning
page.cropBox.upperRight = (200, 200)
must control the ultimate margins, i therefore adjusted the statement to
page.cropBox.upperLeft = (290, 792)
To mirror the cropping onto the other side and make sure the cropping holds the full vertical value
Chops each page in half, e.g. if a source were
created in booklet form, and then re-combines it
for further processing eg. text extraction
Importing required libraries
from PyPDF2 import PdfFileWriter,PdfFileReader,PdfFileMerger
Splitting Left Part
with open("docu.pdf", "rb") as in_f:
input1 = PdfFileReader(in_f)
output = PdfFileWriter()
numPages = input1.getNumPages()
for i in range(numPages):
page = input1.getPage(i)
page.cropBox.lowerLeft = (60, 50)
page.cropBox.upperRight = (305, 700)
output.addPage(page)
with open("left.pdf", "wb") as out_f:
output.write(out_f)
Splitting right part :
with open("docu.pdf", "rb") as in_f:
input1 = PdfFileReader(in_f)
output = PdfFileWriter()
numPages = input1.getNumPages()
for i in range(numPages):
page = input1.getPage(i)
page.cropBox.lowerLeft = (300, 50)
page.cropBox.upperRight = (540, 700)
output.addPage(page)
with open("right.pdf", "wb") as out_f:
output.write(out_f)
Combining left with right (two columns to two pages)
input1 = PdfFileReader(open("left.pdf","rb"))
input2 = PdfFileReader(open("right.pdf","rb"))
output = PdfFileWriter()
numPages = input1.getNumPages()
for i in range(numPages):
l = input1.getPage(i)
output.addPage(l)
r = input2.getPage(i)
output.addPage(r)
with open("out.pdf", "wb") as out_f:
output.write(out_f)
I faced the same challenge and I wrote this (require PyPDF2):
https://gist.github.com/kintaro1981/eb6cfc6f40a7fb39744f5ae630d58fd5
# -*- coding: utf-8 -*-
"""
This script splits each pdf page in half vertically and merge them in a single PDF in order.
It asks how many pages do you want to skip to avoid splitting a book cover or a specific number of initial pages.
Usage:
python cutpdfpages.py <filename.pdf> <newfilename.pdf>
"""
import sys
import copy
from PyPDF2 import PdfWriter, PdfReader
file = str(sys.argv[1])
newfile = str(sys.argv[2])
with open(file, "rb") as pdf1:
pdf = PdfReader(pdf1)
output = PdfWriter()
numpages = pdf.getNumPages()
page2skip = int(input('Insert how many pages do you want to skip: '))
for i in range(page2skip, numpages):
page = pdf.pages[i]
pagebis = copy.copy(page)
page.mediabox.upper_left = (page.mediabox.right / 2, page.mediabox.top,)
output.add_page(page)
pagebis.mediabox.upper_right = (pagebis.mediabox.right / 2, pagebis.mediabox.top,)
output.add_page(pagebis)
with open(newfile, "wb") as newpdf:
output.write(newpdf)

Place image over PDF

How can I place an image over an existing PDF file at an specific coordinate location. The pdf represents a drawing sheet with one page. The image will be scaled. I'm checking ReportLab but can't find the answer. Thanks.
Its been 5 years, I think these answers need some TLC. Here is a complete solution.
The following is tested with Python 2.7
Install dependencies
pip install reportlab
pip install pypdf2
Do the magic
from reportlab.pdfgen import canvas
from PyPDF2 import PdfFileWriter, PdfFileReader
# Create the watermark from an image
c = canvas.Canvas('watermark.pdf')
# Draw the image at x, y. I positioned the x,y to be where i like here
c.drawImage('test.png', 15, 720)
# Add some custom text for good measure
c.drawString(15, 720,"Hello World")
c.save()
# Get the watermark file you just created
watermark = PdfFileReader(open("watermark.pdf", "rb"))
# Get our files ready
output_file = PdfFileWriter()
input_file = PdfFileReader(open("test2.pdf", "rb"))
# Number of pages in input document
page_count = input_file.getNumPages()
# Go through all the input file pages to add a watermark to them
for page_number in range(page_count):
print "Watermarking page {} of {}".format(page_number, page_count)
# merge the watermark with the page
input_page = input_file.getPage(page_number)
input_page.mergePage(watermark.getPage(0))
# add page from input file to output document
output_file.addPage(input_page)
# finally, write "output" to document-output.pdf
with open("document-output.pdf", "wb") as outputStream:
output_file.write(outputStream)
References:
pypdf project page:
https://pypi.org/project/pypdf/
Reportlab docs:
http://www.reportlab.com/apis/reportlab/2.4/pdfgen.html
Reportlab complete user guide:
https://www.reportlab.com/docs/reportlab-userguide.pdf
https://pypi.org/project/pypdf/:
from pypdf import PdfWriter, PdfReader
writer = PdfWriter()
reader = PdfReader("document1.pdf")
watermark = PdfReader("watermark.pdf")
page = reader.pages[0]
page.merge_page(watermark.pages[0])
writer.add_page(page)
# finally, write the results to disk
with open("document-output.pdf", "wb") as fp:
writer.write(fp)
I think it's like watermark, see the documentation for more information
I combined ReportLab and pypdf to insert an image directly without having to generate the PDF up front:
from pyPdf import PdfFileWriter, PdfFileReader
from reportlab.pdfgen import canvas
from StringIO import StringIO
# Using ReportLab to insert image into PDF
imgTemp = StringIO()
imgDoc = canvas.Canvas(imgTemp)
# Draw image on Canvas and save PDF in buffer
imgPath = "path/to/img.png"
imgDoc.drawImage(imgPath, 399, 760, 160, 160) ## at (399,760) with size 160x160
imgDoc.save()
# Use PyPDF to merge the image-PDF into the template
page = PdfFileReader(file("document.pdf","rb")).getPage(0)
overlay = PdfFileReader(StringIO(imgTemp.getvalue())).getPage(0)
page.mergePage(overlay)
#Save the result
output = PdfFileWriter()
output.addPage(page)
output.write(file("output.pdf","w"))
Thx to the previous answers. My way with python3.4
# -*- coding: utf-8 -*-
from io import BytesIO
from PyPDF2 import PdfFileWriter, PdfFileReader
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
def gen_pdf():
# there are 66 slides (1.jpg, 2.jpg, 3.jpg...)
path = 'slades/{0}.jpg'
pdf = PdfFileWriter()
for num in range(1, 67): # for each slide
# Using ReportLab Canvas to insert image into PDF
imgTemp = BytesIO()
imgDoc = canvas.Canvas(imgTemp, pagesize=A4)
# Draw image on Canvas and save PDF in buffer
imgDoc.drawImage(path.format(num), -25, -45)
# x, y - start position
# in my case -25, -45 needed
imgDoc.save()
# Use PyPDF to merge the image-PDF into the template
pdf.addPage(PdfFileReader(BytesIO(imgTemp.getvalue())).getPage(0))
pdf.write(open("output.pdf","wb"))
if __name__ == '__main__':
gen_pdf()
This is quite easy to do with PyMuPDF without merging two PDFs:
import fitz
src_pdf_filename = 'source.pdf'
dst_pdf_filename = 'destination.pdf'
img_filename = 'barcode.jpg'
# http://pymupdf.readthedocs.io/en/latest/rect/
# Set position and size according to your needs
img_rect = fitz.Rect(100, 100, 120, 120)
document = fitz.open(src_pdf_filename)
# We'll put image on first page only but you could put it elsewhere
page = document[0]
page.insertImage(img_rect, filename=img_filename)
# See http://pymupdf.readthedocs.io/en/latest/document/#Document.save and
# http://pymupdf.readthedocs.io/en/latest/document/#Document.saveIncr for
# additional parameters, especially if you want to overwrite existing PDF
# instead of writing new PDF
document.save(dst_pdf_filename)
document.close()
This is what worked for me
from PyPDF2 import PdfFileWriter, PdfFileReader
def watermarks(temp, watermar,new_file):
template = PdfFileReader(open(temp, 'rb'))
wpdf = PdfFileReader(open(watermar, 'rb'))
watermark = wpdf.getPage(0)
for i in xrange(template.getNumPages()):
page = template.getPage(i)
page.mergePage(watermark)
output.addPage(page)
with open(new_file, 'wb') as f:
output.write(f)

Categories