Latest Release: v12.2.0 — Security patches, WEBP improvements | v11.2.1 v10.4.0 | Python 3.9 – 3.13 supported
v12.2.0 Available Now

The Python Imaging
Library (PIL) Fork.

Python Pillow is the industry standard for image processing in Python. Open, resize, filter, convert, draw, and analyze images with a clean, expressive API — all in pure Python.

Install / Download Live Demo GitHub

Trusted by the ecosystem backing modern web & AI

Django FastAPI PyTorch Hugging Face Scikit-learn Ubuntu
12K+
GitHub Stars
30+
Image Formats
200M+
PyPI Downloads / Month
$0
Cost — MIT Licensed

Core Capabilities.

Everything you need to manipulate local and remote images inside Python pipelines.

🗂️

Extensive Format Support

Seamlessly open, read, and write JPEG, PNG, WEBP, GIF, TIFF, BMP, ICO, PSD, and 25+ more formats. Batch-convert massive ML datasets with single-line format migrations.

📐

Geometric Transforms

Resize, crop, rotate, flip, and transpose images. Use high-quality Lanczos resampling to retain visual fidelity at any scale.

🎨

Image Filtering

Apply BLUR, CONTOUR, SHARPEN, EDGE_ENHANCE, FIND_EDGES, EMBOSS, and custom kernel filters via the ImageFilter module.

✏️

Programmatic Drawing

Draw polygons, arcs, rectangles, and overlay TrueType/OpenType text with ImageDraw. Automate watermarks, captions, and thumbnail overlays at scale.

🧩 Core Modules.

Pillow's power comes from its modular design. Each module handles a distinct area of image processing.

📷

Image

The central class. Open, create, save, convert, resize, and transform images. Every pipeline starts here.

open()save()resize()crop()convert()
View Reference →
✏️

ImageDraw

Draw 2D graphics onto images. Supports lines, rectangles, ellipses, polygons, and text rendering.

line()rectangle()ellipse()text()
View Reference →
🔮

ImageFilter

Pre-built filters including GaussianBlur, UnsharpMask, MedianFilter, and custom kernel convolutions.

GaussianBlurSHARPENEDGE_ENHANCE
View Reference →

ImageEnhance

Adjust Brightness, Contrast, Color saturation, and Sharpness using a simple factor-based API.

BrightnessContrastColorSharpness
View Reference →
🔧

ImageOps

High-level operations: autocontrast, equalize, flip, grayscale, pad, fit, contain, and invert.

autocontrast()equalize()fit()grayscale()
View Reference →
🔠

ImageFont

Load TrueType (TTF) and OpenType (OTF) fonts for high-quality text rendering in generated images.

truetype()load_default()getbbox()
Official Reference →
🎛️

ImageChops

Channel operations: add, subtract, multiply, difference, composite — pixel-level arithmetic between images.

add()multiply()difference()
Official Reference →
📊

ImageStat

Compute statistics (mean, median, RMS, standard deviation, extrema) over entire images or pixel bands.

meanmedianrmsextrema
Official Reference →

📥 How to Install Pillow (PIL in Python 3)

Zero to processing in minutes. Select your operating system or package manager below.

Step 1

Install via PIP

Windows supplies pre-compiled binary wheels — no C++ compiler required. Run in PowerShell or Command Prompt.

powershell
$python -m pip install --upgrade Pillow
Verify

Verify Installation

Open the Python REPL and ensure PIL imports cleanly.

python
>>>import PIL
>>>print(PIL.__version__)
>>>from PIL import Image
Step 1

Install Library

Pillow provides native universal wheels for Apple Silicon (M1, M2, M3, M4) and Intel Macs.

terminal
$python3 -m pip install --upgrade Pillow
Optional

Homebrew Codecs (M1/M2/Intel)

For advanced format support (TIFF, JPEG 2000, WebP, AVIF) when compiling from source:

terminal
$brew install libjpeg libtiff openjpeg webp libimagequant
Step 1

System Dependencies

Install essential development libraries for JPEG and PNG support on Ubuntu/Debian:

bash
$sudo apt-get update && sudo apt-get install -y libjpeg-dev zlib1g-dev python3-dev
Step 2

Install via pip (Recommended)

Installs the latest Pillow wheel into your Python environment.

bash
$pip install --upgrade Pillow
Alt

APT System Package

Install system-wide package via Ubuntu repository:

bash
$sudo apt-get install python3-pil
Conda-Forge

Install in Anaconda / Conda

Recommended for Anaconda, Miniconda, and Miniforge environments via conda-forge:

conda
$conda install -c conda-forge pillow
Anaconda GUI

Anaconda Navigator

In Anaconda Navigator: go to Environments > search pillow > Check > Click Apply.

jupyter / prompt
[1]:from PIL import Image
img = Image.open("photo.jpg")
img # renders inline in Jupyter Notebook
Step 1

Create Virtual Env

Recommended: keep your project dependencies clean and isolated.

shell
$python -m venv venv
$source venv/bin/activate # Linux/macOS
$venv\Scripts\activate # Windows
Step 2

Install Pillow

With the virtual environment active, install Pillow normally.

shell
(venv) $pip install --upgrade Pillow

📦 Format Support Matrix.

All 30+ image formats supported across read, write, and animation dimensions.

⚡ Quick Code Cheatsheet

The most frequently used Python instructions for daily image processing tasks.

Open & Inspect

Load an image and verify its dimensions, format, and mode.

from PIL import Image
img = Image.open('file.jpg')
print(img.size, img.format, img.mode)

Display Image

Display in default OS viewer or inline inside Jupyter Notebook.

img.show() # OS Viewer
# In Jupyter Notebook:
display(img)

Black & White (Binary)

Convert to 8-bit grayscale ('L') or pure 1-bit binary ('1').

gray = img.convert('L')
# Pure binary threshold at 128:
bw = gray.point(lambda p: 255 if p > 128 else 0, '1')

Generate Thumbnails

Resize preserving aspect ratio in-place (no upscaling).

img.thumbnail((400, 400))
img.save('thumb.jpg')

Convert to WEBP

Save heavy PNGs/JPEGs as highly compressed WEBP.

img = img.convert("RGB")
img.save('file.webp', 'WEBP', quality=85)

Crop Geometry

Define a box tuple (left, upper, right, lower) to slice.

area = (100, 100, 400, 400)
cropped = img.crop(area)

Contour & Edges

Extract outline contours or sharp edges with ImageFilter.

from PIL import ImageFilter
contour = img.filter(ImageFilter.CONTOUR)

Screen Grab / Clipboard

Capture full screen, bounding box, or clipboard data.

from PIL import ImageGrab
screen = ImageGrab.grab()
clip = ImageGrab.grabclipboard()

Gaussian Blur

Apply smooth radius-based Gaussian blur.

from PIL import ImageFilter
blurred = img.filter(ImageFilter.GaussianBlur(radius=3))

Draw Text & Shapes

Overlay text using ImageDraw and a TrueType font.

from PIL import ImageDraw
draw = ImageDraw.Draw(img)
draw.text((20, 20), "Hello!", fill="white")

Enhance Brightness

Adjust brightness, contrast, color, or sharpness by factor.

from PIL import ImageEnhance
bright = ImageEnhance.Brightness(img).enhance(1.5)

Read EXIF Data

Extract camera metadata embedded in JPEG photos.

from PIL.ExifTags import TAGS
exif = img.getexif()
# Iterate tags and values

📖 Real-World Recipes & Pipelines

Copy–paste solutions for the most common Pillow, OpenCV, and Computer Vision use cases.

🤖

Python OCR: Pillow + OpenCV + Tesseract

Computer Vision

Complete OCR pipeline: pre-process image with OpenCV, extract text bounding boxes with Tesseract OCR, and annotate bounding boxes and labels with Pillow ImageDraw.

ocr_pipeline.py
from PIL import Image, ImageDraw, ImageFont import cv2, numpy as np, pytesseract # 1. Load & preprocess image via OpenCV img_cv = cv2.imread("document.png") gray = cv2.cvtColor(img_cv, cv2.COLOR_BGR2GRAY) thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] # 2. Extract OCR data with PyTesseract data = pytesseract.image_to_data(thresh, output_type=pytesseract.Output.DICT) # 3. Convert OpenCV (BGR) to Pillow (RGB) & annotate img_pil = Image.fromarray(cv2.cvtColor(img_cv, cv2.COLOR_BGR2RGB)) draw = ImageDraw.Draw(img_pil) for i in range(len(data["text"])): if int(data["conf"][i]) > 60 and data["text"][i].strip(): x, y, w, h = data["left"][i], data["top"][i], data["width"][i], data["height"][i] draw.rectangle([x, y, x + w, y + h], outline="red", width=2) draw.text((x, y - 12), data["text"][i], fill="red") img_pil.save("annotated_ocr.png")
🖤

Black & White vs Grayscale (Binary Image)

Thresholding

Transform color images into 8-bit Grayscale (256 shades), 1-bit Dithered B&W, or Pure Binary (custom threshold point mapping) for OCR and barcode preprocessing.

black_and_white.py
from PIL import Image img = Image.open("photo.jpg") # Option 1: 8-bit Grayscale (256 levels of gray) gray = img.convert("L") gray.save("grayscale.png") # Option 2: 1-bit Binary with Floyd-Steinberg dithering binary_dithered = img.convert("1") binary_dithered.save("dithered_bw.png") # Option 3: Pure Black & White Threshold (No Dithering, threshold=128) threshold = 128 pure_bw = gray.point(lambda p: 255 if p > threshold else 0, mode="1") pure_bw.save("pure_binary_bw.png")
📐

Image Contour & Edge Detection

Filters

Extract outline contours and sketch effects using Pillow's built-in ImageFilter.CONTOUR, FIND_EDGES, and EDGE_ENHANCE_MORE kernels.

contour_filter.py
from PIL import Image, ImageFilter, ImageOps img = Image.open("subject.jpg").convert("L") # 1. Apply Contour Filter contour_img = img.filter(ImageFilter.CONTOUR) contour_img.save("contour.png") # 2. Invert contour for dark line art on white background line_art = ImageOps.invert(contour_img.convert("L")) line_art.save("line_art.png") # 3. Find fine edges edges = img.filter(ImageFilter.FIND_EDGES) edges.save("edges.png")
📸

Screen Grab & Clipboard Access

Utility

Capture high-resolution screenshots, multi-monitor setups, cropped regions, or paste clipboard images directly into Pillow image memory.

image_grab.py
from PIL import ImageGrab # 1. Full primary screen capture screenshot = ImageGrab.grab() screenshot.save("fullscreen.png") # 2. Capture specific region (left, upper, right, lower) region = ImageGrab.grab(bbox=(0, 0, 800, 600)) region.save("region.png") # 3. Grab image from system clipboard clip = ImageGrab.grabclipboard() if clip: clip.save("clipboard_image.png") else: print("No image currently on clipboard")
🗂️

Batch Resize for Web

Automation

Resize every image in a folder to 800×600 max bounding box, preserving aspect ratio. Ideal for pre-processing ML datasets or web asset pipelines.

batch_resize.py
from PIL import Image import pathlib src = pathlib.Path("./images") dst = src / "resized" dst.mkdir(exist_ok=True) for fp in src.glob("*.jpg"): img = Image.open(fp) img.thumbnail((800, 600)) img.save(dst / fp.name)
💧

Watermark 1000 Images

Branding

Overlay semi-transparent text or logo watermarks on every image in a directory. Uses composite blending for professional results.

watermark.py
from PIL import Image, ImageDraw, ImageFont def add_watermark(path, text="© MyBrand"): img = Image.open(path).convert("RGBA") overlay = Image.new("RGBA", img.size, (0,0,0,0)) draw = ImageDraw.Draw(overlay) draw.text((20, 20), text, fill=(255,255,255,120)) img = Image.alpha_composite(img, overlay) img.save(path.replace(".png", "_wm.png"))
🔍

Extract EXIF Metadata

Analysis

Read camera metadata from JPEG photos: GPS coordinates, make/model, ISO, shutter speed, and focal length — decoded to human-readable values.

read_exif.py
from PIL import Image from PIL.ExifTags import TAGS img = Image.open("photo.jpg") exif_data = img._getexif() if exif_data: for tag_id, value in exif_data.items(): tag = TAGS.get(tag_id, tag_id) print(f"{tag:25}: {value}")
📱

Generate Social Cards

Content

Programmatically create Open Graph / Twitter card images. Draw a gradient background, overlay your title text, and export as optimized JPEG.

social_card.py
from PIL import Image, ImageDraw, ImageFont img = Image.new("RGB", (1200, 630), (30, 30, 46)) draw = ImageDraw.Draw(img) font = ImageFont.truetype("Inter.ttf", 60) draw.text( (60, 250), "My Article Title", fill="white", font=font ) img.save("og_card.jpg", quality=95)
✂️

Auto-Crop to Content

Transform

Use getbbox() to automatically detect non-white/non-black borders and crop the image to its real content region.

auto_crop.py
from PIL import Image, ImageOps img = Image.open("scan.png").convert("RGB") # Remove white border/padding automatically inverted = ImageOps.invert(img) bbox = inverted.getbbox() if bbox: cropped = img.crop(bbox) cropped.save("cropped.png")
🔄

Batch PNG → WEBP

Conversion

Convert an entire directory of PNG files to space-efficient WEBP format. Typically reduces file size by 25–34% without visible quality loss.

png_to_webp.py
from PIL import Image import pathlib for fp in pathlib.Path(".").glob("*.png"): img = Image.open(fp).convert("RGB") out = fp.with_suffix(".webp") img.save(out, "WEBP", quality=85, method=6) print(f"Saved {out}")

Crop Circular Avatar / Profile

Styling

Create perfectly rounded circular avatar photos with alpha transparency masks. Ideal for web profiles, user avatars, and badge generators.

circular_crop.py
from PIL import Image, ImageDraw img = Image.open("portrait.jpg").convert("RGBA") size = min(img.size) # Center square crop first left = (img.width - size) // 2 top = (img.height - size) // 2 img = img.crop((left, top, left + size, top + size)) # Create anti-aliased circular alpha mask mask = Image.new("L", (size, size), 0) draw = ImageDraw.Draw(mask) draw.ellipse((0, 0, size, size), fill=255) # Apply mask to alpha channel img.putalpha(mask) img.save("circular_avatar.png")
🖼️

Add Border & Padding

ImageOps

Add colored frame borders or uniform padding around an image using ImageOps.expand or fit images to fixed canvas dimensions with ImageOps.pad.

add_border.py
from PIL import Image, ImageOps img = Image.open("artwork.jpg") # 1. Add 20px uniform white border framed = ImageOps.expand(img, border=20, fill="white") # 2. Add asymmetrical border (left, top, right, bottom) fancy = ImageOps.expand(img, border=(30, 10, 30, 40), fill="#1e1e2f") # 3. Fit to exact 1920x1080 canvas with letterbox centering padded = ImageOps.pad(img, (1920, 1080), color="black") padded.save("letterbox_1080p.jpg")
🎞️

Create Animated GIF

Animation

Stitch multiple image frames into a smooth, looping animated GIF with custom per-frame durations and loop controls.

create_gif.py
from PIL import Image import glob # Load all frames sorted by name frames = [Image.open(f) for f in sorted(glob.glob("frames/*.png"))] # Save as animated GIF (100ms per frame, infinite loop) frames[0].save( "animation.gif", save_all=True, append_images=frames[1:], duration=100, loop=0, optimize=True )
🎨

Extract Dominant Color Palette

Analysis

Extract the top 5 dominant brand colors from any photo using Pillow's fast adaptive color quantization and histogram binning.

dominant_colors.py
from PIL import Image img = Image.open("photo.jpg").convert("RGB") # Downscale for instant calculation img.thumbnail((150, 150)) # Quantize to 5 most dominant colors using Adaptive palette quantized = img.quantize(colors=5, method=Image.Quantize.FASTOCTREE) palette = quantized.getpalette()[:15] # 5 * 3 RGB values dominant_colors = [tuple(palette[i:i+3]) for i in range(0, 15, 3)] print("Dominant RGB colors:", dominant_colors)
📱

Convert iPhone HEIC to JPEG/PNG

Conversion

Seamlessly decode Apple iPhone .heic and .heif photos into Pillow images and batch convert them to web-ready JPEG or PNG formats.

heic_to_jpeg.py
from PIL import Image import pillow_heif # pip install pillow-heif # Register HEIF opener with Pillow pillow_heif.register_heif_opener() # Now Image.open transparently handles .heic files! img = Image.open("IMG_4021.HEIC") img.save("IMG_4021.jpg", "JPEG", quality=92) print(f"Converted {img.size} HEIC image to JPEG")

⚙️ Visual Script Generator

Toggle the operations you need — copy a unified, ready-to-run processing pipeline.

pipeline.py

🖼️ Live Image Playground.

Apply Pillow-equivalent effects instantly in your browser. Toggle filters and see the result in real time.

Image Effects

100%
100%
100%
0px
0

Presets

Pillow playground demo image
Live Preview
Equivalent Pillow Code:

                

📊 Pillow vs The Alternatives.

See how Pillow stacks up against other Python image processing libraries.

Feature Pillow ✅ OpenCV Wand (ImageMagick) scikit-image imageio
Pure Python API ✅ Yes ❌ C++ bindings ❌ C bindings ✅ Yes ✅ Yes
Ease of Use ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐
Format Support 30+ formats ~20 formats 200+ formats ~15 formats ~20 formats
pip install size ~3 MB ~50 MB ~30 MB ~20 MB ~1 MB
Drawing / Text ✅ ImageDraw ✅ cv2.putText ✅ Drawing ❌ Limited ❌ None
Thumbnail Generation ✅ One line ⚠️ Manual ✅ Yes ⚠️ Manual ⚠️ Manual
ML / NumPy Integration ✅ np.array(img) ✅ Native arrays ⚠️ Limited ✅ Native ✅ Arrays
License MIT (HPND) Apache 2.0 MIT BSD BSD
Best For General purpose Computer vision Complex transforms Scientific analysis I/O only

💡 Common Errors & Fixes.

The top developer pain points when working with Pillow — with exact solutions.

ModuleNotFoundError

No module named 'PIL'

Cause: Pillow is not installed in the current Python environment.

Fix: Install via pip. The package is called Pillow but imports as PIL.

powershell
$pip install Pillow
# Then use: from PIL import Image
OSError

cannot identify image file

Cause: The file extension doesn't match the actual format, or the file is corrupt/truncated.

Fix: Verify the actual format and pass the explicit format parameter.

python
>>># Check actual format:
with open('file', 'rb') as f: print(f.read(4))
# Force format:
img = Image.open('file', formats=['JPEG'])
DecompressionBombWarning

Image may be a decompression bomb

Cause: Pillow's security limit blocks images larger than 178 million pixels by default to prevent DoS attacks.

Fix: Raise or disable the limit (only for trusted sources).

python
>>>Image.MAX_IMAGE_PIXELS = None # disable
# or raise limit:
Image.MAX_IMAGE_PIXELS = 500_000_000
Orientation Issue

Image appears rotated after opening

Cause: Camera stores orientation in EXIF tag but Pillow does not auto-rotate on open.

Fix: Use ImageOps.exif_transpose() to apply EXIF rotation automatically.

python
>>>from PIL import ImageOps
img = Image.open("photo.jpg")
img = ImageOps.exif_transpose(img)
OSError

cannot write mode RGBA as JPEG

Cause: JPEG does not support transparency (alpha channel). The image has 4 channels (RGBA) instead of 3 (RGB).

Fix: Convert to RGB before saving as JPEG, or use PNG for transparency.

python
>>>img = img.convert("RGB") # drop alpha
img.save("output.jpg", quality=95)
AttributeError

module 'PIL.Image' has no attribute 'ANTIALIAS'

Cause: Image.ANTIALIAS was deprecated in Pillow 9.0.0 and completely removed in Pillow 10.0.0.

Fix: Replace Image.ANTIALIAS with Image.Resampling.LANCZOS (or Image.LANCZOS).

python
>>># Old (breaks in Pillow 10+):
# img.resize((400, 300), Image.ANTIALIAS)

# New (Pillow 10+):
img = img.resize((400, 300), Image.Resampling.LANCZOS)
ImportError

cannot import name '_imaging' from 'PIL'

Cause: Pillow's native C extension was compiled against a different Python version or architecture (common on Apple Silicon M1/M2/M3).

Fix: Force-reinstall pre-built binary wheels cleanly.

terminal
$python -m pip uninstall -y Pillow
python -m pip install --upgrade --no-cache-dir Pillow
MemoryError

Out of memory when processing large images

Cause: Large images are loaded entirely into RAM before processing. A 100 MP TIFF can consume 1–2 GB uncompressed.

Fix: Use draft mode for loading, process in tiles, or downscale before processing.

python
>>># Load reduced version (JPEG only):
img.draft("RGB", (800, 600))
img.load()

Frequently Asked Questions

Everything developers need to know about Pillow in Python.

What is Pillow exactly?

Python Pillow is an open-source library that adds support for opening, manipulating, and saving many different image file formats. As the active fork of the original Python Imaging Library (PIL), Pillow is the foundational tool for image processing in Python — no complex C dependencies required for most operations.

What is the difference between PIL and Pillow?

PIL (Python Imaging Library) is the original, now-discontinued library that stopped supporting Python 3. Pillow is the actively maintained, drop-in compatible fork. It adds Python 3 support, security patches, new format support (WEBP, AVIF), and modern API improvements. You install Pillow but import it as PIL.

How do I install Pillow on Anaconda / Conda?

To install Pillow in an Anaconda or Conda environment, run: conda install -c conda-forge pillow (or conda install pillow). Pillow is also pre-packaged with default Anaconda distributions. In Anaconda Navigator, navigate to Environments, search for pillow, check the box, and click Apply.

How do I convert an image to pure black and white (binary) in Pillow?

There are three ways depending on your goal:

  • Grayscale (8-bit, 256 gray shades): gray = img.convert('L')
  • 1-bit Dithered Black & White: bw = img.convert('1')
  • Pure Binary Thresholding (no dithering): pure_bw = gray.point(lambda p: 255 if p > 128 else 0, mode='1')
How do I use Pillow with OpenCV and Tesseract for OCR projects?

Combine OpenCV for preprocessing (grayscale, adaptive thresholding), Pillow for rendering annotations, and PyTesseract for text extraction:

1. Convert OpenCV BGR array to Pillow RGB: pil_img = Image.fromarray(cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB))

2. Run OCR: data = pytesseract.image_to_data(pil_img, output_type=pytesseract.Output.DICT)

3. Draw bounding boxes: draw = ImageDraw.Draw(pil_img); draw.rectangle([x, y, x+w, y+h], outline='red')

How do I fix "No module named PIL"?

Run pip install Pillow. Even though the package is called Pillow, the import namespace is PIL for backward compatibility. Always use from PIL import Image in your code. If you're using a virtual environment, ensure it is activated first.

How do I take screenshots or capture the clipboard with Pillow?

Use the ImageGrab module: from PIL import ImageGrab. Run screenshot = ImageGrab.grab() to take a full-screen screenshot, region = ImageGrab.grab(bbox=(0, 0, 800, 600)) for a specific bounding box, or clip = ImageGrab.grabclipboard() to get image data currently copied to your clipboard.

How do I display an image using Pillow in Python?

Call img.show() which saves a temporary copy and launches your operating system's default image viewer. Inside Jupyter Notebooks or Google Colab, simply write display(img) or type img as the last line of a cell to render inline.

Can I use Pillow on MicroPython or microcontrollers?

No, standard Pillow requires C libraries (libjpeg, zlib, freetype) and several megabytes of RAM, which makes it incompatible with MicroPython boards like ESP32 or Raspberry Pi Pico. For MicroPython, use lightweight microcontroller framebuffer drivers such as framebuf or dedicated display drivers (ST7789, ILI9341).

How do I check which version of Pillow I have?

Run in Python: import PIL; print(PIL.__version__). Or from your terminal: python -m PIL which will print the version and feature support matrix. You can also run pip show Pillow from the command line.

What image formats does Pillow support?

Pillow supports 30+ formats including JPEG, PNG, WEBP, GIF (animated), TIFF, BMP, ICO, EPS, PSD (Adobe Photoshop), PDF reading, PPM, PCX, and more. Some formats like AVIF require optional system libraries. Use Image.registered_extensions() to see all available formats in your installation.

Can Pillow work with NumPy arrays?

Yes. You can convert between Pillow Images and NumPy arrays easily: arr = numpy.array(img) to convert to array, and img = Image.fromarray(arr) to convert back. This makes Pillow ideal as a preprocessing layer before feeding images into PyTorch, TensorFlow, OpenCV, or scikit-learn models.

Can Pillow read and create animated GIFs?

Yes. Use img.seek(frame_number) to iterate through GIF frames. To create an animated GIF, open all frames as a list and use img.save('output.gif', save_all=True, append_images=[...], duration=100, loop=0). Pillow can also read animated WEBP and TIFF files.

Is Pillow fast enough for production use?

Pillow is implemented in C via libjpeg-turbo, zlib, and other native codecs — making it significantly faster than pure Python alternatives. For high-throughput pipelines, use img.draft() for JPEG draft loading, process multiple images with concurrent.futures.ThreadPoolExecutor, and use img.thumbnail() instead of img.resize() to avoid unnecessary upscaling.

Does Pillow support WEBP and AVIF?

WEBP is fully supported for reading, writing, and animated WEBP files. AVIF support was added in Pillow 9.1.0 but requires libavif to be installed on your system. To check: PIL.features.check('avif'). Modern binary wheels on PyPI include WEBP support out of the box.

What is the Pillow license? Is it free for commercial use?

Pillow uses the HPND (Historical Permission Notice and Disclaimer) license — a permissive open-source license similar to MIT. It is completely free for commercial use, closed-source projects, and any application. No attribution is required in your product, though credit is always appreciated by the community.