How to Automatically Add Watermarks to Images Using Python with Code Examples

This article provides a clear explanation of how to automatically add watermarks to images using Python.

When publishing photos or images on the internet, it’s crucial to add a watermark to protect your copyright. This is especially important today when images can be easily shared on social media platforms like Instagram and Twitter.

Automating the process of adding watermarks saves a lot of time for bloggers, photographers, and designers, while efficiently protecting their copyrights.

By applying a logo or text watermark to images in bulk, you can ensure that the watermark remains visible even if the image is cropped. This method helps boost brand visibility and protect your images from theft or unauthorized use.

This article is a translation from Japanese, so please forgive any translation errors or culturally unfamiliar expressions. We hope it still provides valuable insights and helpful information. Thank you for your understanding!

1. Script Overview

Here’s What You Can Do
  • Automatically place the prepared PNG image in the bottom right corner
  • Automatically choose a black or white logo based on the brightness of the placement area
  • Automatically adjust the logo size according to the image size
  • Supports common image formats like JPEG, PNG, and BMP

This script automatically adds watermarks to images.

Additionally, an install.bat file is provided to easily set up the required environment.

You can download the software from the link below:

2. Prerequisites

To use this script, you need the following environment:

  • A Windows environment (required for the batch file)
  • Python 3.x installed
  • Required Python libraries: Pillow, NumPy

3. How to Use

Step 1: Environment Setup

  • Install Python: If Python 3.x is not installed, download it from the official Python website and install it.
  • Run the environment setup: Extract the “Auto-Watermark-by-kia.zip” file and double-click “install.bat” to execute the setup process.
  • Organize the script and logo images: After extraction, the directory structure should look like this:
    ├── watermark.py
    ├── watermark.bat
    ├── install.bat
    ├── logo
    │   ├── logo-black.png
    │   └── logo-white.png
        

Step 2: Preparing Transparent Logo Images for Watermarks

Prepare your logo images according to the following requirements:

  • Create logo images: Save your logo images as “logo-black.png” and “logo-white.png” in the “logo” folder, overwriting the existing files.
  • Prepare both black and white versions of the logo.
  • Save the logos as PNG files with transparent backgrounds.
  • The recommended image size is between 200px and 728px in width.

Rename the prepared logo files as logo-black.png and logo-white.png and place them in the “logo” folder of the script.

Step 3: Adding Watermarks to Images

  • Prepare image files: Get the images you want to watermark.
  • Create a shortcut: Create a shortcut for the watermark.bat file, move it to your preferred location, and execute it easily.
  • How to run: Drag and drop the image files onto the watermark.bat file (or its shortcut) to execute the script.
  • Batch processing: You can process multiple images by dragging and dropping them all at once.

Step 4: Check the Results

  • Output files: The processed images will have “_watermarked” appended to their filenames and will be saved in the same location as the original files.
  • Example: If you process “sample.jpg,” the output will be “sample_watermarked.jpg”.

4. Script Details

watermark.py

This is the main Python script that adds watermarks to your images.

Settings for Adjusting Watermark Size and Position

By modifying the settings at the top of the script, you can freely adjust the size, position, opacity, and brightness threshold of the watermark.

  • Watermark size (%): You can specify the size of the watermark as a percentage of the image’s size. The shorter side of the image’s dimensions (either width or height) is used as the base for the watermark size.
  • Brightness threshold: If the average brightness of the area where the watermark is placed is higher than this value, the black logo will be used. If it’s lower, the white logo will be applied. Brightness is measured on a scale from 0 (darkest) to 255 (brightest).
  • Opacity: The opacity of both the black and white logos can be adjusted, with values between 0 and 1. A value of 0 means fully opaque, while 1 means fully transparent.
  • Watermark position (%): You can specify the watermark’s position as a percentage relative to the width and height of the image. For example, setting the value to 0.95 means the watermark will be positioned 5% inward from the right and bottom edges.
  • Watermark image path: Specify the file paths for both the black and white logo images.
import os
import sys
import logging
import argparse
from PIL import Image
import numpy as np

########################################################################
# User-configurable settings

# Watermark size (percentage of the shorter side of the image)
LOGO_SCALE = 0.08  # Example: 0.08 means 8% of the shorter side

# Brightness threshold (0-255)
BRIGHTNESS_THRESHOLD = 110  # The brightness threshold to switch between black and white logos (Example: 110)

# Opacity (between 0 and 1)
OPACITY_DARK_LOGO = 0.5  # Opacity for the black logo (0 = fully opaque, 1 = fully transparent)
OPACITY_LIGHT_LOGO = 0.4  # Opacity for the white logo (0 = fully opaque, 1 = fully transparent)

# Watermark position (percentage)
ANCHOR_X_RATIO = 0.95  # Position of the watermark on the right bottom side (percentage of width, Example: 0.95 means 5% inside from the right edge)
ANCHOR_Y_RATIO = 0.95  # Position of the watermark on the bottom side (percentage of height, Example: 0.95 means 5% up from the bottom edge)

# Paths to the watermark images
BLACK_WATERMARK_PATH = r"logo\logo-black.png"
WHITE_WATERMARK_PATH = r"logo\logo-white.png"

# Path to the log file
LOG_FILE_PATH = "watermark_log.txt"

# End of user-configurable settings
########################################################################

def setup_logging():
    """Set up logging"""
    logging.basicConfig(
        filename=LOG_FILE_PATH,
        filemode='w',
        level=logging.INFO,
        format='%(asctime)s - %(levelname)s - %(message)s',
    )

def load_logo_images():
    """Load the watermark images"""
    try:
        black_logo = Image.open(BLACK_WATERMARK_PATH).convert('RGBA')
    except FileNotFoundError:
        logging.error(f"Black logo image not found: {BLACK_WATERMARK_PATH}")
        sys.exit(1)
    except Exception as e:
        logging.error(f"Error loading black logo image: {e}")
        sys.exit(1)

    try:
        white_logo = Image.open(WHITE_WATERMARK_PATH).convert('RGBA')
    except FileNotFoundError:
        logging.error(f"White logo image not found: {WHITE_WATERMARK_PATH}")
        sys.exit(1)
    except Exception as e:
        logging.error(f"Error loading white logo image: {e}")
        sys.exit(1)

    return black_logo, white_logo

def is_image_file(file_path):
    """Check if the file is an image using Pillow"""
    try:
        with Image.open(file_path) as img:
            img.verify()  # Verify that the image file is not corrupted
        return True
    except (IOError, SyntaxError) as e:
        logging.error(f"Error checking file format: {file_path}")
        logging.error(f"Error details: {e}")
        return False

def calculate_average_brightness(region):
    """Calculate the average brightness of a given region"""
    region_rgb = region.convert('RGB')
    pixels = np.array(region_rgb)
    luminance = 0.2126 * pixels[:, :, 0] + 0.7152 * pixels[:, :, 1] + 0.0722 * pixels[:, :, 2]
    average_brightness = luminance.mean()
    return average_brightness

def adjust_logo_opacity(logo_image, opacity_value):
    """Adjust the opacity of the logo"""
    opacity = int(255 * (1 - opacity_value))
    alpha = logo_image.split()[3]
    alpha = alpha.point(lambda p: p * (opacity / 255))
    logo_image.putalpha(alpha)
    return logo_image

def process_image(image_path, black_logo, white_logo):
    """Add a watermark to an image"""
    if not os.path.isfile(image_path) or not is_image_file(image_path):
        logging.warning(f"Unsupported file format or file not found: {image_path}")
        return

    try:
        with Image.open(image_path) as im:
            # Convert the image to RGBA mode (to handle transparency)
            im = im.convert('RGBA')
            width, height = im.size

            # Determine the size of the watermark based on the shorter side of the image
            shorter_side = min(width, height)
            logo_size = int(shorter_side * LOGO_SCALE)  # Set watermark size based on the shorter side

            # Calculate logo dimensions while maintaining aspect ratio
            aspect_ratio = black_logo.width / black_logo.height
            logo_width = logo_size
            logo_height = int(logo_width / aspect_ratio)

            # Resize the logos (keeping them in PNG format)
            black_logo_resized = black_logo.resize((logo_width, logo_height), resample=Image.LANCZOS)
            white_logo_resized = white_logo.resize((logo_width, logo_height), resample=Image.LANCZOS)

            # Calculate the watermark placement
            anchor_x = int(width * ANCHOR_X_RATIO)
            anchor_y = int(height * ANCHOR_Y_RATIO)
            x = anchor_x - logo_width
            y = anchor_y - logo_height
            x = max(0, x)
            y = max(0, y)

            # Crop the region where the watermark will be placed
            region = im.crop((x, y, x + logo_width, y + logo_height))

            # Calculate the brightness of the region
            average_brightness = calculate_average_brightness(region)

            # Select the logo based on the brightness
            if average_brightness >= BRIGHTNESS_THRESHOLD:
                logo_to_use = black_logo_resized
                opacity_value = OPACITY_DARK_LOGO
                logging.info("Selected Logo: Black")
            else:
                logo_to_use = white_logo_resized
                opacity_value = OPACITY_LIGHT_LOGO
                logging.info("Selected Logo: White")

            # Apply the opacity to the selected logo
            logo_to_use = adjust_logo_opacity(logo_to_use, opacity_value)

            # Create a new layer for the watermark
            watermark_layer = Image.new('RGBA', im.size, (0, 0, 0, 0))
            watermark_layer.paste(logo_to_use, (x, y), logo_to_use)

            # Combine the original image with the watermark
            combined = Image.alpha_composite(im, watermark_layer)

            # Determine the output file path and extension
            dir_name, file_name = os.path.split(image_path)
            base_name, ext = os.path.splitext(file_name)
            output_filename = f"{base_name}_watermarked{ext}"
            output_path = os.path.join(dir_name, output_filename)

            # Save the image
            if ext.lower() in ['.png', '.gif', '.tiff', '.tif', '.webp']:
                combined.save(output_path)
            else:
                combined_rgb = combined.convert('RGB')
                combined_rgb.save(output_path, quality=95)

            logging.info(f"Processed and saved: {output_path}")

    except Exception as e:
        logging.error(f"Error processing image: {image_path}")
        logging.error(f"Error details: {e}")

def main():
    # Set up logging
    setup_logging()

    # Process command-line arguments
    parser = argparse.ArgumentParser(description='Script to add watermarks to images')
    parser.add_argument('images', nargs='+', help='Paths to the image files to be processed')
    args = parser.parse_args()

    # Load the watermark images
    black_logo, white_logo = load_logo_images()

    for image_path in args.images:
        process_image(image_path, black_logo, white_logo)

if __name__ == "__main__":
    main()

Code Explanation:

  • Importing Libraries: Pillow is used for image processing, and NumPy is used for numerical calculations.
  • Loading the Watermark Images: The black and white logo images are loaded from the specified paths in RGBA mode. Using RGBA mode allows handling transparency.
  • Retrieving Image Files: The script retrieves a list of image files to process from the command-line arguments, allowing multiple images to be processed at once.
  • Resizing the Logo Based on Image Size: The script determines the aspect ratio of the image and adjusts the logo size based on the specified percentage. The height is used as the basis for portrait images, while the width is used for landscape images, maintaining the logo’s aspect ratio.
  • Calculating Watermark Position: The script calculates the watermark position based on the specified percentage values. It uses the bottom-right corner as the reference and adjusts the top-left position of the logo accordingly, ensuring the logo stays within the bounds of the image.
  • Calculating Brightness: The script calculates the average brightness of the region where the watermark will be placed. Based on whether the brightness is above or below the threshold, the script decides whether to use the black or white logo.
  • Setting Opacity: The selected logo’s opacity is adjusted based on the specified transparency value. The script manipulates the alpha channel to naturally blend the logo into the image.
  • Combining the Watermark: The original image and the watermark are combined. Alpha compositing is used to correctly layer the watermark, which has transparency information, over the original image.
  • Saving the Image: The processed image is saved with _watermarked appended to the original file name. The script saves the image in the appropriate mode based on the image format. For instance, JPEG files are converted to RGB mode and saved with specified quality settings.

Batch Files and Their Use

What is a batch file? A batch file is a type of script file in Windows that automates tasks. In this case, the batch files are used to set up the environment and run the watermarking process without having to manually input commands each time.

install.bat

This is a batch file for setting up the environment. It creates a virtual environment (venv) and installs the necessary libraries.

You only need to run this file the first time after downloading the script, and you can delete it afterward.


@echo off
chcp 65001 >nul
setlocal

REM Create the virtual environment
python -m venv venv

REM Activate the virtual environment
call venv\Scripts\activate.bat

REM Install the necessary libraries
pip install --upgrade pip
pip install Pillow numpy

echo Environment setup is complete.
pause

Code Explanation:

  • Creating the virtual environment: A virtual environment is created using Python’s venv module.
  • Installing the libraries: Pillow and NumPy are installed using pip.

watermark.bat

This is a batch file for running the Python script.


@echo off
chcp 65001 >nul
setlocal

REM Activate the virtual environment
call venv\Scripts\activate.bat

REM Set the script path (assuming it is in the same directory as the batch file)
set SCRIPT_PATH=%~dp0watermark.py

REM Collect the arguments
set args=
:loop
if "%~1"=="" goto after_loop
set args=%args% "%~1"
shift
goto loop
:after_loop

REM Run the script
python "%SCRIPT_PATH%" %args%

REM Check for errors
if %ERRORLEVEL% neq 0 (
    echo An error occurred.
    pause
)

Code Explanation:

  • Activating the virtual environment: The virtual environment created by install.bat is activated.
  • Running the script: The Python script is executed with the image files specified in the command-line arguments.
  • Error handling: If an error occurs, a message is displayed.

5. Conclusion

This script simplifies the process of adding watermarks to your images. It automatically selects the appropriate logo based on brightness, resizes the logo according to the image size, and eliminates the need for manual adjustments. We encourage you to give it a try!

If you have any questions or feedback, we encourage you to leave them in the comment section below.

Thank you for reading! We hope this script helps protect your images and enhance your workflow.

コメントする

ABOUTこの記事をかいた人

Web、Python、生成AI、投資、行動経済学の知見を活かし、みんなの生活を豊かにするための情報発信を心がけています。日々の選択を少し変えるだけで、ちょっと笑顔が増えるかも。一緒に学び、成長しながら、より良い人生にしていきましょう。