[Copy-Paste OK] Bulk Image Resizing with Python! A Beginner's Guide to Pillow for Web Creators
Hello! This is a series where I, someone who had zero programming knowledge just a few months ago, explain things from a beginner's perspective based on my experience launching a website with the help of AI.
When you're running a website, one task that almost always comes up is "image resizing." Thumbnails for blog posts, product images, portfolio pieces... resizing a large number of images one by one is honestly enough to break your spirit, right? I've been there.
But don't worry. With Python, you can automate that tedious work in just a few seconds! In this article, I'll carefully explain how to create a "Bulk Image Resizing Tool" that even programming beginners can use right away just by copying and pasting, including some of the points where I got stuck. I really want you to experience that "It works!" moment.
This Session's Goal: Let's Automate Tedious Image Resizing!
By the time you finish this article, you'll be able to create a Python script that:
- Takes all the images in a specified folder
- Maintains the image's aspect ratio to prevent distortion
- Bulk resizes them to a specified width
- And automatically saves them to a different folder
For example, you'll be able to instantly convert dozens of photos stored in a folder into images with a width of 800px for your blog. No more opening image editing software over and over again!
Goodbye to manual work! An image of bulk processing with Python.
Preparation: Installing Pillow and Setting Up Your Workspace
Before we cast the magic spell, let's start with some prep work. Don't worry, it's not difficult!
1. What is Pillow? And How Do I Install It?
The star of our show today is a library called "Pillow." A library is like a "toolbox" filled with useful functions. Pillow is, so to speak, the "master toolbox for image processing" in Python.
Pillow is an extremely reliable library used by many developers worldwide. It has extensive documentation on its official website, so you can use it with confidence. (Reference: Pillow Official Documentation)
Installation is as simple as running the following line in your Command Prompt (Windows) or Terminal (Mac).
pip install Pillow
2. Prepare Your Working Folder
Next, let's prepare a folder for our work. This is very important! To keep things from getting messy, let's separate the folder for the original images and the folder for the resized images.
First, create a folder named "resize_tool" somewhere you like, such as your desktop. Then, create the following three items inside it:
- input_images folder: This is where you'll put the original images you want to resize.
- output_images folder: This is where the resized images will be saved.
- resize.py: This is the Python code file we are about to write.
The structure will look like this:
resize_tool/
βββ input_images/
β βββ photo1.jpg
β βββ photo2.png
β βββ ... (put the images you want to resize here)
β
βββ output_images/
β βββ (this will be empty at first)
β
βββ resize.py (we will create this file)
And that's all for preparation! Go ahead and put a few of your own images into the `input_images` folder.
Let's Get Practical: Writing the Python Code!
It's finally time for coding! Open the `resize.py` file in your text editor and let's write it together. I'll break down and explain each part of the process, so please follow along at your own pace.
Step 1: Prepare the Necessary Tools (Modules)
First, at the beginning of our program, we need to declare, "we will be using these tools." Let's call on our image processing master, "Pillow," and our folder and file handling expert, "os."
import os
from PIL import Image
from PIL import Image means, "From the Pillow library (PIL), we specifically want to use the functionality for handling Images." Just think of it as a standard incantation.
Step 2: Tell the Program Where the Folders Are
Next, we need to tell the program where the "input folder" and "output folder" we just created are located.
# Specify the paths for the input and output folders
input_dir = 'input_images'
output_dir = 'output_images'
With this, the program now understands that it should read images from `input_images` and write the results to `output_images`.
Step 3: Try Resizing a Single Image (The Basic Process)
Trying to do everything at once can be confusing, so let's first look at the process of resizing just "a single image." This will be the foundation for everything else.
- Open the image (`Image.open`)
- Resize it to the new dimensions (`.resize`)
- Save it with a new name (`.save`)
In code, it looks something like this. (β» We won't run this code just yet.)
# (This is just an example)
# 1. Open the image
img = Image.open('input_images/photo1.jpg')
# 2. Resize to 800px width (height is arbitrary for now)
resized_img = img.resize((800, 600))
# 3. Save it under a different name
resized_img.save('output_images/resized_photo1.jpg')
Step 4: Process All Images in the Input Folder Sequentially
Once you understand the basics, it's time for the main event. Let's have Python take out the files from the `input_images` folder one by one and apply the resizing process to them in sequence. This kind of "looping" is what programming excels at.
Using `os.listdir(input_dir)` gives you a list of filenames inside the specified folder. We'll use this to repeat the process until there are no files left.
# Loop through all files in the input directory
for filename in os.listdir(input_dir):
# The resizing process for each file will go here
print(f"Processing {filename}...")
The for ... in ...: syntax is for creating a loop. It takes the list of filenames obtained from `os.listdir(input_dir)` and puts them one by one into a variable called `filename`, then executes the code block inside.
[Crucial] The Pitfall I Fell Into and How to Solve It
It might seem like we're progressing smoothly, but there's a common pitfall for beginners right here. I fell for it spectacularly!
Problem: The script tries to process non-image files and crashes!
If you're using a Mac, it automatically generates hidden files like `.DS_Store`. You might also put your own text files for notes in the folder. The previous code attempts to process "all" files in the folder, so it will throw an error when it tries to open a file that isn't an image.
Solution: Only process image files (like .jpg, .png, etc.)
We'll add a condition to check the end of the filename (the extension) and only perform the resize operation if it's an image format. This will reliably prevent errors.
for filename in os.listdir(input_dir):
# Check if the file extension is one of .jpg, .jpeg, .png, or .gif
if filename.lower().endswith(('.jpg', '.jpeg', '.png', '.gif')):
# If the resize logic is here, only image files will be targeted!
print(f"Processing image file: {filename}")
else:
# If it's not an image file, skip it
print(f"Skipping non-image file: {filename}")
continue # Move to the next iteration of the loop
The key is to convert the filename to lowercase with .lower() before checking the ending with .endswith(). This allows it to handle extensions in uppercase, like `PHOTO.JPG`.
Advanced Tip 1: Resize Beautifully by Maintaining Aspect Ratio
Okay, we've got the basics of resizing down, but if you just specify a size, the image will get stretched vertically or horizontally and look distorted. To maintain the quality of your website, preserving the aspect ratio is essential!
The calculation is simple. We just need to calculate the original image's aspect ratio and then automatically compute the new height based on the new width.
- Decide on the target width (e.g., 800px)
- Get the original image's dimensions (width and height)
- Calculate the aspect ratio with
original_height / original_width - Determine the new height with
new_height = target_width * aspect_ratio
When translated into code, it looks like this:
# (This code goes inside the loop)
# Open the original image
img = Image.open(os.path.join(input_dir, filename))
width, height = img.size # Get the original width and height
# Specify the new width
new_width = 800
# Calculate the new height while maintaining the aspect ratio
new_height = int(new_width * height / width)
# Execute the resize!
resized_img = img.resize((new_width, new_height))
Using os.path.join() is a safe way to correctly combine the folder name and filename for any operating system. Also, since the calculation result might be a decimal, we convert it to an integer with `int()`.
Advanced Tip 2: For Web Creators! Let's Add a Watermark
Sometimes you want to add a "watermark" to prevent your work or blog images from being used without permission. With Pillow, even that is easy. Let's add a copyright notice or other text to the resized image.
For this, we'll use Pillow's drawing functionality, `ImageDraw`.
# (This is processed after resizing)
from PIL import ImageDraw, ImageFont
# ... after the resize process ...
# Create a drawing object
draw = ImageDraw.Draw(resized_img)
# Specify text and font
text = "Β© Your Name"
# You can specify a font installed on your PC. If not found, a default font is used.
try:
font = ImageFont.truetype("arial.ttf", 24)
except IOError:
font = ImageFont.load_default()
# Calculate the position to draw the text (bottom right)
text_width, text_height = draw.textbbox((0, 0), text, font=font)[2:4]
position = (resized_img.width - text_width - 10, resized_img.height - text_height - 10)
# Draw the text
draw.text(position, text, font=font, fill=(255, 255, 255, 128)) # Semi-transparent white
# Save the image after this
It might look a bit complex, but the flow is simply "switch to drawing mode," "decide on the text and position," and "write it." The last `128` in `fill=(255, 255, 255, 128)` represents the opacity, which you can adjust between 0 (fully transparent) and 255 (fully opaque).
[AI Pro Tip] How to Ask an AI to Write This Code?
AIs like ChatGPT and Gemini have been indispensable to my programming journey. If you give them the right instructions (prompts), they can generate code like this in an instant.
For example, try asking like this:
Please create a Python script to bulk resize images using the Pillow library. # Requirements - Read images from a folder named `input_images`. - Only process files with `.jpg`, `.jpeg`, and `.png` extensions. - Resize all images to a width of 800px while maintaining the aspect ratio. - Save the resized images to a folder named `output_images` with their original filenames. - Please display a message in the console showing which file is being processed.
The key is to convey what you want to do concretely and clearly in a list. AI is an excellent assistant, so the more precise your instructions, the more accurate the code it will return.
All Together Now: The Complete, Ready-to-Run Bulk Image Resizer Script
The wait is over! Here is the final version of the Python script that combines all the elements we've discussed. Copy and paste this into `resize.py`, put a few images into your `input_images` folder, and give it a run.
To run it, navigate to the `resize_tool` folder in your command prompt or terminal and just type `python resize.py`.
import os
from PIL import Image
def resize_images_in_folder(input_dir, output_dir, new_width=800):
"""
A function to batch resize images in a specified folder,
maintaining the aspect ratio.
:param input_dir: Path to the input folder
:param output_dir: Path to the output folder
:param new_width: The target width of the resized images in pixels
"""
# Create the output folder if it doesn't exist
if not os.path.exists(output_dir):
os.makedirs(output_dir)
print(f"Created folder: '{output_dir}'")
# List of supported image extensions
supported_formats = ('.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff')
# Get all files from the input directory
filenames = os.listdir(input_dir)
if not filenames:
print(f"The input folder '{input_dir}' is empty.")
return
print(f"Starting process... Number of files to check: {len(filenames)}")
# Process each file
for filename in filenames:
# Check if the file format is supported
if not filename.lower().endswith(supported_formats):
print(f"--- Skipping: {filename} (unsupported file type)")
continue
try:
# Create full input and output paths
input_path = os.path.join(input_dir, filename)
output_path = os.path.join(output_dir, filename)
# Open the image
with Image.open(input_path) as img:
# Get original image's width and height
width, height = img.size
# Calculate the new height while maintaining the aspect ratio
aspect_ratio = height / width
new_height = int(new_width * aspect_ratio)
# Resize the image
resized_img = img.resize((new_width, new_height))
# Save the image (maintaining transparency for PNGs)
if filename.lower().endswith('.png'):
resized_img.save(output_path, 'PNG')
else:
# For JPEGs, you can specify the quality (default is 75)
# Convert to RGB to prevent errors when saving JPEGs
resized_img.convert('RGB').save(output_path, 'JPEG', quality=90)
print(f"β Success: Resized {filename} to {new_width}x{new_height}")
except Exception as e:
print(f"Γ Error: A problem occurred while processing {filename} - {e}")
print("All processing complete.")
# --- This is where the program execution starts ---
if __name__ == "__main__":
# Specify the input and output folder paths
INPUT_FOLDER = 'input_images'
OUTPUT_FOLDER = 'output_images'
# Specify the target width for resizing
TARGET_WIDTH = 800
# Run the function
resize_images_in_folder(INPUT_FOLDER, OUTPUT_FOLDER, TARGET_WIDTH)
Open the `output_images` folder. If you see a whole row of resized images, it's a great success!
Finally: Programming is Magic That Solves "Tedious" Problems
This time, we used Python and Pillow to create a tool that automates the boring task of resizing images. Programming might sound difficult, but when you have a goal like "solving a tedious problem around me," it suddenly becomes fun and a very practical skill.
I would be overjoyed if this article leads to your own "I did it!" success story and becomes your first step into the world of programming. Please try experimenting with different settings and modify it into your very own tool!
To the Next Step
Now that you've experienced the convenience of Python in this article, you're probably eager to take the next step. Next time, why not try connecting with an external service to do something even more interesting?
The following article explains how to create a command-line app that gets the weather forecast using a Web API. Let's use the knowledge you gained today to aim for even greater skills!