-
Section 1: Getting Started
-
Section 2: Core Syntax and Data Types
-
Section 3: Collections
-
39: Set Operations: Union, Intersection, Difference
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Turtle Graphics and Early Practice Projects
-
Section 7: Working with Files and I/O
-
Section 8: Regular Expressions
-
Section 9: Object-Oriented Python
-
Section 10: Error Handling
-
Section 11: Modules and Packages
-
Section 12: Iterators, Generators, and Functional Tools
-
Section 13: Decorators and Metaprogramming
-
Section 14: Concurrency and Parallelism
-
Section 15: Working with Dates, Times, and Numbers
-
Section 16: Standard Library Deep Dive I: Data Structures
-
Section 17: Standard Library Deep Dive II: System and Introspection
-
Section 18: Standard Library Deep Dive III: Security and Encoding
-
Section 19: Standard Library Deep Dive IV: Text and Data Utilities
-
Section 20: Networking and Web Basics
-
Section 21: Working with Databases
-
Section 22: Testing and Quality
-
Section 23: Advanced Typing
-
Section 24: Context Managers and Resource Handling
-
Section 25: Text, Unicode, and Binary Data
-
Section 26: More Functional and Iteration Tools
-
Section 27: Data Validation and Configuration
-
Section 28: Working with Images and Media
-
Section 29: Property-Based and Documentation Testing
-
Section 30: Packaging and Deployment
-
Section 31: Performance and Internals
-
Section 32: Design Patterns in Python
-
Section 33: GUI Programming
-
Section 34: Security Basics
-
Section 35: Data Structures and Algorithms
-
Section 36: Practical Projects
-
Section 37: Capstone Projects
-
Section 38: Interview and Algorithm Practice
-
Section 39: Writing Idiomatic Python
338: Generating Thumbnails and Watermarks Programmatically
I've seen a lot of developers approach image processing by treating pixels like they're just items in a list. When they first try to build a thumbnail generator, they usually reach for a simple resize function and assume that's the end of the story. But there is a massive difference between resizing an image and generating a thumbnail.
"Resizing is Just Changing the Width and Height"
The most common mistake I see is using a basic resize method—like Image.resize((100, 100)) in Pillow—and expecting the image to look right. If you take a high-res landscape photo (say, 4000x2000) and force it into a 100x100 square, you aren't making a thumbnail; you're squashing your image. Your mountains become needles and your people look like they've been flattened by a steamroller.
from PIL import Image
# The WRONG way: This ignores the aspect ratio
img = Image.open("vacation_photo.jpg")
thumbnail = img.resize((100, 100))
thumbnail.save("squashed.jpg")
Beyond the distortion, simple resizing often ignores the "sampling" process. If you just throw away pixels to make the image smaller, you get "aliasing"—those jagged, shimmering edges that make a photo look amateur. You need a resampling filter (like Lanczos) to average the pixels correctly.
Maintaining Proportions with Image.thumbnail
To do this properly, you want to maintain the aspect ratio. Pillow provides a method specifically for this: thumbnail(). Unlike resize(), thumbnail() calculates the largest possible size that fits within your requested dimensions while keeping the image's original proportions. It also modifies the image in place, which is more memory-efficient for batch processing.
from PIL import Image
img = Image.open("vacation_photo.jpg")
# This will not distort the image; it fits it within a 128x128 box
img.thumbnail((128, 128), Image.Resampling.LANCZOS)
img.save("proper_thumb.jpg")
If you absolutely need a perfect square (which is common for profile pictures), don't squash the image. Instead, you should "center crop"—find the shortest side, crop the center to a square, and then thumbnail that. It's a few more lines of code, but it's the difference between a professional app and a broken one.
Avoiding the "Blocky" Watermark
Now, let's talk about watermarks. A common frustration I hear is: "I tried to add my logo, but it has a weird white or black box around it!" This happens because the developer is pasting an RGB image onto another RGB image, ignoring the alpha channel (transparency).
To get a professional, translucent watermark, both your base image and your watermark must be in RGBA mode. You don't just "paste" the image; you use the watermark's own alpha channel as a mask. This tells Python, "Only apply the pixels where the logo actually exists; leave the transparent parts alone."
from PIL import Image
# Load the main image and the watermark
base = Image.open("product_shot.jpg").convert("RGBA")
watermark = Image.open("logo.png").convert("RGBA")
# Scale the watermark to be, say, 20% of the base image width
w_width, w_height = watermark.size
base_width, base_height = base.size
scale_factor = (base_width * 0.2) / w_width
new_size = (int(w_width * scale_factor), int(w_height * scale_factor))
watermark = watermark.resize(new_size, Image.Resampling.LANCZOS)
# Calculate position (bottom right corner with a 20px margin)
position = (base_width - watermark.size[0] - 20, base_height - watermark.size[1] - 20)
# Create a blank layer for the watermark to avoid modifying the base directly
overlay = Image.new("RGBA", base.size, (0, 0, 0, 0))
overlay.paste(watermark, position)
# Composite the two together
result = Image.alpha_composite(base, overlay)
result.convert("RGB").save("watermarked_product.jpg")
I prefer using Image.alpha_composite over a simple paste because it handles the blending of semi-transparent pixels much more naturally. If your logo has a soft glow or a drop shadow, alpha_composite will preserve that; a standard paste often leaves a jagged edge.
📋 Practical Task
Build a Batch Image Processor for an E-commerce Catalog
You have a folder of high-resolution product images. Your goal is to automate the creation of a "Gallery Set" for each image. Write a Python script that performs the following for every .jpg file in a source directory:
- Create a Square Thumbnail: Generate a 200x200 thumbnail. If the original image is not square, you must center-crop it first so that the final result is a perfect square without any stretching or distortion.
- Apply a Brand Watermark: Take a provided
logo.png(with transparency) and place it in the bottom-right corner of the original image. The logo should be scaled to exactly 15% of the base image's width. - Save Outputs: Save the thumbnail in a folder named
/thumbnailsand the watermarked version in a folder named/watermarked, maintaining the original filenames.
Hint: Remember to handle the conversion between RGB and RGBA modes to ensure your watermark doesn't have a solid background.
There are no comments for now.