Pillow
| Language | Python |
|---|---|
| License | MIT-CMU (permissive) |
| Repository | github.com/python-pillow/Pillow |
| Documentation | AVIF in the Pillow handbook |
| Depends on | libavif with dav1d and libaom (included in the wheels from Pillow 11.3) |
| Read / write | yes / yes, 8-bit only; still and animated, alpha, Exif/XMP/ICC |
Pillow is the standard imaging library for Python. AVIF support arrived in 11.2.1 for builds from source and is in the PyPI wheels since 11.3, using libavif with dav1d for decoding and libaom for encoding. Opening and saving AVIF works like any other format.
Pillow decodes every AVIF to 8-bit RGB or RGBA and saves only 8-bit AVIF, so 10/12-bit and HDR precision is lost. Use pyvips when you need high bit depth.
Installation#
Shell
pip install --upgrade Pillow
Check that your build has AVIF:
Python
from PIL import features
print(features.check("avif")) # True
Basic usage: convert JPEG to AVIF and back#
Python
from PIL import Image
with Image.open("photo.jpg") as im:
print(im.size, im.mode)
im.save("photo.avif", quality=60)
with Image.open("photo.avif") as im:
print(im.format, im.size, im.mode) # AVIF (w, h) RGB
im.save("photo.png")
How to set AVIF quality, speed and chroma subsampling#
Python
from PIL import Image
with Image.open("screenshot.png") as im:
im.save(
"screenshot.avif",
quality=70, # 0..100, default 75
speed=4, # 0 (slowest, smallest) .. 10 (fastest), default 6
subsampling="4:4:4", # 4:2:0 (default), 4:2:2, 4:4:4 or 4:0:0
)
Use 4:4:4 for screenshots, text and graphics with sharp colored edges.
How to get AVIF width and height without decoding#
Image.open reads only the header; pixels are decoded when you access them:
Python
from PIL import Image
with Image.open("photo.avif") as im:
print(im.width, im.height, im.mode, getattr(im, "n_frames", 1))
How to keep Exif and the ICC profile when converting#
Python
from PIL import Image
with Image.open("photo.jpg") as im:
im.save(
"photo.avif",
quality=60,
exif=im.info.get("exif"),
icc_profile=im.info.get("icc_profile"),
)
How to create an animated AVIF#
Python
from PIL import Image
frames = [Image.open(f"frame{i}.png") for i in range(10)]
frames[0].save(
"anim.avif",
save_all=True,
append_images=frames[1:],
duration=100, # milliseconds per frame, or a list
quality=50,
)
How to read the frames of an animated AVIF#
Python
from PIL import Image, ImageSequence
with Image.open("anim.avif") as im:
for i, frame in enumerate(ImageSequence.Iterator(im)):
frame.load()
print(i, frame.size, frame.info.get("duration"))
Tips#
- AVIF encoding is slow:
speed=8or higher for on-the-fly conversion, 4-6 for files you encode once. max_threads=Nlimits encoder threads on a shared server.- Call
ImageOps.exif_transpose(im)before saving to apply Exif orientation to the pixels.