Of course! Here's a comprehensive guide to using the Pillow library (a fork of PIL) in Python 3.5.

What is Pillow?
Pillow is the friendly fork of the Python Imaging Library (PIL). PIL was the original go-to library for image processing in Python, but it has been inactive for many years. Pillow was created to continue its development and is now the de-facto standard for image manipulation in Python.
It allows you to:
- Open, manipulate, and save many different image file formats (JPEG, PNG, GIF, BMP, TIFF, etc.).
- Perform operations like resizing, cropping, rotating, and drawing.
- Apply filters and color transformations.
- Extract image metadata (like EXIF data from photos).
Installation
Since Pillow is a third-party library, you need to install it using pip. The package name is Pillow (with a capital 'P').
Open your terminal or command prompt and run:

pip install Pillow
If you have multiple Python versions, you might need to be more specific:
python3.5 -m pip install Pillow
Basic Usage: Opening and Saving an Image
The main entry point to Pillow is the Image module, which you import from the PIL package.
Let's start with the most common tasks: opening an image, displaying it, and saving it.
Example: basic_ops.py
from PIL import Image
try:
# --- 1. Open an image file ---
# Replace 'my_image.jpg' with the path to your image file.
# The image will be loaded into a 'Image' object.
img = Image.open('my_image.jpg')
# --- 2. Display basic information about the image ---
print(f"Filename: {img.filename}")
print(f"Format: {img.format}") # e.g., JPEG, PNG
print(f"Mode: {img.mode}") # e.g., RGB, L (grayscale), RGBA
print(f"Size: {img.size}") # A tuple (width, height) in pixels
print(f"Width: {img.width}")
print(f"Height: {img.height}")
# --- 3. Display the image (requires a GUI) ---
# This will open the image in your default image viewer.
# img.show()
# --- 4. Save the image to a new file ---
# You can save it in a different format.
# For example, convert a JPEG to a PNG.
img.save('converted_image.png')
print("\nImage saved as 'converted_image.png'")
except FileNotFoundError:
print("Error: The file 'my_image.jpg' was not found.")
print("Please make sure you have an image file in the same directory, or provide the full path.")
except Exception as e:
print(f"An error occurred: {e}")
To run this, save it as basic_ops.py and place an image named my_image.jpg in the same folder. Then run:
python3.5 basic_ops.py

Common Image Manipulations
This is where Pillow really shines. Let's explore some common operations.
Resizing an Image
You can resize an image by specifying a new size (width, height) or using a scaling factor.
from PIL import Image
# Assuming 'img' is an Image object loaded previously
# For this example, let's create a new one
img = Image.open('my_image.jpg')
# Resize to a specific size (width, height)
resized_img = img.resize((800, 600))
# Resize using a thumbnail (maintains aspect ratio)
# The 'thumbnail' method modifies the image in-place.
# It will not make the image larger than the specified size.
img.thumbnail((300, 300))
print(f"New thumbnail size: {img.size}")
# Save the resized image
resized_img.save('resized_image.jpg')
Cropping an Image
Cropping is done using a 4-tuple (left, upper, right, lower) that defines the rectangle to keep.
from PIL import Image
img = Image.open('my_image.jpg')
# Define the crop box (left, upper, right, lower)
# This example crops a 400x400 square from the top-left corner.
crop_box = (0, 0, 400, 400)
cropped_img = img.crop(crop_box)
cropped_img.save('cropped_image.jpg')
Rotating an Image
You can rotate an image by a given angle (in degrees).
from PIL import Image
img = Image.open('my_image.jpg')
# Rotate 90 degrees counter-clockwise
rotated_img = img.rotate(90)
# Rotate 45 degrees and expand the canvas to fit the entire image
# If you don't use expand=True, parts of the image might be cut off.
rotated_img_expanded = img.rotate(45, expand=True)
rotated_img.save('rotated_image.jpg')
rotated_img_expanded.save('rotated_expanded_image.jpg')
Flipping an Image
Flipping is done with the transpose method.
from PIL import Image
img = Image.open('my_image.jpg')
# Flip horizontally (left to right)
flipped_horizontal = img.transpose(Image.FLIP_LEFT_RIGHT)
# Flip vertically (top to bottom)
flipped_vertical = img.transpose(Image.FLIP_TOP_BOTTOM)
flipped_horizontal.save('flipped_horizontal.jpg')
flipped_vertical.save('flipped_vertical.jpg')
Converting Between Color Modes
This is very useful for processing images. For example, converting a color image to grayscale.
from PIL import Image
img = Image.open('my_image.jpg')
# Convert to grayscale
grayscale_img = img.convert('L')
# Convert to a different mode, e.g., RGBA (adds an alpha channel for transparency)
rgba_img = img.convert('RGBA')
grayscale_img.save('grayscale_image.jpg')
rgba_img.save('rgba_image.png') # PNG supports transparency
Working with Pixels
You can access and manipulate individual pixels, although this can be slow for large images. The load() method returns a pixel access object.
from PIL import Image
# Create a new 100x100 black image
img = Image.new('RGB', (100, 100), color='black')
pixels = img.load()
# Change the color of the pixel at (x, y)
pixels[10, 20] = (255, 0, 0) # Set pixel to red
# Draw a white line
for x in range(100):
pixels[x, 50] = (255, 255, 255) # Set pixel to white
img.save('pixel_art.png')
Drawing on Images
Pillow includes a simple ImageDraw module for drawing shapes and text.
from PIL import Image, ImageDraw, ImageFont
# Create a new blank image
img = Image.new('RGB', (400, 200), color='lightblue')
draw = ImageDraw.Draw(img)
# Draw a rectangle
draw.rectangle([50, 50, 150, 150], fill='red', outline='darkred', width=5)
# Draw an ellipse (a circle if the box is square)
draw.ellipse([200, 50, 350, 150], fill='yellow', outline='orange', width=3)
# Draw text (requires a font file)
try:
# You may need to provide the path to a .ttf font file
# On Linux, common fonts are in /usr/share/fonts/
# On Windows, they are in C:\Windows\Fonts\
font = ImageFont.truetype("arial.ttf", 40)
draw.text((10, 10), "Hello Pillow!", fill='black', font=font)
except IOError:
# Fallback to a default font if the specific one isn't found
draw.text((10, 10), "Hello Pillow!", fill='black')
img.save('drawn_image.png')
Important Considerations for Python 3.5
- Compatibility: Pillow is generally very good at maintaining backward compatibility. Most code written for Pillow 2.x or 3.x will work fine in Python 3.5.
- Security: Be cautious when opening images from untrusted sources. While Pillow has many security features, malformed image files can sometimes cause issues. Always validate inputs if you're building a public-facing application.
- Performance: For very large images or complex, repetitive operations (like iterating over every pixel), pure Python with Pillow can be slow. For those cases, you might consider using a library like OpenCV, which is optimized for performance but has a different API.
Summary
Pillow is an incredibly powerful and easy-to-use library for image processing in Python. For Python 3.5, it remains the best choice for a wide range of tasks, from simple resizing and format conversion to complex pixel manipulation and drawing. The key is to start with the Image.open() method to get an Image object and then use its methods and the modules in the PIL package to perform your desired operations.
