Working with lots of images? Whether you’re handling user-uploads, prepping assets for the web, or just cleaning up a folder of photos, automating conversion and compression will save you hours of manual work—and bandwidth!

In this tutorial you’ll learn how to:

  1. Batch-convert any image (PNG, WEBP, TIFF, BMP…) to JPEG

  2. Optimize the resulting JPEGs for web-friendly file sizes

  3. Package it all into a one-file Python script

🛠️ Prerequisites:

  • Python 3.6+ installed on your machine

  • Basic comfort with the command line

  • (Optional) A virtualenv or Conda environment

pip install pillow

📂 Project Structure:

Create a folder called image-converter with two subfolders:

image-converter/
├─ input_images/    ← put your source files here
└─ output_images/   ← optimized JPGs will land here

🔥 The Script:

Create convert_images.py in image-converter/ and paste:

from PIL import Image
import os
import sys

# 1️⃣ Determine script’s own directory
BASE_DIR = os.path.dirname(os.path.abspath(__file__))

# 2️⃣ Define input/output folders
input_folder  = os.path.join(BASE_DIR, 'input_images')
output_folder = os.path.join(BASE_DIR, 'output_images')

# 3️⃣ Sanity checks
if not os.path.isdir(input_folder):
    print(f"❌ Input folder not found: {input_folder}")
    sys.exit(1)
os.makedirs(output_folder, exist_ok=True)

# 4️⃣ Gather images
valid_exts = ('png', 'webp', 'jpeg', 'jpg', 'tiff', 'bmp')
files = [f for f in os.listdir(input_folder)
         if f.lower().endswith(valid_exts)]

if not files:
    print("❌ No images found in", input_folder)
    sys.exit(1)

print(f"🔍 Found {len(files)} image(s):")
for f in files: print("  •", f)

# 5️⃣ Conversion loop
for fname in files:
    src_path = os.path.join(input_folder, fname)
    img = Image.open(src_path).convert('RGB')   # ensure JPEG-compatible

    base, _ = os.path.splitext(fname)
    dst_path = os.path.join(output_folder, f"{base}.jpg")

    # quality=85 is usually a sweet spot; optimize=True shrinks a bit more
    img.save(dst_path, "JPEG", quality=85, optimize=True)
    print(f"✅ Saved: {dst_path}")

print(f"\n🎉 Done! Converted & optimized {len(files)} files.")

🚀 How It Works

  1. Absolute paths
    We compute BASE_DIR so you can run the script from anywhere, and it will always locate the right folders.

  2. File filtering
    We only pick files with common image extensions—even skips over stray text files or hidden folders.

  3. RGB conversion
    JPEG doesn’t support alpha/transparency. Converting to RGB ensures no errors.

  4. Quality & optimization

    • quality=85 retains visual fidelity with ~30–50% smaller size than 100.
    • optimize=True applies an extra compression pass.

✅ Running It

  1. Drop all your images into input_images/.

  2. From the terminal (inside image-converter/):

python convert_images.py

Hope this saves you time and bandwidth. If you 💚 it, give it a clap, and drop any questions or improvements below!