PDF Watermark Adder

 import os

from pathlib import Path

from pypdf import PdfReader, PdfWriter

from reportlab.pdfgen import canvas

from reportlab.lib.pagesizes import letter, A4

from reportlab.lib.colors import Color

import io

 

# ============================================================

# STEP 1: Create Text Watermark as PDF (in memory)

# ============================================================

 

def create_text_watermark(text, page_width, page_height,

                           font_size=50, opacity=0.15,

                           rotation=45, color=(0.5, 0.5, 0.5)):

    """

    Generate a transparent diagonal text watermark

    and return it as a PDF bytes object.

    """

    packet = io.BytesIO()

    c = canvas.Canvas(packet, pagesize=(page_width, page_height))

 

    # Set transparency

    c.setFillColor(Color(color[0], color[1], color[2], alpha=opacity))

    c.setFont("Helvetica-Bold", font_size)

 

    # Move to center of page and rotate

    c.translate(page_width / 2, page_height / 2)

    c.rotate(rotation)

 

    # Draw watermark text centered

    c.drawCentredString(0, 0, text)

 

    c.save()

    packet.seek(0)

    return packet

 

 

# ============================================================

# STEP 2: Create Image Watermark as PDF (in memory)

# ============================================================

 

def create_image_watermark(image_path, page_width, page_height,

                            opacity=0.2, scale=0.4):

    """

    Place an image watermark centered on the page.

    """

    packet = io.BytesIO()

    c = canvas.Canvas(packet, pagesize=(page_width, page_height))

 

    img_width  = page_width * scale

    img_height = page_height * scale

    x = (page_width - img_width) / 2

    y = (page_height - img_height) / 2

 

    c.setFillAlpha(opacity)

    c.drawImage(image_path, x, y, width=img_width, height=img_height,

                mask='auto', preserveAspectRatio=True)

 

    c.save()

    packet.seek(0)

    return packet

 

 

# ============================================================

# STEP 3: Apply Watermark to Each Page

# ============================================================

 

def apply_watermark(input_pdf, output_pdf, watermark_packet_func,

                    page_range=None):

    """

    Merge watermark onto each page of the input PDF.

    page_range: tuple (start, end) 1-indexed inclusive, or None for all pages

    """

    reader = PdfReader(input_pdf)

    writer = PdfWriter()

 

    total_pages = len(reader.pages)

    print(f"\n Total pages in PDF: {total_pages}")

 

    # Determine page range

    if page_range:

        start = max(0, page_range[0] - 1)

        end   = min(total_pages, page_range[1])

    else:

        start = 0

        end   = total_pages

 

    for i, page in enumerate(reader.pages):

        if start <= i < end:

            # Get actual page dimensions

            media_box  = page.mediabox

            page_w = float(media_box.width)

            page_h = float(media_box.height)

 

            # Create fresh watermark for this page size

            wm_packet = watermark_packet_func(page_w, page_h)

            wm_reader = PdfReader(wm_packet)

            watermark_page = wm_reader.pages[0]

 

            # Merge watermark onto page

            page.merge_page(watermark_page)

 

        writer.add_page(page)

 

    with open(output_pdf, "wb") as f:

        writer.write(f)

 

    print(f" Watermarked PDF saved: {output_pdf}")

 

 

# ============================================================

# STEP 4: Batch Watermark Multiple PDFs

# ============================================================

 

def batch_watermark(folder_path, watermark_func, suffix="_watermarked"):

    folder = Path(folder_path)

    pdf_files = list(folder.glob("*.pdf"))

 

    if not pdf_files:

        print(" No PDF files found in folder.")

        return

 

    print(f"\n Found {len(pdf_files)} PDF(s) — processing...")

 

    for pdf in pdf_files:

        output_name = pdf.stem + suffix + ".pdf"

        output_path = pdf.parent / output_name

        try:

            apply_watermark(str(pdf), str(output_path), watermark_func)

        except Exception as e:

            print(f"  ⚠ Error processing {pdf.name}: {e}")

 

 

# ============================================================

# HELPER: Get Page Range Input

# ============================================================

 

def get_page_range(total_hint="all"):

    choice = input(f"\nApply watermark to all pages or specific range? (all/range) [{total_hint}]: ").strip().lower()

    if choice == "range":

        start = int(input("  Start page (1-indexed): ").strip())

        end   = int(input("  End page: ").strip())

        return (start, end)

    return None

 

 

# ============================================================

# MAIN MENU

# ============================================================

 

def main():

    print("\n" + "="*55)

    print("  PDF WATERMARK ADDER")

    print("="*55)

 

    print("\nMode:")

    print("  1. Add TEXT watermark to single PDF")

    print("  2. Add IMAGE watermark to single PDF")

    print("  3. Batch TEXT watermark (entire folder)")

 

    mode = input("\nEnter choice (1/2/3): ").strip()

 

    # ---- Single PDF Modes ----

    if mode in ["1", "2"]:

        input_pdf = input("\nEnter input PDF path: ").strip()

        if not os.path.isfile(input_pdf):

            print(" Invalid file path!")

            return

 

        default_out = Path(input_pdf).stem + "_watermarked.pdf"

        output_pdf  = input(f"Output PDF name [{default_out}]: ").strip() or default_out

 

        page_range = get_page_range()

 

        if mode == "1":

            # --- Text Watermark Settings ---

            text      = input("\nWatermark text (e.g. CONFIDENTIAL): ").strip() or "CONFIDENTIAL"

            font_size = int(input("Font size (default 50): ").strip() or 50)

            opacity   = float(input("Opacity 0.0-1.0 (default 0.15): ").strip() or 0.15)

            rotation  = float(input("Rotation angle (default 45): ").strip() or 45)

 

            print("\nColor options: 1=Gray  2=Red  3=Blue  4=Black")

            color_choice = input("Choose color (default 1): ").strip() or "1"

            colors = {

                "1": (0.5, 0.5, 0.5),

                "2": (0.8, 0.1, 0.1),

                "3": (0.1, 0.1, 0.8),

                "4": (0.0, 0.0, 0.0)

            }

            color = colors.get(color_choice, (0.5, 0.5, 0.5))

 

            def watermark_func(w, h):

                return create_text_watermark(

                    text, w, h,

                    font_size=font_size,

                    opacity=opacity,

                    rotation=rotation,

                    color=color

                )

 

        else:

            # --- Image Watermark Settings ---

            image_path = input("\nEnter image path (.png/.jpg): ").strip()

            if not os.path.isfile(image_path):

                print(" Invalid image path!")

                return

 

            opacity = float(input("Opacity 0.0-1.0 (default 0.2): ").strip() or 0.2)

            scale   = float(input("Image scale 0.1-1.0 (default 0.4): ").strip() or 0.4)

 

            def watermark_func(w, h):

                return create_image_watermark(

                    image_path, w, h,

                    opacity=opacity,

                    scale=scale

                )

 

        apply_watermark(input_pdf, output_pdf, watermark_func, page_range)

 

    # ---- Batch Mode ----

    elif mode == "3":

        folder = input("\nEnter folder path containing PDFs: ").strip()

        if not os.path.isdir(folder):

            print(" Invalid folder!")

            return

 

        text      = input("Watermark text (e.g. DRAFT): ").strip() or "DRAFT"

        font_size = int(input("Font size (default 60): ").strip() or 60)

        opacity   = float(input("Opacity 0.0-1.0 (default 0.15): ").strip() or 0.15)

        rotation  = float(input("Rotation angle (default 45): ").strip() or 45)

 

        def watermark_func(w, h):

            return create_text_watermark(text, w, h,

                                         font_size=font_size,

                                         opacity=opacity,

                                         rotation=rotation)

 

        batch_watermark(folder, watermark_func)

 

    else:

        print(" Invalid choice.")

        return

 

    print("\n" + "="*55)

    print("  All done! Your watermarked PDF(s) are ready.")

    print("="*55 + "\n")

 

 

# ============================================================

# RUN

# ============================================================

 

if __name__ == "__main__":

    main()

 

No comments: