Unit 12.1A · Term 1

PIL Image Basics

Learn how Python treats an image as both a file and a grid of pixels. With Pillow you can load, create, inspect, resize, crop, rotate, convert, edit and save images.

Learning Objectives

  • 12.6.2.2 Use commands of module Image in PIL library (load, create, size, save) to manipulate images

Lesson Presentation

12.1A-pil-image-basics.pdf · Slides for classroom use

Conceptual Anchor

The Digital Photo Lab

Pillow is your digital photo lab. Image.open() takes a photo from storage, Image.new() prepares a blank canvas, .size measures it, image methods transform it, and .save() writes the result back to a file.

Image.open()Load an existing image
img.sizeInspect width and height
resize / cropTransform the image
getpixel()Read or change pixels
img.save()Save the final result

Images Are Pixel Grids

Every pixel has a coordinate (x, y). In Pillow, (0, 0) is at the top-left. x increases to the right and y increases downward.

Coordinate System

The coordinate order is always (x, y).

(0, 0)
(3, 2)
(6, 5)

Width × Height

img.size returns (width, height).

width = 640 px height = 360 px
Pythonw, h = img.sizeResultw = 640, h = 360

Important

For an image of size (640, 360), valid pixel coordinates run from x = 0...639 and y = 0...359.

Image Modes

The image mode tells Pillow how pixel values are stored. RGB uses the same Red, Green and Blue channel values from the previous lesson.

RGB3 channels
RGBA4 channels
Lgrayscale
1black / white
Mode Meaning Typical pixel value
"RGB" Red, Green and Blue (142, 87, 201)
"RGBA" RGB + Alpha transparency (142, 87, 201, 128)
"L" 8-bit grayscale 0...255
"1" Binary black and white black / white

Core Image Commands

Installing Pillow

# Install once in your terminal pip install Pillow # Import in Python from PIL import Image
Command Purpose Example
Image.open(path) Open an image file img = Image.open("photo.jpg")
Image.new(mode, size, color) Create a new image Image.new("RGB", (400,300), (255,0,0))
img.size Read (width, height) w, h = img.size
img.mode Read the image mode print(img.mode)
img.save(path) Save to a file img.save("output.png")
img.show() Open a preview img.show()
img.resize((w, h)) Return a resized copy small = img.resize((320,180))
img.crop(box) Return a selected rectangle part = img.crop((50,40,250,180))
img.rotate(angle) Return a rotated copy turned = img.rotate(45, expand=True)
img.convert(mode) Convert image mode gray = img.convert("L")

Interactive Image Lab

Use the buttons to preview common Pillow operations. The browser animation is only a visual model; the Python command below is what you would write with Pillow.

Original image: 480 × 300 pixelsimg = Image.open("scene.png")
original

480 × 300

resize()

new dimensions

crop()

selected region

rotate()

turned copy

Resize, Crop & Rotate

1 Resize

resize() expects a new (width, height) tuple and returns a new image object.

from PIL import Image img = Image.open("landscape.jpg") small = img.resize((320, 180)) small.save("landscape_small.png")

2 Crop

The crop box is (left, upper, right, lower).

Crop Box

(left, upper) (right, lower)

Python

img = Image.open("photo.jpg") box = (100, 60, 420, 260) cropped = img.crop(box) cropped.save("cropped.png")

Crop width = right - left
Crop height = lower - upper

3 Rotate

img = Image.open("photo.jpg") rotated = img.rotate(45, expand=True) rotated.save("rotated.png")

Why expand=True?

At angles such as 45°, corners may fall outside the original canvas. expand=True enlarges the output canvas so the full rotated image can fit.

Worked Examples

1 Open → Inspect → Resize → Save

from PIL import Image img = Image.open("landscape.jpg") print("Mode:", img.mode) print("Size:", img.size) thumbnail = img.resize((320, 180)) thumbnail.save("landscape_thumb.png")

2 Create a New Image

from PIL import Image red_img = Image.new( "RGB", (400, 300), (255, 0, 0) ) red_img.save("red_canvas.png")

output: red_canvas.png

3 Create a Gradient Pixel by Pixel

from PIL import Image img = Image.new("RGB", (256, 256)) for x in range(256): for y in range(256): img.putpixel((x, y), (x, y, 128)) img.save("gradient.png")

R changes with x · G changes with y

4 Convert to Grayscale

from PIL import Image img = Image.open("photo.jpg") gray = img.convert("L") gray.save("photo_gray.png") print(gray.mode) # L

Pixel Explorer

Hover over or tap a pixel. The readout shows what img.getpixel((x, y)) would return.

Selected Pixel
Coordinate
(3, 4)
RGB
(109, 158, 197)
Python
img.getpixel((3, 4))

5 Read and Change a Pixel

from PIL import Image img = Image.open("photo.jpg").convert("RGB") pixel = img.getpixel((10, 20)) print(pixel) img.putpixel((10, 20), (255, 255, 255)) img.save("edited.png")

From One Pixel to a Whole Image

Once you can read and write one pixel, nested loops can process every (x, y) position.

6 Invert Every RGB Pixel

from PIL import Image img = Image.open("photo.jpg").convert("RGB") w, h = img.size for x in range(w): for y in range(h): r, g, b = img.getpixel((x, y)) img.putpixel((x, y), (255-r, 255-g, 255-b)) img.save("inverted.png")
(142, 87, 201)
(113, 168, 54)

Each channel becomes 255 - value

Why convert to RGB first?

An input file may use another mode. .convert("RGB") makes each pixel predictable so it can be unpacked as r, g, b.

Video Demonstration

Working with Images Using Pillow

Practical demonstration of loading, resizing, rotating, cropping and processing images in Python.

Common Pitfalls

resize(), crop(), rotate() and convert() return new images

Store the result: small = img.resize((200, 100)).

Width/height vs x/y

img.size is (width, height); pixel coordinates are (x, y).

Wrong crop-box order

Use (left, upper, right, lower), not (x, y, width, height).

Pixel mode mismatch

r, g, b = img.getpixel(...) assumes RGB-like pixels. Convert when necessary: img = img.convert("RGB").

Distorted aspect ratio

Changing a 16:9 image directly to a square changes its proportions. Decide whether stretching is acceptable before resizing.

Practice Tasks

Remember

Create an 800×500 RGB image with colour (30, 144, 255).

Understand

An image is (1200, 800). State the largest valid x-coordinate and y-coordinate.

Apply

Load an image, print its mode and size, resize it to 400×300, and save it as small.png.

Apply

Crop the rectangle from (100, 50) to (500, 350) and save it as crop.png.

Analyze

Explain why (100, 50, 400, 300) does not mean x=100, y=50, width=400, height=300 in crop().

Analyze

Swap the red and blue values of every pixel: (r, g, b) → (b, g, r).

Create

Build a pipeline: open → crop → resize → grayscale → rotate → save.

Self-Check Quiz

Q1: What does Image.open("photo.jpg") do?

It opens and identifies the image file and returns a Pillow image object.

Q2: What does img.size return?

A tuple (width, height) in pixels.

Q3: Where is coordinate (0, 0)?

At the top-left corner of the image.

Q4: What does img.crop((10, 20, 110, 80)) select?

left=10, upper=20, right=110, lower=80; the result is 100×60 pixels.

Q5: Why might you use img.convert("RGB") before pixel processing?

To make each pixel predictable as Red, Green and Blue channel values that can be unpacked as r, g, b.

Q6: Does img.resize((200, 100)) change img itself?

No. Assign the returned copy: small = img.resize((200, 100)).