PIL
Python Imaging Library
picture size
image processing
Python programming

How do I get the picture size with PIL?

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

Getting image dimensions is one of the most common tasks in image pipelines. With Pillow, the actively maintained fork of PIL, you can read width and height without loading full pixel data into memory in many formats. This is useful for validation, thumbnail workflows, and dataset quality checks.

Read Width and Height with Pillow

The fastest path is opening the file with Image.open and reading the size property. size returns a two-item tuple containing width and height in pixels.

python
1from pathlib import Path
2from PIL import Image
3
4
5def get_image_size(path: Path) -> tuple[int, int]:
6    with Image.open(path) as img:
7        width, height = img.size
8        return width, height
9
10
11if __name__ == "__main__":
12    file_path = Path("./assets/photo.jpg")
13    w, h = get_image_size(file_path)
14    print(f"{file_path.name}: {w}x{h}")

Using a context manager ensures the file handle closes immediately, which matters when processing many files.

Validate Dimensions in Upload Pipelines

A typical web workflow checks dimensions before accepting user uploads. You can enforce min and max limits and return clear validation errors.

python
1from pathlib import Path
2from PIL import Image, UnidentifiedImageError
3
4
5MAX_WIDTH = 3840
6MAX_HEIGHT = 2160
7MIN_WIDTH = 200
8MIN_HEIGHT = 200
9
10
11def validate_image(path: Path) -> tuple[bool, str]:
12    try:
13        with Image.open(path) as img:
14            width, height = img.size
15
16        if width < MIN_WIDTH or height < MIN_HEIGHT:
17            return False, f"Image too small: {width}x{height}"
18
19        if width > MAX_WIDTH or height > MAX_HEIGHT:
20            return False, f"Image too large: {width}x{height}"
21
22        return True, "ok"
23    except UnidentifiedImageError:
24        return False, "Not a valid image file"
25
26
27if __name__ == "__main__":
28    result, message = validate_image(Path("./uploads/avatar.png"))
29    print(result, message)

This pattern is easy to integrate in API handlers before persisting files.

Batch Processing and Reporting

For data teams, a single-file check is rarely enough. Batch scanning helps detect inconsistent sources before model training or media generation.

python
1from pathlib import Path
2from PIL import Image
3
4
5def scan_directory(root: Path) -> list[tuple[str, int, int]]:
6    rows: list[tuple[str, int, int]] = []
7
8    for path in root.rglob("*"):
9        if path.suffix.lower() not in {".jpg", ".jpeg", ".png", ".webp"}:
10            continue
11        try:
12            with Image.open(path) as img:
13                w, h = img.size
14            rows.append((str(path), w, h))
15        except Exception as exc:
16            print(f"Skipping {path}: {exc}")
17
18    return rows
19
20
21if __name__ == "__main__":
22    records = scan_directory(Path("./dataset/images"))
23    for record in records[:5]:
24        print(record)
25    print(f"Scanned {len(records)} images")

Once you have a table of dimensions, you can identify outliers and standardize resize rules.

Orientation and Metadata Considerations

A subtle detail is EXIF orientation. Some photos from phones can report one width and height pair while intended display orientation is rotated. If your downstream task depends on display orientation, normalize using ImageOps.exif_transpose before measuring.

python
1from PIL import Image, ImageOps
2
3with Image.open("./assets/camera_photo.jpg") as img:
4    normalized = ImageOps.exif_transpose(img)
5    print("raw size:", img.size)
6    print("display size:", normalized.size)

For strict computer vision preprocessing, document whether you use raw metadata dimensions or normalized display dimensions so every stage is consistent.

Performance Notes

Reading metadata is much cheaper than decoding full arrays, but it still does file I/O. If you have massive datasets, avoid reopening the same file repeatedly in separate pipeline steps. Cache results or produce a single manifest file that all jobs consume.

Also keep error handling explicit. Corrupt files, truncated downloads, and renamed non-image files happen often in real-world datasets. Robust scanning code should skip invalid inputs while recording enough context for cleanup.

Common Pitfalls

The most common mistake is forgetting to close image files, which can exhaust file descriptors in large scans. Another issue is assuming every path with an image extension is valid image content. You should catch UnidentifiedImageError and continue. Teams also overlook EXIF orientation and end up with inconsistent width and height logic between upload validation and UI rendering. Finally, avoid reading image size after converting to another format unless conversion is intentional, since dimensions can change during preprocessing steps such as crop or resize.

Summary

  • Use Image.open and .size for a direct width-height lookup.
  • Always open images with a context manager for safe file handling.
  • Add dimension validation rules for upload pipelines.
  • Batch scan directories to detect outliers and corrupt files early.
  • Decide clearly between raw metadata size and EXIF-normalized display size.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.