I'm trying to programmatically add a clickable image icon to the top-left corner of the first page of a PDF file using Python. I want the icon to link to a URL.
what I tried using reportlab and PyPDF2:
from PyPDF2 import PdfReader, PdfWriter
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from reportlab.lib.units import inch
import io
# Input paths
pdf_path = "original.pdf"
icon_path = "icon.jpeg"
output_pdf_path = "output.pdf"
# Set up canvas for overlay
packet = io.BytesIO()
can = canvas.Canvas(packet, pagesize=letter)
# Coordinates for top-left corner with padding
x, y = 40, 792 - 40 - inch
can.drawImage(icon_path, x, y, width=inch, height=inch)
can.linkURL("https://t.me/newsmalayalampdf", (x, y, x + inch, y + inch), relative=0)
can.save()
packet.seek(0)
# Merge overlay with original PDF
overlay = PdfReader(packet)
reader = PdfReader(pdf_path)
writer = PdfWriter()
first_page = reader.pages[0]
first_page.merge_page(overlay.pages[0])
writer.add_page(first_page)
for page in reader.pages[1:]:
writer.add_page(page)
with open(output_pdf_path, "wb") as f:
writer.write(f)
Despite setting the coordinates for the top-left, the image still appears somewhere in the middle of the page in the output. I've tried recalculating the Y position using the letter page height, but no luck.
What is the correct way to align an image with a hyperlink in the top-left of a PDF page using ReportLab and PyPDF2?
For this task you could use a textBased.pdf and place it over the pages via stamping using one single shell command.
cpdf -stamp-on logouri.pdf -pos-left "40 580" in.pdf -o output.pdf
However although in my tests that works perfectly well as a "native" no libs coding method. It introduces some handling issues that I can resolve but not so simple to use by others.
Thus, I have emulated a similar simplified call via 1 line approach using pymupdf.
python LogoUri.py input.pdf
import pymupdf
import sys
import os
if len(sys.argv) < 2:
print("Usage: python logouri.py input.pdf")
sys.exit(1)
input_pdf = sys.argv[1]
output_pdf = os.path.splitext(input_pdf)[0] + "-withlogo.pdf"
image_path = "logo.jpeg"
link_url = "https://t.me/newsmalayalampdf"
# Placements
x_offset = 36
y_offset = 36
display_size = 72 # points
doc = pymupdf.open(input_pdf)
for page in doc:
rect = pymupdf.Rect( x_offset, y_offset, x_offset + display_size, y_offset + display_size )
page.insert_image(rect, filename=image_path)
page.insert_link({ "kind": pymupdf.LINK_URI, "from": rect, "uri": link_url })
doc.save(output_pdf)
For only the first page replace the page loop with;
doc = pymupdf.open(input_pdf)
page = doc[0]
rect = pymupdf.Rect( x_offset, y_offset, x_offset + display_size, y_offset + display_size )
page.insert_image(rect, filename=image_path)
page.insert_link({ "kind": pymupdf.LINK_URI, "from": rect, "uri": link_url })
doc.save(output_pdf)