Spaces:
Running
Running
| """ | |
| 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) | |