ktu-papers-api / watermark.py
GitHub Action
Deploy clean API instance with LFS and README metadata
dce86d1
Raw
History Blame Contribute Delete
3.21 kB
"""
watermark.py
------------
Add your brand watermark (centered logo + bottom text) to KTU question paper PDFs,
and merge multiple papers into one branded file. Pure-Python, uses PyMuPDF.
"""
from __future__ import annotations
import fitz # PyMuPDF
def add_watermark(pdf_bytes: bytes,
logo_bytes: bytes | None = None,
text: str | None = "Downloaded from Keralatimetable.in",
logo_scale: float = 0.65,
text_color=(0.2, 0.2, 0.2)) -> bytes:
"""Return new PDF bytes with a centered logo and bottom-center text."""
doc = fitz.open(stream=pdf_bytes, filetype="pdf")
logo_ratio = None
if logo_bytes:
lp = fitz.open(stream=logo_bytes, filetype="png")
logo_ratio = lp[0].rect.height / lp[0].rect.width
lp.close()
for page in doc:
r = page.rect
# 1) Large Logo image, centered in the middle of the page
if logo_bytes and logo_ratio:
w = r.width * logo_scale
h = w * logo_ratio
# Calculate coordinates for absolute center
x0 = (r.width - w) / 2
y0 = (r.height - h) / 2
box = fitz.Rect(x0, y0, x0 + w, y0 + h)
# overlay=True puts it on top. It respects native PNG transparency.
page.insert_image(box, stream=logo_bytes, overlay=True)
# 2) Text watermark, bottom center, full opacity
if text:
font_size = 12
# Calculate text width to perfectly center it horizontally
text_length = fitz.get_text_length(text, fontname="helv", fontsize=font_size)
x_text = (r.width - text_length) / 2
y_text = r.height - 30 # 30 units up from the bottom edge
# Insert text at the calculated point with full opacity
page.insert_text(fitz.Point(x_text, y_text), text, fontsize=font_size, fontname="helv", color=text_color, overlay=True)
out = doc.tobytes(garbage=4, deflate=True)
doc.close()
return out
def merge_pdfs(pdf_bytes_list: list[bytes]) -> bytes:
"""Merge several PDFs (in order) into one PDF, returns bytes."""
merged = fitz.open()
for b in pdf_bytes_list:
d = fitz.open(stream=b, filetype="pdf")
merged.insert_pdf(d)
d.close()
out = merged.tobytes(garbage=4, deflate=True)
merged.close()
return out
def brand_papers(pdf_bytes_list: list[bytes],
logo_bytes: bytes | None = None,
text: str | None = "Downloaded from Keralatimetable.in") -> bytes:
"""Merge a list of PDFs then watermark the whole thing -> branded bytes."""
merged = merge_pdfs(pdf_bytes_list) if len(pdf_bytes_list) > 1 else pdf_bytes_list[0]
return add_watermark(merged, logo_bytes=logo_bytes, text=text)
if __name__ == "__main__":
import sys
# demo: python watermark.py input.pdf logo.png output.pdf
inp, logo, outp = sys.argv[1], sys.argv[2], sys.argv[3]
pdf = open(inp, "rb").read()
lg = open(logo, "rb").read()
open(outp, "wb").write(add_watermark(pdf, logo_bytes=lg, text="Downloaded from Keralatimetable.in"))
print("wrote", outp)