All formats

pillow-heif

LanguagePython (C extension)
LicenseBSD-3-Clause (the wheels bundle libheif and codecs under LGPL-3.0, and x265 under GPL-2.0)
Repositorygithub.com/bigcat88/pillow_heif
Documentationpillow-heif.readthedocs.io
Depends onPillow; libheif with libde265 and x265 (bundled in the wheels)
Read / writeyes / yes, 8/10/12-bit, alpha, multiple images, thumbnails, depth images, Exif/XMP

pillow-heif is a Python binding of libheif that works as a Pillow plugin. After register_heif_opener(), Image.open("photo.heic") returns a normal Pillow image and image.save("x.heic") writes HEIC. Its own HeifFile API gives access to everything else in a file: all top-level images, thumbnails, depth images, and high bit depth data as NumPy arrays.

Binary wheels for Windows, macOS and Linux include libheif with the libde265 decoder and the x265 encoder, so nothing else needs to be installed. x265 is GPL-2.0; take that into account if you distribute the wheels with your application.

Installation#

Shell
pip install pillow-heif

Basic usage: convert HEIC to JPEG#

Python
from PIL import Image
from pillow_heif import register_heif_opener

register_heif_opener()  # Image.open now understands HEIC/HEIF

with Image.open("IMG_0001.heic") as im:
    print(im.size, im.mode)
    im.save("IMG_0001.jpg", quality=90, exif=im.info.get("exif"))

The image is already rotated according to the HEIF irot/imir properties, so don’t apply the Exif orientation again.

How to save an image as HEIC#

Python
from PIL import Image
from pillow_heif import register_heif_opener

register_heif_opener()

with Image.open("photo.png") as im:
    im.save("photo.heic", quality=80)  # 0-100; quality=-1 means lossless

How to convert all HEIC files in a folder#

Python
from pathlib import Path
from PIL import Image
from pillow_heif import register_heif_opener

register_heif_opener()

for path in Path("photos").glob("*.heic"):
    with Image.open(path) as im:
        im.save(path.with_suffix(".jpg"), quality=90, exif=im.info.get("exif"))

How to read Exif and XMP metadata#

Python
with Image.open("IMG_0001.heic") as im:
    exif = im.getexif()
    print(exif.get(0x0110))           # camera model
    xmp = im.info.get("xmp")          # bytes or None

How to read all images, thumbnails and depth maps#

Python
import pillow_heif

heif_file = pillow_heif.open_heif("IMG_0001.heic")
print("images in file:", len(heif_file))
for img in heif_file:
    print(img.size, img.mode, img.info.get("primary"))

if heif_file.info["thumbnails"]:
    thumb = heif_file[0].get_thumbnail(0)
    thumb.to_pillow().save("thumb.jpg")

if heif_file.info["depth_images"]:
    depth = heif_file.info["depth_images"][0]
    depth.to_pillow().save("depth.png")

How to get 10-bit pixels as a NumPy array#

Python
import numpy as np
import pillow_heif

heif_file = pillow_heif.open_heif("hdr.heic", convert_hdr_to_8bit=False)
arr = np.asarray(heif_file)  # uint16 for 10/12-bit images
print(arr.shape, arr.dtype)

Tips#