Of course! Here’s a comprehensive guide to using the thumbnail method in Python's Pillow (PIL) library, including a complete code example, explanation, and best practices.

What is PIL.Image.thumbnail()?
The thumbnail() method is a convenient way to create a lower-resolution version of an image. It modifies the image in-place, meaning it doesn't return a new image object but instead resizes the existing one.
The most important feature of thumbnail() is that it maintains the original aspect ratio of the image. This is crucial for preventing images from looking stretched or squished.
Key Characteristics
- In-Place Operation: It modifies the image object directly. This means if you do
img.thumbnail(size), the originalimgis now the thumbnail. - Maintains Aspect Ratio: It calculates the new size that fits within the given
sizewhile keeping the original proportions. - Modifies the
ImageObject: The original image data is replaced with the smaller thumbnail data. If you need to keep the original high-resolution image, you must make a copy first. - Accepts a Tuple: The
sizeargument is a tuple of(width, height).
Basic Example
Here is a simple, complete example to demonstrate how it works.
First, make sure you have Pillow installed:

pip install Pillow
Now, let's create a script.
from PIL import Image
# --- 1. Open an image ---
# Replace 'my_image.jpg' with the path to your image file.
# We'll use a placeholder image from online for this example.
try:
original_image = Image.open("my_image.jpg")
except FileNotFoundError:
# If you don't have an image, this will download a sample one.
import urllib.request
url = "https://picsum.photos/seed/pil_example/1200/800.jpg"
urllib.request.urlretrieve(url, "my_image.jpg")
original_image = Image.open("my_image.jpg")
print(f"Original image size: {original_image.size}")
# --- 2. Define the desired thumbnail size ---
# The size is a tuple (width, height).
thumbnail_size = (200, 200)
# --- 3. Create a copy if you need to preserve the original ---
# This is a crucial step!
thumbnail_image = original_image.copy()
# --- 4. Create the thumbnail ---
# The image is modified in-place.
thumbnail_image.thumbnail(thumbnail_size)
print(f"Thumbnail image size: {thumbnail_image.size}")
# --- 5. Save the new thumbnail ---
thumbnail_image.save("thumbnail.jpg")
print("Thumbnail 'thumbnail.jpg' created successfully.")
# To see the images (optional, requires a display)
# original_image.show()
# thumbnail_image.show()
Output:
Original image size: (1200, 800)
Thumbnail image size: (200, 150) # Note: Height is less than 200 to maintain aspect ratio
Thumbnail 'thumbnail.jpg' created successfully.
How the Size is Calculated (Aspect Ratio)
Let's break down how thumbnail(200, 200) worked on an image of (1200, 800).
-
Calculate Ratios:
- Width Ratio:
target_width / original_width=200 / 1200≈166 - Height Ratio:
target_height / original_height=200 / 800=25
- Width Ratio:
-
Choose the Smaller Ratio: To ensure the entire image fits inside the
(200, 200)box, Pillow must use the smaller of the two ratios. In this case,166is smaller.
(图片来源网络,侵删) -
Apply the Ratio: Pillow multiplies both the original width and height by this smaller ratio to get the final dimensions.
- New Width:
1200 * 0.166≈200 - New Height:
800 * 0.166≈3
- New Width:
-
Final Size: Since pixel dimensions must be integers, Pillow rounds the result. The final size is
(200, 133). (Note: The exact rounding can sometimes result in(200, 132)or(200, 134)depending on the Pillow version and internal calculations, but the principle is the same).
Best Practices and Common Pitfalls
Always Make a Copy First
This is the most common mistake. If you call thumbnail() on your original image, it will be permanently resized.
Incorrect (Loses original):
img = Image.open("large_image.jpg")
img.thumbnail((100, 100)) # img is now a 100px thumbnail
# You can no longer get the original size!
Correct (Preserves original):
img = Image.open("large_image.jpg")
thumbnail = img.copy() # Create a copy
thumbnail.thumbnail((100, 100)) # Resize the copy
# img is still the original large_image.jpg
# thumbnail is the small version
The thumbnail() Method vs. resize()
| Feature | thumbnail(size) |
resize(size, resample) |
|---|---|---|
| Operation | In-place (modifies the image object). | Returns a new image object. |
| Aspect Ratio | Always maintained. | Not maintained unless you calculate the correct size yourself. |
| Primary Use | Quickly creating a smaller preview version. | Precisely resizing an image to any dimensions, even if it distorts the aspect ratio. |
When to use resize()?
When you need specific dimensions and don't care about the aspect ratio (e.g., for a background tile) or when you've already calculated the new size to maintain the aspect ratio.
from PIL import Image
img = Image.open("my_image.jpg")
# Resize to a fixed 300x500 pixels, will stretch the image
resized_img = img.resize((300, 500))
# Resize while maintaining aspect ratio (more manual)
original_size = img.size
target_width = 300
aspect_ratio = original_size[1] / original_size[0]
new_height = int(target_width * aspect_ratio)
correctly_resized_img = img.resize((target_width, new_height))
Resampling Filter
The thumbnail() method automatically chooses a good resampling filter (usually Image.Resampling.LANCZOS for high-quality downscaling). You cannot change this filter with thumbnail().
If you need more control over the quality or type of resampling, you must use the resize() method and specify the resample argument (e.g., Image.Resampling.NEAREST, Image.Resampling.BILINEAR, Image.Resampling.LANCZOS).
Complete Workflow: Batch Processing Thumbnails
Here's a practical example of how to create thumbnails for all images in a folder.
import os
from PIL import Image
# --- Configuration ---
INPUT_FOLDER = "original_images" # Folder with your original images
OUTPUT_FOLDER = "thumbnails" # Folder to save the thumbnails
THUMBNAIL_SIZE = (400, 400) # The maximum size for the thumbnails
# --- Create the output folder if it doesn't exist ---
if not os.path.exists(OUTPUT_FOLDER):
os.makedirs(OUTPUT_FOLDER)
# --- Process all images in the input folder ---
for filename in os.listdir(INPUT_FOLDER):
try:
# Construct full file path
input_path = os.path.join(INPUT_FOLDER, filename)
# Skip directories
if not os.path.isfile(input_path):
continue
# Open the image
img = Image.open(input_path)
# Create a copy to preserve the original
thumb = img.copy()
# Create the thumbnail
thumb.thumbnail(THUMBNAIL_SIZE)
# Construct the output path and save
# Use the same filename for the thumbnail
output_path = os.path.join(OUTPUT_FOLDER, filename)
thumb.save(output_path)
print(f"Created thumbnail for: {filename}")
except Exception as e:
print(f"Could not process {filename}. Error: {e}")
print("\nBatch processing complete!") 