CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pillow-heif

Python interface for libheif library providing HEIF/AVIF image processing with both standalone and Pillow plugin capabilities

Overall
score

94%

Overview
Eval results
Files

image-classes.mddocs/

Image Classes

Main container and image classes for handling HEIF/AVIF data. These classes provide comprehensive access to image data, metadata, and specialized image types including depth images and auxiliary images.

Capabilities

HeifFile - Image Container

Main container class for HEIF/AVIF files that can contain one or more images with metadata. Provides both container-like access and direct access to the primary image.

class HeifFile:
    """
    Container for HEIF/AVIF images with metadata support.
    
    Properties:
    - size: tuple[int, int], dimensions of primary image (width, height)
    - mode: str, color mode ('RGB', 'RGBA', 'L', etc.)
    - data: bytes, raw image data of primary image
    - stride: int, bytes per row of primary image
    - info: dict, metadata dictionary with EXIF, XMP, IPTC data
    - mimetype: str, MIME type of file ('image/heif' or 'image/avif')
    - primary_index: int, index of primary image in multi-image file
    - has_alpha: bool, True if primary image has alpha channel
    - premultiplied_alpha: bool, True if alpha is premultiplied
    """
    
    def __init__(self, fp, convert_hdr_to_8bit=True, bgr_mode=False, **kwargs):
        """
        Initialize HeifFile from file path or file-like object.
        
        Parameters:
        - fp: file path (str) or file-like object
        - convert_hdr_to_8bit: bool, convert HDR to 8-bit
        - bgr_mode: bool, use BGR pixel order
        - **kwargs: additional decoding options
        """
    
    @property
    def size(self) -> tuple[int, int]:
        """Dimensions of primary image (width, height)."""
    
    @property
    def mode(self) -> str:
        """Color mode of primary image ('RGB', 'RGBA', 'L', etc.)."""
    
    @property
    def data(self) -> bytes:
        """Raw image data of primary image."""
    
    @property
    def stride(self) -> int:
        """Bytes per row of primary image."""
    
    @property
    def info(self) -> dict:
        """Metadata dictionary with EXIF, XMP, IPTC data."""
    
    @property
    def mimetype(self) -> str:
        """MIME type of file ('image/heif' or 'image/avif')."""
    
    @property
    def primary_index(self) -> int:
        """Index of primary image in multi-image file."""
    
    @property
    def has_alpha(self) -> bool:
        """True if primary image has alpha channel."""
    
    @property
    def premultiplied_alpha(self) -> bool:
        """True if alpha is premultiplied."""
    
    @premultiplied_alpha.setter
    def premultiplied_alpha(self, value: bool):
        """Set premultiplied alpha state."""
    
    @property
    def __array_interface__(self):
        """NumPy array interface for direct array access."""
    
    def save(self, fp, **kwargs):
        """
        Save all images to HEIF/AVIF file.
        
        Parameters:
        - fp: output file path or file-like object
        - **kwargs: encoding options (quality, etc.)
        """
    
    def add_frombytes(self, mode, size, data, **kwargs):
        """
        Add image from raw bytes data.
        
        Parameters:
        - mode: str, color mode ('RGB', 'RGBA', etc.)
        - size: tuple[int, int], image dimensions
        - data: bytes, raw image data
        - **kwargs: additional options
        """
    
    def add_from_heif(self, image):
        """
        Add image from another HeifImage.
        
        Parameters:
        - image: HeifImage, source image to add
        """
    
    def add_from_pillow(self, image):
        """
        Add image from Pillow Image.
        
        Parameters:
        - image: PIL Image, source image to add
        """
    
    def to_pillow(self) -> 'PIL.Image.Image':
        """
        Convert primary image to Pillow Image.
        
        Returns:
        PIL.Image.Image: Pillow Image object with metadata preserved
        """
    
    def get_aux_image(self, aux_id):
        """
        Get auxiliary image by ID.
        
        Parameters:
        - aux_id: int, auxiliary image identifier
        
        Returns:
        HeifAuxImage: Auxiliary image object
        """
    
    def __len__(self) -> int:
        """Return number of images in container."""
    
    def __iter__(self):
        """Iterate over all images in container."""
    
    def __getitem__(self, index) -> 'HeifImage':
        """Get image by index."""
    
    def __delitem__(self, index):
        """Delete image by index."""

Usage example:

import pillow_heif

# Create from file
heif_file = pillow_heif.open_heif("multi_image.heic")

# Access primary image properties
print(f"Primary image: {heif_file.size} {heif_file.mode}")
print(f"Has alpha: {heif_file.has_alpha}")
print(f"MIME type: {heif_file.mimetype}")

# Container operations
print(f"Total images: {len(heif_file)}")
for i, image in enumerate(heif_file):
    print(f"Image {i}: {image.size}")

# Add new image
heif_file.add_frombytes("RGB", (100, 100), b"..." * 30000)

# Save modified file
heif_file.save("output.heic", quality=95)

HeifImage - Individual Image

Represents a single image within a HeifFile with full access to image data, metadata, and associated auxiliary images.

class HeifImage:
    """
    Individual image within a HEIF/AVIF container.
    
    Properties:
    - size: tuple[int, int], image dimensions (width, height)
    - mode: str, color mode ('RGB', 'RGBA', 'L', etc.)
    - data: bytes, raw image data
    - stride: int, bytes per row of image data
    - has_alpha: bool, True if image has alpha channel
    - premultiplied_alpha: bool, True if alpha is premultiplied
    - info: dict, image metadata dictionary
    - __array_interface__: dict, NumPy array interface for direct array access
    """
    
    @property
    def size(self) -> tuple[int, int]:
        """Image dimensions (width, height)."""
    
    @property
    def mode(self) -> str:
        """Color mode ('RGB', 'RGBA', 'L', etc.)."""
    
    @property
    def data(self) -> bytes:
        """Raw image data."""
    
    @property
    def stride(self) -> int:
        """Bytes per row of image data."""
    
    @property
    def has_alpha(self) -> bool:
        """True if image has alpha channel."""
    
    @property
    def premultiplied_alpha(self) -> bool:
        """True if alpha is premultiplied."""
    
    @premultiplied_alpha.setter
    def premultiplied_alpha(self, value: bool):
        """Set premultiplied alpha state."""
    
    @property
    def info(self) -> dict:
        """Image metadata dictionary."""
    
    @property
    def __array_interface__(self):
        """NumPy array interface for direct array access."""
    
    def to_pillow(self):
        """
        Convert image to Pillow Image.
        
        Returns:
        PIL.Image: Pillow Image object with metadata preserved
        """
    
    def get_aux_image(self, aux_id):
        """
        Get auxiliary image associated with this image.
        
        Parameters:
        - aux_id: int, auxiliary image identifier
        
        Returns:
        HeifAuxImage: Associated auxiliary image
        """
    
    def load(self):
        """
        Decode image data if not already loaded.
        
        Notes:
        - Called automatically when accessing data property
        - Useful for explicit control over decoding timing
        """

Usage example:

import pillow_heif
import numpy as np

heif_file = pillow_heif.open_heif("image.heic")

# Access individual image
image = heif_file[0]  # First image
print(f"Image size: {image.size}")
print(f"Color mode: {image.mode}")

# Convert to NumPy array using array interface
np_array = np.asarray(image)
print(f"Array shape: {np_array.shape}")

# Convert to Pillow for processing
pil_image = image.to_pillow()
pil_image.show()

# Access metadata
if 'exif' in image.info:
    print("EXIF data present")

HeifDepthImage - Depth Information

Represents depth image data associated with a HeifImage, providing 3D depth information for effects and processing.

class HeifDepthImage:
    """
    Depth image associated with a HeifImage.
    
    Properties:
    - size: tuple[int, int], depth image dimensions
    - mode: str, depth data mode (typically 'L' for grayscale)
    - data: bytes, raw depth data
    - stride: int, bytes per row of depth data
    - info: dict, depth-specific metadata
    """
    
    @property
    def size(self) -> tuple[int, int]:
        """Depth image dimensions."""
    
    @property
    def mode(self) -> str:
        """Depth data mode (typically 'L' for grayscale)."""
    
    @property
    def data(self) -> bytes:
        """Raw depth data."""
    
    @property
    def stride(self) -> int:
        """Bytes per row of depth data."""
    
    @property
    def info(self) -> dict:
        """Depth-specific metadata."""
    
    def to_pillow(self):
        """
        Convert depth image to Pillow Image.
        
        Returns:
        PIL.Image: Pillow Image containing depth information
        """
    
    def load(self):
        """
        Decode depth data if not already loaded.
        """

Usage example:

import pillow_heif

heif_file = pillow_heif.open_heif("depth_image.heic")
image = heif_file[0]

# Check if image has depth information
if hasattr(image, 'depth_images') and image.depth_images:
    depth_image = image.depth_images[0]
    print(f"Depth image size: {depth_image.size}")
    
    # Convert to Pillow for visualization
    depth_pil = depth_image.to_pillow()
    depth_pil.save("depth_map.png")

HeifAuxImage - Auxiliary Images

Represents auxiliary images associated with a HeifImage, such as alpha masks, thumbnails, or other supplementary data.

class HeifAuxImage:
    """
    Auxiliary image associated with a HeifImage.
    
    Properties:
    - size: tuple[int, int], auxiliary image dimensions
    - mode: str, color mode of auxiliary data
    - data: bytes, raw auxiliary image data
    - stride: int, bytes per row of auxiliary data
    """
    
    @property
    def size(self) -> tuple[int, int]:
        """Auxiliary image dimensions."""
    
    @property
    def mode(self) -> str:
        """Color mode of auxiliary data."""
    
    @property
    def data(self) -> bytes:
        """Raw auxiliary image data."""
    
    @property
    def stride(self) -> int:
        """Bytes per row of auxiliary data."""
    
    def to_pillow(self):
        """
        Convert auxiliary image to Pillow Image.
        
        Returns:
        PIL.Image: Pillow Image containing auxiliary data
        """
    
    def load(self):
        """
        Decode auxiliary data if not already loaded.
        """

Usage example:

import pillow_heif

heif_file = pillow_heif.open_heif("image_with_aux.heic")
image = heif_file[0]

# Access auxiliary images
aux_image = image.get_aux_image(1)  # Get auxiliary image by ID
if aux_image:
    print(f"Auxiliary image size: {aux_image.size}")
    aux_pil = aux_image.to_pillow()
    aux_pil.save("auxiliary_data.png")

Common Usage Patterns

Working with Multi-Image Files

import pillow_heif

# Open multi-image HEIF file
heif_file = pillow_heif.open_heif("burst_photos.heic")

# Process each image
for i, image in enumerate(heif_file):
    print(f"Processing image {i+1}/{len(heif_file)}")
    pil_image = image.to_pillow()
    pil_image.save(f"image_{i+1}.jpg", quality=95)

# Access specific images
primary_image = heif_file[heif_file.primary_index]
print(f"Primary image: {primary_image.size}")

Metadata Access

import pillow_heif

heif_file = pillow_heif.open_heif("image_with_metadata.heic")

# Access metadata from HeifFile
print("File metadata:")
for key, value in heif_file.info.items():
    print(f"  {key}: {type(value).__name__}")

# Access metadata from individual images
image = heif_file[0]
if 'exif' in image.info:
    exif_data = image.info['exif']
    print(f"EXIF data size: {len(exif_data)} bytes")

NumPy Integration

import pillow_heif
import numpy as np

heif_file = pillow_heif.open_heif("image.heic")
image = heif_file[0]

# Direct NumPy array access
np_array = np.asarray(image)
print(f"Array shape: {np_array.shape}")
print(f"Data type: {np_array.dtype}")

# Process with NumPy
processed = np_array * 0.8  # Darken image
processed = processed.astype(np.uint8)

# Convert back to HeifFile
new_heif = pillow_heif.from_bytes(
    mode=image.mode,
    size=image.size,
    data=processed.tobytes()
)

Install with Tessl CLI

npx tessl i tessl/pypi-pillow-heif

docs

encoding.md

file-operations.md

image-classes.md

index.md

metadata-utilities.md

pillow-integration.md

tile.json