Skip to main content

Python bindings for libheif - HEIC/AVIF/JPEG2000 image codec

Project description

pylibheif

PyPI version Build and Publish License: LGPL v3 Python 3.11+

Python bindings for libheif using pybind11.

Features

  • HEIC/HEIF Support: Read and write HEIC images (HEVC/H.265 encoded)
  • AVIF Support: Read and write AVIF images (AV1 encoded)
  • JPEG2000 Support: Read and write JPEG2000 images in HEIF container
  • NumPy Integration: Zero-copy access to image data via Python Buffer Protocol
  • Metadata Support: Read and write EXIF, XMP, and custom metadata
  • RAII Resource Management: Automatic resource cleanup with context managers

Supported Formats

Format Decoding Encoding Codec
HEIC (HEVC/H.265) libde265 / x265
AVIF (AV1) DAV1D + AOM
JPEG2000 OpenJPEG

Requirements

  • Python >= 3.12
  • NumPy >= 1.26.0
  • CMake >= 3.15
  • C++17 compatible compiler

System Dependencies

# macOS
brew install openjpeg

# Ubuntu/Debian
sudo apt install libopenjp2-7-dev

Installation

pip install pylibheif

Or with uv:

uv pip install pylibheif

Building from Source

# Clone with submodules
git clone --recursive https://github.com/twn39/pylibheif.git
cd pylibheif

# Install
uv pip install -e .

Usage

Reading HEIC/AVIF Images

Using context manager (recommended):

import pylibheif
import numpy as np

# Open HEIC file with context manager
with pylibheif.HeifContext() as ctx:
    ctx.read_from_file('image.heic')
    
    # Get primary image handle
    handle = ctx.get_primary_image_handle()
    print(f'Image size: {handle.width}x{handle.height}')
    print(f'Has alpha: {handle.has_alpha}')
    
    # Decode to RGB
    img = handle.decode(pylibheif.HeifColorspace.RGB, 
                        pylibheif.HeifChroma.InterleavedRGB)
    
    # Get as NumPy array (zero-copy)
    plane = img.get_plane(pylibheif.HeifChannel.Interleaved, False)
    arr = np.asarray(plane)  # shape: (height, width, 3)

Explicit creation (for more control):

import pylibheif
import numpy as np

# Create context explicitly
ctx = pylibheif.HeifContext()
ctx.read_from_file('image.heic')

handle = ctx.get_primary_image_handle()
img = handle.decode(pylibheif.HeifColorspace.RGB, 
                    pylibheif.HeifChroma.InterleavedRGB)
plane = img.get_plane(pylibheif.HeifChannel.Interleaved, False)
arr = np.asarray(plane)

# Resources are automatically freed when objects go out of scope

Writing HEIC/AVIF Images

import pylibheif
import numpy as np

# Create image from NumPy array
width, height = 1920, 1080
img = pylibheif.HeifImage(width, height, 
                          pylibheif.HeifColorspace.RGB,
                          pylibheif.HeifChroma.InterleavedRGB)
img.add_plane(pylibheif.HeifChannel.Interleaved, width, height, 8)

# Fill with data
plane = img.get_plane(pylibheif.HeifChannel.Interleaved, True)
arr = np.asarray(plane)
arr[:] = your_image_data  # your RGB data

# Encode and save
ctx = pylibheif.HeifContext()

# For HEIC (HEVC)
encoder = pylibheif.HeifEncoder(pylibheif.HeifCompressionFormat.HEVC)
# For AVIF (AV1)
# encoder = pylibheif.HeifEncoder(pylibheif.HeifCompressionFormat.AV1)
# For JPEG2000
# encoder = pylibheif.HeifEncoder(pylibheif.HeifCompressionFormat.JPEG2000)

encoder.set_lossy_quality(85)
encoder.encode_image(ctx, img)
ctx.write_to_file('output.heic')

Converting HEIC to JPEG

import pylibheif
import numpy as np
from PIL import Image

# Decode HEIC
ctx = pylibheif.HeifContext()
ctx.read_from_file('input.heic')
handle = ctx.get_primary_image_handle()
img = handle.decode(pylibheif.HeifColorspace.RGB, 
                    pylibheif.HeifChroma.InterleavedRGB)

# Get NumPy array
plane = img.get_plane(pylibheif.HeifChannel.Interleaved, False)
arr = np.asarray(plane)

# Save as JPEG using PIL
pil_img = Image.fromarray(arr)
pil_img.save('output.jpg', 'JPEG', quality=85)

Reading Metadata

import pylibheif

ctx = pylibheif.HeifContext()
ctx.read_from_file('image.heic')
handle = ctx.get_primary_image_handle()

# Get metadata block IDs
exif_ids = handle.get_metadata_block_ids('Exif')
for id in exif_ids:
    metadata_type = handle.get_metadata_block_type(id)
    metadata_bytes = handle.get_metadata_block(id)
    print(f'Metadata type: {metadata_type}, size: {len(metadata_bytes)}')

Writing Metadata

import pylibheif
import numpy as np

# Create and encode an image
width, height = 64, 64
img = pylibheif.HeifImage(width, height,
                          pylibheif.HeifColorspace.RGB,
                          pylibheif.HeifChroma.InterleavedRGB)
img.add_plane(pylibheif.HeifChannel.Interleaved, width, height, 8)
plane = img.get_plane(pylibheif.HeifChannel.Interleaved, True)
arr = np.asarray(plane)
arr[:] = 128  # fill with gray

ctx = pylibheif.HeifContext()
encoder = pylibheif.HeifEncoder(pylibheif.HeifCompressionFormat.HEVC)
encoder.set_lossy_quality(85)
handle = encoder.encode_image(ctx, img)

# Add EXIF metadata (with 4-byte offset prefix for TIFF header)
exif_data = b'\x00\x00\x00\x00' + b'Exif\x00\x00' + b'II*\x00...'  # your EXIF data
ctx.add_exif_metadata(handle, exif_data)

# Add XMP metadata
xmp_data = b'''<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/">
  <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
    <rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/">
      <dc:creator>My App</dc:creator>
    </rdf:Description>
  </rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>'''
ctx.add_xmp_metadata(handle, xmp_data)

# Add custom/generic metadata
custom_data = b'{"app": "myapp", "version": "1.0"}'
ctx.add_generic_metadata(handle, custom_data, "json", "application/json")

# Save
ctx.write_to_file('output_with_metadata.heic')

API Reference

class pylibheif.HeifContext

Manages the valid lifetime of libheif context. It is the main entry point (root object) for high-level API.

Methods

__init__() Creates a new empty context.

read_from_file(filename: str) -> None Reads a HEIF file from the given filename.

  • filename: Path to the HEIF file.

read_from_memory(data: bytes) -> None Reads a HEIF file from a bytes object.

  • data: Bytes containing the file content.

write_to_file(filename: str) -> None Writes the current context to a file.

  • filename: Destination path.

write_to_bytes() -> bytes Writes the current context to a bytes object.

  • Returns: bytes object containing the encoded file data.

get_primary_image_handle() -> HeifImageHandle Gets the handle for the primary image in the file.

  • Returns: HeifImageHandle for the primary image.

get_image_handle(id: int) -> HeifImageHandle Gets the handle for a specific image ID.

  • id: The ID of the image (see get_list_of_top_level_image_IDs).
  • Returns: HeifImageHandle.

get_list_of_top_level_image_IDs() -> List[int] Gets a list of IDs of all top-level images in the file.

  • Returns: List of integer IDs.

add_exif_metadata(handle: HeifImageHandle, data: bytes) -> None Adds EXIF metadata to the specified image.

  • handle: Image handle from encoding.
  • data: Raw EXIF bytes (with 4-byte offset prefix for TIFF header).

add_xmp_metadata(handle: HeifImageHandle, data: bytes) -> None Adds XMP metadata to the specified image.

  • handle: Image handle from encoding.
  • data: XMP XML as bytes.

add_generic_metadata(handle: HeifImageHandle, data: bytes, item_type: str, content_type: str = "") -> None Adds generic/custom metadata to the specified image.

  • handle: Image handle from encoding.
  • data: Raw metadata bytes.
  • item_type: Metadata item type (e.g. "json", "iptc").
  • content_type: Optional MIME content type (e.g. "application/json").

class pylibheif.HeifImageHandle

Represents a compressed image within the HEIF file.

Properties

  • width (int): The width of the image.
  • height (int): The height of the image.
  • has_alpha (bool): True if the image has an alpha channel.

Methods

decode(colorspace: HeifColorspace = HeifColorspace.RGB, chroma: HeifChroma = HeifChroma.InterleavedRGB) -> HeifImage Decodes the image handle into an uncompressed HeifImage.

  • colorspace: Target colorspace (default: RGB).
  • chroma: Target chroma format (default: InterleavedRGB).
  • Returns: Decoded HeifImage.

get_metadata_block_ids(type_filter: str = "") -> List[str] Gets a list of metadata block IDs attached to this image.

  • type_filter: Optional filter string (e.g. "Exif", "XMP").
  • Returns: List of metadata ID strings.

get_metadata_block_type(id: str) -> str Gets the type string of a specific metadata block.

  • id: Metadata ID.
  • Returns: Type string (e.g. "Exif").

get_metadata_block(id: str) -> bytes Gets the raw data of a metadata block.

  • id: Metadata ID.
  • Returns: bytes object containing the metadata.

class pylibheif.HeifImage

Represents an uncompressed image containing pixel data. Supports the Python Buffer Protocol for zero-copy access with NumPy.

Properties

  • width (int): The width of the image.
  • height (int): The height of the image.

Methods

__init__(width: int, height: int, colorspace: HeifColorspace, chroma: HeifChroma) Creates a new empty image.

  • width: Image width.
  • height: Image height.
  • colorspace: Image colorspace.
  • chroma: Image chroma format.

add_plane(channel: HeifChannel, width: int, height: int, bit_depth: int) -> None Adds a new plane to the image.

  • channel: The channel type (e.g. HeifChannel.Interleaved).
  • width: Width of the plane.
  • height: Height of the plane.
  • bit_depth: Bit depth (e.g. 8).

get_plane(channel: HeifChannel, writeable: bool = False) -> HeifPlane Gets a plane object that supports the buffer protocol.

  • channel: The channel to retrieve.
  • writeable: Whether the buffer should be writable.
  • Returns: HeifPlane object (wrappable with np.asarray()).

class pylibheif.HeifEncoder

Controls the encoding process.

Methods

__init__(format: HeifCompressionFormat) Creates a new encoder for the specified format.

  • format: Compression format (e.g. HeifCompressionFormat.HEVC).

set_lossy_quality(quality: int) -> None Sets the quality for lossy compression.

  • quality: Integer between 0 (lowest) and 100 (highest).

set_parameter(name: str, value: str) -> None Sets a low-level encoder parameter.

  • name: Parameter name (e.g. "speed" for AV1).
  • value: Parameter value.

encode_image(context: HeifContext, image: HeifImage) -> HeifImageHandle Encodes the given image and appends it to the context.

  • context: The destination HeifContext.
  • image: The source HeifImage to encode.
  • Returns: HeifImageHandle for the encoded image. Can be used to add metadata.

Enums

pylibheif.HeifColorspace

  • RGB, YCbCr, Monochrome, Undefined

pylibheif.HeifChroma

  • InterleavedRGB: Interleaved R, G, B bytes.
  • InterleavedRGBA: Interleaved R, G, B, A bytes.
  • C420: YUV 4:2:0 planar.
  • C422: YUV 4:2:2 planar.
  • C444: YUV 4:4:4 planar.
  • Monochrome.

pylibheif.HeifChannel

  • Interleaved: For interleaved RGB/RGBA.
  • Y, Cb, Cr: For YUV planar.
  • R, G, B: For RGB planar.
  • Alpha: For Alpha channel.

pylibheif.HeifCompressionFormat

  • HEVC: H.265 (libx265).
  • AV1: AV1 (AOM/RAV1E/SVT).
  • JPEG: JPEG.
  • JPEG2000: JPEG 2000 (OpenJPEG).

Building from Source

# Clone with submodules
git clone --recursive https://github.com/your-username/pylibheif.git
cd pylibheif

# Build
uv pip install -e .

Performance

Benchmarks on 1920x1080 RGB image (Apple Silicon):

Operation pylibheif pillow-heif Note
HEVC Decode 25 ms 25 ms ~39 FPS
HEVC Encode 279 ms 272 ms Quality 80
AV1 Encode 91 ms - Speed 50

pylibheif offers performance comparable to pillow-heif (both wrapper libheif), but exposes a lower-level C++ API for fine-grained control.

Run benchmarks yourself:

uv pip install pillow-heif pytest-benchmark
uv run pytest tests/test_benchmark.py --benchmark-only

License

This project is licensed under the LGPL-3.0 License - see the LICENSE file for details.

Acknowledgments

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pylibheif-1.21.2.post3.tar.gz (2.2 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

pylibheif-1.21.2.post3-cp314-cp314-manylinux_2_28_x86_64.whl (24.2 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.28+ x86-64

pylibheif-1.21.2.post3-cp314-cp314-macosx_14_0_arm64.whl (6.9 MB view details)

Uploaded CPython 3.14macOS 14.0+ ARM64

pylibheif-1.21.2.post3-cp313-cp313-manylinux_2_28_x86_64.whl (24.2 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.28+ x86-64

pylibheif-1.21.2.post3-cp313-cp313-macosx_14_0_arm64.whl (6.9 MB view details)

Uploaded CPython 3.13macOS 14.0+ ARM64

pylibheif-1.21.2.post3-cp312-cp312-manylinux_2_28_x86_64.whl (24.2 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.28+ x86-64

pylibheif-1.21.2.post3-cp312-cp312-macosx_14_0_arm64.whl (6.9 MB view details)

Uploaded CPython 3.12macOS 14.0+ ARM64

pylibheif-1.21.2.post3-cp311-cp311-manylinux_2_28_x86_64.whl (24.2 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.28+ x86-64

pylibheif-1.21.2.post3-cp311-cp311-macosx_14_0_arm64.whl (6.9 MB view details)

Uploaded CPython 3.11macOS 14.0+ ARM64

File details

Details for the file pylibheif-1.21.2.post3.tar.gz.

File metadata

  • Download URL: pylibheif-1.21.2.post3.tar.gz
  • Upload date:
  • Size: 2.2 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pylibheif-1.21.2.post3.tar.gz
Algorithm Hash digest
SHA256 a20951f384b152bfe5628b6b8fbc680ed003002e95aa43b52bfda2004bf5814f
MD5 cc234c70ddb1294fa80c39ed77416c42
BLAKE2b-256 3057d4dcf023025be35c6e8ebda6228e1be97530d7cab7f1ac514db5ea017144

See more details on using hashes here.

Provenance

The following attestation bundles were made for pylibheif-1.21.2.post3.tar.gz:

Publisher: build.yml on twn39/pylibheif

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pylibheif-1.21.2.post3-cp314-cp314-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pylibheif-1.21.2.post3-cp314-cp314-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 f510e2146f72f23f5ddf923efc2dd0a5272291a1bdf6b025966ac7bb5edb2ae6
MD5 35f79bba92a5eaaa497f43c9fa7c1186
BLAKE2b-256 daca126b15a62eca26fd689556d9290db171ecd5581201dedf68d70679a409af

See more details on using hashes here.

Provenance

The following attestation bundles were made for pylibheif-1.21.2.post3-cp314-cp314-manylinux_2_28_x86_64.whl:

Publisher: build.yml on twn39/pylibheif

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pylibheif-1.21.2.post3-cp314-cp314-macosx_14_0_arm64.whl.

File metadata

File hashes

Hashes for pylibheif-1.21.2.post3-cp314-cp314-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 6bb545552e303f08462d6cae8290d5744dde0c294c56d43937982e4d49207929
MD5 b48f38c691bb4bff9ba2e72714e0c5bd
BLAKE2b-256 bcc09ec2d88dbd46194187bdc365efbe5932deb7fd423a3765c26933fd3ce223

See more details on using hashes here.

Provenance

The following attestation bundles were made for pylibheif-1.21.2.post3-cp314-cp314-macosx_14_0_arm64.whl:

Publisher: build.yml on twn39/pylibheif

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pylibheif-1.21.2.post3-cp313-cp313-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pylibheif-1.21.2.post3-cp313-cp313-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 3430bce9b29b69fcaf5f5a7e06ce4874904ad5b1bb348a6aefc079a5d25edfb4
MD5 498c516d666adc85eb0b86c5d7d6cab7
BLAKE2b-256 e4737b6c8d42222bda37d3a8faffe67c18d850bf93964fd3db1a13ae3c34500c

See more details on using hashes here.

Provenance

The following attestation bundles were made for pylibheif-1.21.2.post3-cp313-cp313-manylinux_2_28_x86_64.whl:

Publisher: build.yml on twn39/pylibheif

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pylibheif-1.21.2.post3-cp313-cp313-macosx_14_0_arm64.whl.

File metadata

File hashes

Hashes for pylibheif-1.21.2.post3-cp313-cp313-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 747eb0744408e4941066c8114f0599cfd4f7c5f4546e1a4fb4a0be69d7f48d5f
MD5 ab0c50921097d198d4105ee28ae61589
BLAKE2b-256 23deff39e8ecf2d76c986492277fa2b89c6fd8e30fe44a7305ca66945fd04819

See more details on using hashes here.

Provenance

The following attestation bundles were made for pylibheif-1.21.2.post3-cp313-cp313-macosx_14_0_arm64.whl:

Publisher: build.yml on twn39/pylibheif

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pylibheif-1.21.2.post3-cp312-cp312-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pylibheif-1.21.2.post3-cp312-cp312-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 5688c96f6b177e5eb68f443bd82e22f7c801bd4145c4e1f98d66c3b1940b6919
MD5 3a1d510f42cedd02474b6ff6892c8076
BLAKE2b-256 94aa1090d941caccfaaff379144086ff6594bdcf70c2454d119a96c12b02e9dc

See more details on using hashes here.

Provenance

The following attestation bundles were made for pylibheif-1.21.2.post3-cp312-cp312-manylinux_2_28_x86_64.whl:

Publisher: build.yml on twn39/pylibheif

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pylibheif-1.21.2.post3-cp312-cp312-macosx_14_0_arm64.whl.

File metadata

File hashes

Hashes for pylibheif-1.21.2.post3-cp312-cp312-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 e20596ee003c23cd2db8fe2bbb2a97e2fd3130a6635598cc9d0d2970fe48bd9c
MD5 70282ab1fb14756c4dbd6da4e36b5d60
BLAKE2b-256 fdc3bfb1bc088aae8db286660d416b9c4324cecc3f9121cb1368d18eb2bee3d7

See more details on using hashes here.

Provenance

The following attestation bundles were made for pylibheif-1.21.2.post3-cp312-cp312-macosx_14_0_arm64.whl:

Publisher: build.yml on twn39/pylibheif

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pylibheif-1.21.2.post3-cp311-cp311-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pylibheif-1.21.2.post3-cp311-cp311-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 279e1f9b24200d838ddaeaf1763bdd026325de514095e094eb95f95c8b62c0cb
MD5 27568e9a54bafb718ff8c28f03afee5d
BLAKE2b-256 804af1d430e7bd279f7680be739541c44de0dca149fec9e137afaca21efd12a4

See more details on using hashes here.

Provenance

The following attestation bundles were made for pylibheif-1.21.2.post3-cp311-cp311-manylinux_2_28_x86_64.whl:

Publisher: build.yml on twn39/pylibheif

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pylibheif-1.21.2.post3-cp311-cp311-macosx_14_0_arm64.whl.

File metadata

File hashes

Hashes for pylibheif-1.21.2.post3-cp311-cp311-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 afd32517502f45a984046d2c7a29399a707a30610caa838d8bf4f606fe297c4c
MD5 8c26406b944aabf3815444e0cae389eb
BLAKE2b-256 00c052eddb2a4314fdf8cac37cafdfc209a94dfa25240238957dea99194611ef

See more details on using hashes here.

Provenance

The following attestation bundles were made for pylibheif-1.21.2.post3-cp311-cp311-macosx_14_0_arm64.whl:

Publisher: build.yml on twn39/pylibheif

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page