Pillow
| Language | Python 3 |
|---|---|
| License | MIT-CMU (permissive) |
| Repository | github.com/python-pillow/Pillow |
| Documentation | WebP in the Pillow docs |
| Depends on | libwebp (bundled in the PyPI wheels) |
| Read / write | yes / yes, lossy, lossless, alpha, animation, ICC, Exif, XMP |
Pillow is the standard imaging library for Python. Its WebP plugin uses libwebp, which the binary wheels on PyPI include, so pip install pillow is enough on Windows, macOS and Linux. It supports every WebP feature: lossy and lossless encoding, alpha, animation (read and write) and metadata.
Installation#
Shell
pip install pillow
If you build Pillow from source, install libwebp-dev (Debian/Ubuntu) or webp (Homebrew) first.
Basic usage: convert to WebP#
Python
from PIL import Image
with Image.open("photo.jpg") as im:
print(im.format, im.size, im.mode)
im.save("photo.webp", quality=80, method=6) # quality 0-100, method 0 (fast) .. 6 (smallest)
with Image.open("photo.webp") as im:
im.save("photo.png")
How to save a lossless WebP#
Python
with Image.open("logo.png") as im:
im.save("logo.webp", lossless=True, quality=100, method=6) # for lossless, quality is the effort
Add exact=True to keep the RGB values of transparent pixels. For lossy images with alpha, alpha_quality=0..100 sets the alpha channel quality separately.
How to get WebP dimensions without decoding#
Image.open reads only the header; pixels are decoded on first access:
Python
with Image.open("in.webp") as im:
print(im.size, im.mode, getattr(im, "n_frames", 1))
How to create an animated WebP#
Python
from PIL import Image
frames = [Image.open(f"frame{i}.png") for i in range(10)]
frames[0].save(
"anim.webp",
save_all=True,
append_images=frames[1:],
duration=100, # ms per frame, or a list with one value per frame
loop=0, # 0 = forever
quality=75,
# lossless=True, minimize_size=True, allow_mixed=True are also accepted
)
Converting an animated GIF: Image.open("anim.gif").save("anim.webp", save_all=True).
How to read the frames of an animated WebP#
Python
from PIL import Image, ImageSequence
with Image.open("anim.webp") as im:
print(im.n_frames, "frames, loop", im.info.get("loop"))
for i, frame in enumerate(ImageSequence.Iterator(im)):
print(i, frame.info.get("duration"), "ms")
frame.convert("RGBA").save(f"frame{i}.png")
How to keep the ICC profile and Exif#
Pillow doesn’t copy metadata unless you pass it:
Python
with Image.open("photo.jpg") as im:
im.save(
"photo.webp",
quality=80,
icc_profile=im.info.get("icc_profile"),
exif=im.info.get("exif", b""),
)
Tips#
from PIL import features; features.check("webp")reports whether WebP support is compiled in.- WebP is limited to 16383 x 16383 pixels;
saveraises an error for larger images. - Call
ImageOps.exif_transpose(im)before saving if the source has an Exif orientation you want applied.