Pillow-HEIF
Pillow-HEIF is a Python interface for the libheif library, enabling the Pillow (PIL Fork) imaging library to open and save HEIF (High Efficiency Image File Format) and HEIC images. The current version is 1.3.0 and the project maintains an active release cadence with frequent updates to bundled libraries and bug fixes.
Warnings
- breaking Python 3.9 support was dropped in `v1.2.0`. Projects targeting Python 3.9 will need to upgrade to Python 3.10 or newer, or stick to `pillow-heif` versions prior to `1.2.0`.
- breaking AVIF support was deprecated in `v0.22.0` and completely dropped in `v1.0.0`. This was done because Pillow itself gained native AVIF support. If you rely on `pillow-heif` for AVIF, you must either use an older version or transition to Pillow's native AVIF capabilities.
- breaking Versions prior to `1.3.0` are vulnerable to an integer overflow in the encode path buffer validation, which could lead to heap out-of-bounds read (CVE-2026-28231, GHSA-5gjj-6r7v-ph3x). This is a critical security vulnerability.
- breaking As of `v1.2.0`, the `PREFERRED_DECODER` option must always specify a valid and available decoder ID, otherwise an exception will be raised. Previously, an invalid decoder might have been silently ignored.
- gotcha On macOS, versions prior to `1.2.1` could crash when `opencv-python` (`cv2`) and `pillow-heif` were both used, due to conflicts in bundled `libx265` libraries. This issue was fixed in `v1.2.1`.
Install
-
pip install pillow-heif
Imports
- register_heif_opener
from pillow_heif import register_heif_opener
- Image
from PIL import Image
Quickstart
from PIL import Image
from pillow_heif import register_heif_opener
import os
# Register the HEIF opener once at the start of your application
register_heif_opener()
# --- Example: Open and convert a HEIF/HEIC image ---
heif_path = os.environ.get('HEIF_INPUT_PATH', 'input.heif')
output_path = os.environ.get('OUTPUT_JPEG_PATH', 'output.jpeg')
try:
# Open a HEIF image
heif_img = Image.open(heif_path)
print(f"Successfully opened HEIF image: {heif_path}")
print(f"Image format: {heif_img.format}, size: {heif_img.size}, mode: {heif_img.mode}")
# Convert and save to JPEG
# Note: HEIF often has 10-bit or 12-bit depth. For 8-bit formats like JPEG,
# Pillow will convert, potentially losing some detail.
if heif_img.mode == 'LA': # Handle monochrome with alpha
heif_img = heif_img.convert('L')
elif 'A' in heif_img.mode: # Remove alpha for JPEG
heif_img = heif_img.convert('RGB')
else:
heif_img = heif_img.convert('RGB') # Ensure RGB for JPEG
heif_img.save(output_path, quality=90)
print(f"Saved converted image to: {output_path}")
except FileNotFoundError:
print(f"Error: HEIF input file '{heif_path}' not found.")
print("Please ensure 'input.heif' exists or set HEIF_INPUT_PATH environment variable.")
except Exception as e:
print(f"An error occurred: {e}")
# --- Example: Create and save a HEIF/HEIC image (requires an input image first) ---
# This part assumes 'output.jpeg' was created or exists.
if os.path.exists(output_path):
try:
jpeg_img = Image.open(output_path)
heic_output_path = os.environ.get('OUTPUT_HEIC_PATH', 'generated.heic')
# Save as HEIC. You can specify encoder parameters in .info['heif_metadata']
jpeg_img.save(heic_output_path, quality=80, save_all=True)
print(f"Saved image back to HEIC: {heic_output_path}")
except Exception as e:
print(f"An error occurred while saving to HEIC: {e}")
else:
print(f"Skipping HEIC creation: '{output_path}' not found.")