Blog Pages

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:

Post a Comment