How to Generate Thumbnails While Maintaining Aspect Ratio in Python

Resize images to fit within maximum dimensions while preserving the original aspect ratio using Pillow (PIL).

Easy Python 3.9+ Aug 9, 2026 Automation & scripting 13 views 0 copies

Requires third-party packages — install first
pip install Pillow

Python code

29 lines
Python 3.9+
from PIL import Image

def thumbnail_with_aspect_ratio(image_path, output_path, max_width, max_height):
    with Image.open(image_path) as img:
        # Get original dimensions
        width, height = img.size

        # Calculate scaling ratio to fit within max dimensions
        ratio = min(max_width / width, max_height / height)

        # New dimensions (rounded to integers)
        new_width = int(width * ratio)
        new_height = int(height * ratio)

        # Resize using high-quality resampling
        img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)

        # Save the resized image
        img.save(output_path)
        return new_width, new_height

if __name__ == "__main__":
    # Create a simple test image (400x300)
    test_img = Image.new("RGB", (400, 300), "blue")
    test_img.save("original.jpg")

    # Generate a thumbnail (max 100x100)
    result = thumbnail_with_aspect_ratio("original.jpg", "thumb.jpg", 100, 100)
    print(f"Original: 400x300 -> Thumbnail: {result[0]}x{result[1]}")

Output

stdout
Original: 400x300 -> Thumbnail: 100x75

How it works

Open the image with Image.open in a context manager to ensure the file is closed. Compute the scaling ratio as the minimum of the width and height ratios, which guarantees the thumbnail fits within the max box without distortion. Resize with Image.Resampling.LANCZOS for high-quality downsampling. The new dimensions are rounded to integers to match pixel grid requirements. Saving the resized image writes the final file, and returning the dimensions is handy for reporting.

Common mistakes

  • Not rounding new dimensions to integers, causing TypeError on resize.
  • Using a fixed ratio instead of `min()` which distorts the image.
  • Forgetting to use `Image.Resampling.LANCZOS` for better quality (older `Image.ANTIALIAS` is deprecated).
  • Not closing the image file if not using a context manager; leads to resource leaks.

Variations

  1. Use `img.thumbnail((max_width, max_height))` which modifies the image in place and preserves aspect ratio.
  2. Take a `quality` parameter for JPEG compression when saving.

Real-world use cases

  • Generating profile picture thumbnails for user uploads in a web application back end.
  • Creating preview images for product catalog entries that must fit a uniform display size.
  • Preparing social media share images that must fit platform-specific dimension constraints.

Sponsored

Run locally

This sample needs third-party packages, so it cannot run in the browser IDE. Copy the code above, install the packages shown at the top, then run it in your own Python environment.

More from Automation & scripting

Related tutorials and quizzes for this topic.