All formats

pyvips

LanguagePython
LicenseMIT (libvips: LGPL-2.1)
Repositorygithub.com/libvips/pyvips
Documentationpyvips documentation
Depends onlibvips built with libheif and an AV1 codec (included in the pyvips-binary wheel)
Read / writeyes / yes, 8/10/12-bit, alpha, animated AVIF

pyvips wraps libvips, a demand-driven image library that processes images in small pieces instead of loading them whole. It’s several times faster than Pillow for resizing and converting large images, uses little memory, and keeps 10/12-bit AVIF precision. AVIF goes through libvips’ heifload and heifsave; writing a .avif file selects AV1 compression.

Installation#

Shell
pip install "pyvips[binary]"   # wheels with a prebuilt libvips, including AVIF

Or install libvips from your system (apt install libvips-dev, brew install vips) and then pip install pyvips. System packages need libheif with an AV1 encoder for writing AVIF.

Basic usage: convert to AVIF and back#

Python
import pyvips

image = pyvips.Image.new_from_file("photo.jpg", access="sequential")
print(image.width, image.height, image.bands)
image.write_to_file("photo.avif", Q=60)  # the .avif suffix selects AV1

avif = pyvips.Image.new_from_file("photo.avif")
avif.write_to_file("photo.png")

How to make an AVIF thumbnail#

thumbnail loads only what it needs and resizes in one step:

Python
import pyvips

thumb = pyvips.Image.thumbnail("photo.jpg", 400)  # 400 pixels wide
thumb.write_to_file("thumb.avif", Q=55, effort=4)

How to set effort, bit depth and lossless mode#

Python
image = pyvips.Image.new_from_file("photo.png")
image.heifsave(
    "out.avif",
    compression="av1",
    Q=60,
    effort=2,          # 0 (fastest) .. 9 (slowest, smallest), default 4
    bitdepth=10,       # 8, 10 or 12
    subsample_mode="off",  # keep 4:4:4 chroma
)

image.heifsave("lossless.avif", compression="av1", lossless=True)

How to encode AVIF to bytes#

Python
data = image.heifsave_buffer(compression="av1", Q=60)
# or: image.write_to_buffer(".avif", Q=60)

How to read frames of an animated AVIF#

Load all pages with n=-1; frames are stacked vertically, each page-height pixels tall:

Python
anim = pyvips.Image.new_from_file("anim.avif", n=-1)
page_height = anim.get("page-height")
frames = anim.height // page_height
for i in range(frames):
    frame = anim.crop(0, i * page_height, anim.width, page_height)
    frame.write_to_file(f"frame{i}.png")

Tips#