If you have more than a few images to process, or you want resizing built into an app, Python’s Pillow library is a good starting point. It’s small, well documented and handles most formats.

Install Pillow

pip install Pillow

Resize to exact dimensions

from PIL import Image

img = Image.open("photo.jpg")
resized = img.resize((800, 600), Image.Resampling.LANCZOS)
resized.save("photo-800x600.jpg", quality=85)

resize() forces the exact size you give it. If the new proportions don’t match the original, the image will be stretched. Use it when you’ve already decided the shape. On older Pillow versions, the resampling constant may be written as Image.LANCZOS.

Keep the aspect ratio with thumbnail()

from PIL import Image

img = Image.open("photo.jpg")
img.thumbnail((1200, 1200))
img.save("photo-small.jpg", quality=80, optimize=True)

thumbnail() shrinks the image so it fits inside the box you give, keeping proportions. It changes the image in place, and it never enlarges, which is usually what you want. The ratio logic is explained in what is aspect ratio.

Fix phone photos that come out sideways

Photos from phones often rely on an EXIF orientation tag. If you resize and save without handling it, the image may appear rotated. Pillow has a helper for this:

from PIL import Image, ImageOps

img = Image.open("phone-photo.jpg")
img = ImageOps.exif_transpose(img)
img.thumbnail((1600, 1600))
img.save("phone-photo-small.jpg", quality=82)

More on that tag in what is EXIF data.

Convert PNG with transparency to JPG

JPG can’t store transparency, so convert the image mode first, or Pillow will raise an error:

img = Image.open("logo.png").convert("RGB")
img.save("logo.jpg", quality=85)

Transparent areas will turn black. To get a white background, paste the image onto a white canvas first. See converting PNG to JPG for why this happens.

Batch resize a folder

from pathlib import Path
from PIL import Image, ImageOps

src = Path("originals")
dst = Path("resized")
dst.mkdir(exist_ok=True)

for path in src.glob("*.jpg"):
    img = ImageOps.exif_transpose(Image.open(path))
    img.thumbnail((1600, 1600))
    img.save(dst / path.name, quality=80, optimize=True)

Saving into a separate folder means your originals stay untouched, which is the safest habit. See common resizing mistakes.

Save as WebP

img.save("photo.webp", quality=80)

WebP support depends on how Pillow was built, but standard installs usually include it. Why it’s worth it is covered in converting images to WebP.

Choosing a resampling filter

Lanczos gives sharp results for shrinking photos. Bicubic is a good all-rounder. Nearest is for pixel art. Details are in resampling methods.

When code isn’t worth it

Prefer the terminal? See resizing images with ImageMagick.

For a one-off job, writing a script takes longer than using a tool. Try our free online image resizer and keep Python for the repetitive work.

Leave a Reply

Your email address will not be published. Required fields are marked *