If you run an online shop or handle marketing, you have been here before: a few hundred product photos arrive, and every single one needs the same treatment — resized to one dimension, compressed below a certain file size, stamped with your company watermark, and finally converted into a web-friendly format. Opening, editing and re-saving each file by hand is bearable for ten images. By the hundredth, you want to give up.
Yet this kind of "same set of steps, repeated hundreds of times" work is exactly what a computer does best. With Pillow, Python's image-processing library, roughly twenty lines of code will process an entire folder in one go — you can go and make a coffee, and come back to a finished job.
What is Pillow, and why learn it?
Pillow is the most widely used image library for Python (it was originally called PIL). It can open images, resize, crop, rotate, adjust brightness, draw text watermarks, convert formats and compress. In short, it covers everything you use day to day in an image editor — and it is free, open source, and driven entirely by code. Because it is code-driven, it can work in bulk: processing a hundred images is exactly the same procedure as processing one. The only difference is a loop.
Step 1: Install Pillow
Open Command Prompt on Windows and run a single line:
That is it — your Python installation can now handle images, with no software to buy.
Step 2: Learn the three basic moves
Every batch job is built from three actions: open, edit, and save.
As simple as that. resize() sets the dimensions, and quality=80 inside save() controls compression (1 to 100 — the lower the number, the smaller the file).
Step 3: Process an entire folder
Once you can handle one image, adding a loop turns it into batch work. Say you have a folder called photos and you want every image inside resized to 800×800, compressed, and written into a new folder called output:
Line by line
- glob.glob("photos/*") — grabs every file in the folder at once, so you never have to count them yourself.
- path.lower().endswith(IMG_EXTS) — keeps images only; spreadsheets, PDFs and hidden files are skipped automatically.
- convert("RGB") — normalises the colour mode; some PNGs carry a transparency channel and will throw an error if saved as JPG without this.
- resize(..., Image.LANCZOS) — picks the highest-quality resampling filter, so downscaled images stay crisp.
- try / except — if one or two files are corrupt, the script carries on instead of dying halfway and wasting the run.
- optimize=True — asks Pillow for an extra squeeze, usually a few percent smaller, at no cost.
Adding a company watermark
A watermark is simply a small logo pasted onto a larger image. Prepare a logo with a transparent background (PNG), then:
Note the third argument to paste(): passing the logo itself as the mask is what makes the transparent area show the photo underneath. Skip it and you get an ugly white box.
Convert to WebP for a faster website
If you run a website, converting photos to WebP typically makes them about thirty percent smaller than JPG with no visible difference — so pages load faster. The change is minimal: just alter the filename and format on save.
Pillow picks the format from the filename, so there is nothing extra to install and no need to upload files to an online converter one by one.
Five practical tips
- Back up the originals — always write results to a new folder rather than overwriting the source. You get room to experiment and nothing is lost if something goes wrong.
- Think in "long edge" — product photos come in different aspect ratios, and forcing them into a square stretches them. To keep proportions, scale the long edge only, or crop to square first.
- Phone photos can appear upside down — handset photos carry rotation metadata (EXIF). One line, ImageOps.exif_transpose(img), puts them the right way up.
- Start at quality 80 — JPG quality 80 is usually indistinguishable from 100 by eye but halves the file size. Below 70 you start to see blocky artefacts, so there is no reason to start at 100.
- It is faster than you think — Pillow processes an 800px image in a few milliseconds; a thousand images take tens of seconds. Far quicker than doing it by hand.
Summary
Python Tutorial: This article started from the three simplest moves — open, resize, save — and worked up to processing an entire folder, stamping a company watermark, and converting to WebP to save space. The core idea is a single sentence: find the task you repeat, and hand it to Python to run through a loop in one pass. Next time you face "a few hundred images that all need the same treatment", stop opening an image editor for every file — write twenty lines, set your parameters, run it once, and reuse the script every month after that.