Get AI summaries of any video or article — Sign up free
Python Tutorial: Image Manipulation with Pillow thumbnail

Python Tutorial: Image Manipulation with Pillow

Corey Schafer·
4 min read

Based on Corey Schafer's video on YouTube. If you like this content, support the original creators by watching, liking and subscribing to their content.

TL;DR

Install Pillow using the OS-specific documentation steps, and be ready to install additional dependencies (e.g., via Homebrew on macOS) before running `pip install pillow`.

Briefing

Pillow turns Python into a practical image-processing tool, letting developers batch-display, convert, resize, and transform images without manual editing. The core payoff is automation: instead of resizing every upload by hand, a script can generate the exact derivative files a website needs—different formats, thumbnail sizes, and gallery-ready versions—directly from a folder of originals.

Getting started is straightforward but not entirely “pip-only.” After installing Pillow (via the Pillow documentation’s OS-specific instructions), the workflow may require additional external libraries—on macOS, the tutorial uses Homebrew to install those dependencies—then verifies the install by importing Image from PIL (e.g., `from PIL import Image`). Once the import works, the tutorial demonstrates the basic pattern: open an image file into an Image object, perform an operation, and save the result.

The first concrete example is format conversion. An image is opened with `Image.open(...)`, displayed using `image.show()`, then saved as a different extension using `image.save(...)`—switching from `pup one.jpeg` to `pup one.png`. After confirming the new file exists and opens correctly, the script deletes the PNG to keep the workspace clean.

Batch processing is where Pillow becomes especially valuable. The tutorial loops through all files in the current directory using `os.listdir('.')`, filters for JPEGs by checking filename endings, and for each match opens the image, splits the base name and extension with `os.path.splitext`, and saves a converted PNG into a dedicated output folder (e.g., `pngs/`). This produces a parallel set of images with consistent naming.

Next comes resizing for web use while preserving aspect ratio. The script defines a target size as a tuple (e.g., `(300, 300)`), creates an output directory for that size (e.g., `300/`), and applies `image.thumbnail(size)` before saving. Filenames are updated to include the size suffix (e.g., `originalname_300.jpeg`), making it easy to map derivatives back to originals. The same logic scales to multiple requirements: adding a 700-pixel variant is done by duplicating the step with a new size and output folder, producing both 300 and 700 versions quickly.

Finally, the tutorial broadens the toolkit beyond resizing and format changes. It demonstrates single-image transformations: rotating an image by 90 degrees with `image.rotate(90)`, converting to black-and-white using `image.convert(mode='L')`, and applying a Gaussian blur via `ImageFilter.GaussianBlur(radius=...)`. It highlights that blur strength depends on parameters (default blur is subtle; increasing the radius to around 15 makes the effect clearly visible).

Overall, Pillow is presented as a workflow enabler for image pipelines—especially for websites—where consistent derivative images (thumbnails, galleries, and resized formats) can be generated automatically from uploaded files using a small set of repeatable operations and the official documentation for parameter values.

Cornell Notes

Pillow lets Python scripts open images, transform them, and write new files—ideal for automating the repetitive work of preparing images for websites. After installing Pillow (and any required OS dependencies), images are loaded with `Image.open`, previewed with `image.show`, and saved with `image.save` in a chosen format. Batch conversion and resizing use `os.listdir` to iterate through files, filter by extension, and then apply operations like `image.thumbnail((w, h))` while keeping aspect ratio. The same approach scales to multiple sizes (e.g., 300 and 700) by running the resize-and-save step into different output folders. Additional transformations include rotation, black-and-white conversion, and Gaussian blur using `ImageFilter.GaussianBlur` with adjustable radius.

What is the basic Pillow workflow for changing an image file?

Create an Image object with `Image.open('filename')`, optionally preview it with `image.show()`, apply a transformation (e.g., `image.thumbnail(size)` or `image.rotate(90)`), then write the result with `image.save('new_filename.ext')`. The tutorial uses this pattern for format conversion (JPEG → PNG) and for resizing into size-specific folders.

How does the tutorial batch-process multiple images in one run?

It imports `os`, loops through filenames in the current directory with `for f in os.listdir('.')`, filters to only JPEGs using `if f.endswith('JPEG')`, then opens each file with `Image.open(f)`. It uses `os.path.splitext` to separate the base name from the extension so it can save derivatives with consistent naming into output directories like `pngs/`, `300/`, and `700/`.

How does resizing avoid squishing images?

Instead of forcing an exact width/height, it uses `image.thumbnail(size)` where `size` is a tuple like `(300, 300)`. Pillow’s `thumbnail` method preserves aspect ratio, producing a smaller image that fits within the bounding box rather than distorting the original proportions.

How can the script generate multiple thumbnail sizes efficiently?

By repeating the same resize-and-save logic for each target size. The tutorial sets one size variable (e.g., 300), saves into a `300` folder with filenames like `name_300.jpeg`, then adds another pass for 700 into a `700` folder with filenames like `name_700.jpeg`. This produces both sets quickly without manual editing.

What other image transformations are demonstrated besides resizing and format conversion?

Rotation with `image.rotate(90)`, black-and-white conversion with `image.convert(mode='L')`, and blurring with `ImageFilter.GaussianBlur(radius=...)`. The blur example shows that default parameters may be subtle, while increasing the radius (e.g., to 15) makes the blur effect much more noticeable.

Review Questions

  1. When converting a batch of JPEGs to PNGs, why is `os.path.splitext` useful for naming output files?
  2. What’s the difference between using `image.thumbnail((w, h))` and saving a resized image that forces exact dimensions?
  3. Which Pillow methods and parameters are used to rotate, convert to black-and-white, and apply Gaussian blur?

Key Points

  1. 1

    Install Pillow using the OS-specific documentation steps, and be ready to install additional dependencies (e.g., via Homebrew on macOS) before running `pip install pillow`.

  2. 2

    Use `from PIL import Image` to create an Image object with `Image.open(...)`, then preview with `image.show()` to confirm the file is loaded correctly.

  3. 3

    Convert formats by saving the same Image object with a different extension using `image.save('name.ext')` (e.g., JPEG to PNG).

  4. 4

    Batch operations can be automated by looping through directory contents with `os.listdir('.')` and filtering filenames by extension.

  5. 5

    Preserve aspect ratio during resizing by using `image.thumbnail((max_w, max_h))` rather than forcing exact dimensions.

  6. 6

    Generate multiple derivative sizes by running the same thumbnail-and-save step for each target size into separate output folders (e.g., `300/` and `700/`).

  7. 7

    Use Pillow transformations like `rotate`, `convert(mode='L')`, and `ImageFilter.GaussianBlur(radius=...)` to create rotated, black-and-white, and blurred variants.

Highlights

Pillow’s `image.thumbnail((w, h))` resizes images to fit within a bounding box while preserving aspect ratio—ideal for thumbnails.
A simple `os.listdir('.')` loop plus `Image.open` enables one-command conversion of an entire folder of JPEGs into PNGs or resized derivatives.
Gaussian blur strength depends heavily on the `radius` parameter; increasing it makes the effect clearly visible.
Output organization matters: saving derivatives into dedicated folders (like `pngs/`, `300/`, `700/`) keeps pipelines predictable and easy to deploy.

Topics

  • Pillow Installation
  • Image Format Conversion
  • Batch Image Processing
  • Thumbnail Resizing
  • Image Transformations