thecodex.expert · The Codex Family of Knowledge
Tier 3 · Upper-Intermediate · Python Project

Batch Image Resizer

Resize a whole folder of images to a target size, keeping their proportions. Learn batch processing and working with a real library.

🧠 Teaches how to think spoonfed, every age Last verified:

1 The Problem

We want a batch image resizer: point it at a folder, and it resizes every image to fit within a target size — keeping each image’s proportions so nothing is squashed — saving the results to an output folder. It teaches batch processing and using a real third-party library (Pillow).

Where this shows up: preparing images for the web, generating thumbnails, photo workflows, content pipelines. Batch-processing files with a specialised library is a common, practical automation.

2 How to Think About It

Think about resizing without distortion, before any code:

The plan — in plain English
1. Find every image in the input folder. → 2. For each, work out the scale that fits it within the target while keeping its width-to-height ratio. → 3. Resize and save to the output folder. → The key rule: scale by the same factor in both directions so the image is never squashed.

Find images in folder

For each image

Compute scale to fit target

Keep aspect ratio

Resize image

Save to output folder

3 The Build — explained part by part

Here is the complete resizer. It uses Pillow (pip install Pillow). The proportion maths is pulled out so we can test it without real images. Each part is explained below.

Pythonresize.py
from pathlib import Path
from PIL import Image      # pip install Pillow

def fit_size(width, height, max_size):
    # Scale so the longest side equals max_size, keeping proportions.
    scale = max_size / max(width, height)
    if scale >= 1:
        return (width, height)      # already small enough
    return (round(width * scale), round(height * scale))

def resize_folder(input_dir, output_dir, max_size=800):
    out = Path(output_dir)
    out.mkdir(exist_ok=True)
    for path in Path(input_dir).glob("*.jpg"):
        image = Image.open(path)
        new_size = fit_size(image.width, image.height, max_size)
        resized = image.resize(new_size)
        resized.save(out / path.name)

if __name__ == "__main__":
    resize_folder("photos", "resized", 800)
    print("Done resizing.")
What each part does — in plain words
from PIL import Image — Pillow, the standard Python imaging library. Image.open loads a picture; .resize changes its size; .save writes it out.

fit_size(width, height, max_size) — the maths, isolated so it is testable. scale = max_size / max(width, height) finds the factor that makes the longest side equal max_size.

if scale >= 1: return (width, height) — if the image is already smaller than the target, leave it alone — never blow images up.

round(width * scale), round(height * scale) — apply the same scale to both dimensions, so proportions are preserved and the image is not squashed.

resize_folder — the batch loop: find every .jpg, compute its new size, resize, and save to the output folder.
Common mistakes — and how to avoid them
✗ Resizing to a fixed size like 800x800 — non-square images get squashed.
✓ Scale both sides by the same factor to keep proportions.
✗ Blowing small images up to the max — they become blurry.
✓ Skip resizing when the image is already smaller (scale >= 1).
✗ Saving over the originals — you lose the full-size versions.
✓ Write to a separate output folder.

4 Test & Prove Each Part

Image files are awkward to test, so we test the proportion maths — the part most likely to have bugs — without any real images.

A wide image scales to fit, keeping proportions
A small image is left unchanged
The aspect ratio is preserved after resizing
Pythontest_resize.py
def fit_size(width, height, max_size):
    scale = max_size / max(width, height)
    if scale >= 1:
        return (width, height)
    return (round(width * scale), round(height * scale))


def test_scales_down():
    """A 1600x800 image fits to 800 on its longest side."""
    assert fit_size(1600, 800, 800) == (800, 400)


def test_small_unchanged():
    """An image already small enough is unchanged."""
    assert fit_size(400, 300, 800) == (400, 300)


def test_ratio_preserved():
    """The width-to-height ratio survives resizing."""
    w, h = fit_size(1000, 500, 500)
    assert w / h == 1000 / 500

Run with pytest -v. By isolating fit_size, we test the crucial proportion logic with plain numbers — no image files needed. The ratio-preserved test guarantees images never come out squashed.

5 The Interface

INPUTfolder + max sizeimages to resize
Call
resize_folder("photos", "resized", 800)
OUTPUTresized imagesproportional, in output folder
Result
resized/photo1.jpg  (was 4000x3000, now 800x600)

6 Run It & Automate It

Run it locally
pip install Pillow
python3 resize.py
Put .jpg files in a photos/ folder; resized copies appear in resized/.

Jenkins runs the tests automatically — each line explained below.

What you should see when it works
Terminala real run
Done resizing.
# resized/ now holds proportionally-shrunk copies of every image
If it breaks — how to fix it
🚨 ModuleNotFoundError: No module named 'PIL'.
Install Pillow: pip install Pillow.
🚨 Images look squashed.
You used a fixed size. Use fit_size to scale both dimensions by the same factor.
GroovyJenkinsfile
// Jenkinsfile — automated tests on every change.
pipeline {
    agent any
    stages {
        stage('Get the code') { steps { checkout scm } }       // download the code
        stage('Install') { steps { sh 'python3 -m venv venv && . venv/bin/activate && pip install pytest' } }  // test tool
        stage('Test') { steps { sh '. venv/bin/activate && pytest -v' } }   // run every test
    }
    post {
        success { echo 'All tests passed.' }
        failure { echo 'A test failed — look above.' }
    }
}
🎯 Try this next — make it yours
  1. More formats. Handle PNG and others, not just JPG. (Teaches: globbing multiple patterns.)
  2. Thumbnails. Also make tiny square crops. (Teaches: cropping.)
  3. Progress. Show how many images processed. (Teaches: progress reporting.)
What you learned
You learned batch processing with a real third-party library (Pillow), and the important habit of isolating pure logic (the proportion maths) from library calls so it stays testable. Resizing proportionally — never squashing — is the key rule. Related: pathlib.