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.
Asked
Active
Viewed 5.3k times
36
-
Does the image always occur at the same location? – Graham Chiu May 28 '10 at 04:00
-
Yes, it's basically a stamp near the lower left corner. – Eric Acevedo May 28 '10 at 15:14
-
Is the answer below sufficient? If not then what is wrong with it? – theheadofabroom Mar 17 '11 at 17:35
-
4Is there any way to put an image (like png, jpg, gif) over it? At specific coordinates? Or is the only solution to smush 2 pdfs together? – Auston Mar 19 '11 at 19:07
6 Answers
53
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

Martin Thoma
- 124,992
- 159
- 614
- 958

Dr Manhattan
- 13,537
- 6
- 45
- 41
-
3While you're bringing the answer up to date, the [pdfrw](https://github.com/pmaupin/pdfrw/) library can also [watermark](https://github.com/pmaupin/pdfrw/blob/master/examples/watermark.py) in a very similar fashion, and can also go the other way -- allowing you to use pre-existing PDFs as if they were images (without rasterizing them) in PDFs that you [build with reportlab](https://github.com/pmaupin/pdfrw/blob/master/examples/rl1/platypus_pdf_template.py). Disclaimer: I am the pdfrw author... – Patrick Maupin Jul 29 '15 at 22:40
-
@PatrickMaupin Can you use a ready-to-use answer with pdfrw? It would be super useful. – Basj May 20 '18 at 09:57
-
@PatrickMaupin pdfrw could benefit greatly from a watermark example that uses a png or jpeg file and adds the water mark at specific coordinates. Is this currently possible? – DrMaxB Jun 30 '20 at 23:52
29
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

Martin Thoma
- 124,992
- 159
- 614
- 958

Mohammad Efazati
- 4,812
- 2
- 35
- 50
-
Thanks it worked fine, just cheked the PdfFileReader.getPage() and PdfFileWriter.addPage() methods from docs. – Eric Acevedo Mar 17 '11 at 20:21
-
It seems PyPdf is not maintained anymore, nor the announced continuator site. What other solution exists in the long run ? – lalebarde Apr 06 '14 at 09:45
-
5
-
2@lalebarde: [`PyPDF2`](https://mstamy2.github.io/PyPDF2/) is the successor. – Ethan Furman Jul 05 '17 at 18:11
-
I'm the maintainer of pypdf and PyPDF2. The project continues with pypdf :-) – Martin Thoma Feb 11 '23 at 14:43
14
I combined ReportLab and pypdf<3.0.0 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"))

Martin Thoma
- 124,992
- 159
- 614
- 958

mariusnn
- 1,847
- 18
- 30
6
Thx to the previous answers. My way with python3.4 and PyPDF2<3.0.0
# -*- 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()

Martin Thoma
- 124,992
- 159
- 614
- 958

Bonus_05
- 210
- 2
- 5
5
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()

J. Owens
- 832
- 7
- 9
-
@j-owens - I've been having issues with the Rect constructor. It seems like the coordinates do not work correctly and you can only insert an image upside down. – atm Jun 27 '18 at 02:03
-
1The origin (0, 0) starts in the upper-left unlike some other libraries which might start in the lower-left (although I've come across a few PDFs with weird origins). I wonder if you have your y-coordinates inverted. – J. Owens Jun 27 '18 at 14:47
-
-
In newer versions of PyMuPDF, camel case has been replaced with snake case and page.insertImage should instead be page.insert_image. Adding this for others who try the above example (like I did). – most200 Nov 30 '22 at 05:44
0
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)

booberz
- 371
- 1
- 3
- 20