34

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.

Eric Acevedo
  • 1,152
  • 1
  • 11
  • 25

7 Answers7

52

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:

New home of pypdf: http://mstamy2.github.io/PyPDF2/

Reportlab docs: http://www.reportlab.com/apis/reportlab/2.4/pdfgen.html

Reportlab complete user guide: https://www.reportlab.com/docs/reportlab-userguide.pdf

Dr Manhattan
  • 12,429
  • 5
  • 42
  • 39
  • 3
    While 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? – mbyamukama Jun 30 '20 at 23:52
28

http://pybrary.net/pyPdf/:

from pyPdf import PdfFileWriter, PdfFileReader

output = PdfFileWriter()
input1 = PdfFileReader(file("document1.pdf", "rb"))
watermark = PdfFileReader(file("watermark.pdf", "rb"))

input1.mergePage(watermark.getPage(0))

# finally, write "output" to document-output.pdf
outputStream = file("document-output.pdf", "wb")
output.write(input1)
outputStream.close()

I think it's like watermark, see the manual for better idea

Mohammad Efazati
  • 4,686
  • 2
  • 33
  • 50
14

I combined ReportLab (http://www.reportlab.com/software/opensource/rl-toolkit/download/) and pyPDF (http://pybrary.net/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"))
mariusnn
  • 1,787
  • 16
  • 29
5

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()
Bonus_05
  • 100
  • 1
  • 4
4

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
  • 804
  • 6
  • 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
  • 1
    The 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
  • I have tried this and it doesn't work. Any ideas why? Looks so neat! – Dusan J. Jan 14 '20 at 10:59
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
  • 351
  • 1
  • 2
  • 20
-6

Since, its existing pdf, the most easy way to do it is:

  1. Convert pdf to .doc or .odt ( Check http://www.zamzar.com/ )
  2. Add images into the converted file however you want.
  3. Convert back to PDF (openoffice and libreoffice makes it easy to save pdfs)

PS: If the pdf file needs to further edited always keep a backup of source .doc file, so that the changes can be done easily, too much conversion have bad effects on file quality.

Sathish Manohar
  • 5,515
  • 8
  • 34
  • 45