0
# Metadata and Utilities
1
2
Helper functions for MIME type detection, orientation handling, library information, and plugin loading. These utilities provide essential support functionality for HEIF/AVIF processing and integration with the broader image processing ecosystem.
3
4
## Capabilities
5
6
### MIME Type Detection
7
8
Determines the MIME type of HEIF/AVIF files for proper content type handling and format identification.
9
10
```python { .api }
11
def get_file_mimetype(fp) -> str:
12
"""
13
Determine MIME type of HEIF/AVIF file.
14
15
Parameters:
16
- fp: file path (str) or file-like object
17
18
Returns:
19
str: MIME type string ('image/heif', 'image/avif', or empty string if not supported)
20
21
Notes:
22
- Fast detection based on file signature
23
- Returns empty string for unsupported formats
24
- Useful for web applications and content type headers
25
"""
26
```
27
28
Usage example:
29
```python
30
import pillow_heif
31
32
# Check MIME type of various files
33
files = ["image.heic", "photo.avif", "unknown.jpg"]
34
35
for filepath in files:
36
mimetype = pillow_heif.get_file_mimetype(filepath)
37
if mimetype:
38
print(f"{filepath}: {mimetype}")
39
else:
40
print(f"{filepath}: Not a HEIF/AVIF file")
41
42
# Web application usage
43
def get_content_type(filepath):
44
"""Get appropriate content type for web responses."""
45
mimetype = pillow_heif.get_file_mimetype(filepath)
46
return mimetype if mimetype else "application/octet-stream"
47
```
48
49
### EXIF Orientation Handling
50
51
Resets EXIF orientation metadata to default value, useful for correcting orientation-related display issues.
52
53
```python { .api }
54
def set_orientation(info: dict) -> int | None:
55
"""
56
Reset EXIF orientation metadata to default (1).
57
58
Parameters:
59
- info: dict, image metadata dictionary containing EXIF data
60
61
Returns:
62
int | None: Previous orientation value, or None if no EXIF data present
63
64
Notes:
65
- Modifies the info dictionary in-place
66
- Sets orientation to 1 (normal, no rotation)
67
- Useful after applying rotation corrections
68
"""
69
```
70
71
Usage example:
72
```python
73
import pillow_heif
74
75
# Open image and check orientation
76
heif_file = pillow_heif.open_heif("rotated_photo.heic")
77
print(f"Metadata keys: {list(heif_file.info.keys())}")
78
79
# Reset orientation if present
80
if 'exif' in heif_file.info:
81
old_orientation = pillow_heif.set_orientation(heif_file.info)
82
if old_orientation:
83
print(f"Reset orientation from {old_orientation} to 1")
84
85
# Save with corrected orientation
86
heif_file.save("corrected_photo.heic")
87
88
# Function to auto-correct orientation
89
def correct_orientation(heif_file):
90
"""Auto-correct image orientation using EXIF data."""
91
if 'exif' in heif_file.info:
92
# Apply rotation based on EXIF before resetting
93
pil_image = heif_file.to_pillow()
94
95
# PIL automatically handles EXIF orientation
96
# Reset EXIF to prevent double-correction
97
pillow_heif.set_orientation(heif_file.info)
98
99
return pillow_heif.from_pillow(pil_image)
100
return heif_file
101
```
102
103
### Library Information
104
105
Functions to retrieve version and capability information about the underlying libheif library.
106
107
```python { .api }
108
def libheif_version() -> str:
109
"""
110
Get version string of underlying libheif library.
111
112
Returns:
113
str: Version string (e.g., "1.17.6")
114
115
Notes:
116
- Returns the version of the C library, not the Python bindings
117
- Useful for compatibility checking and debugging
118
"""
119
120
def libheif_info() -> dict:
121
"""
122
Get comprehensive information about libheif capabilities.
123
124
Returns:
125
dict: Information dictionary with keys:
126
- 'version': str, libheif version
127
- 'encoders': list, available encoder names
128
- 'decoders': list, available decoder names
129
- 'builtin_encoders': list, built-in encoder names
130
- 'builtin_decoders': list, built-in decoder names
131
132
Notes:
133
- Encoder/decoder availability depends on compile-time options
134
- Plugin encoders/decoders loaded at runtime are included
135
"""
136
```
137
138
Usage example:
139
```python
140
import pillow_heif
141
import json
142
143
# Check library version
144
version = pillow_heif.libheif_version()
145
print(f"libheif version: {version}")
146
147
# Get detailed capability information
148
info = pillow_heif.libheif_info()
149
print("Library capabilities:")
150
print(json.dumps(info, indent=2))
151
152
# Check for specific encoder support
153
if 'x265' in info.get('encoders', []):
154
print("x265 HEIF encoder available")
155
if 'aom' in info.get('encoders', []):
156
print("AOM AV1 encoder available for AVIF")
157
158
# Conditional functionality based on capabilities
159
def get_available_formats():
160
"""Get list of supported output formats."""
161
info = pillow_heif.libheif_info()
162
formats = []
163
164
if any('heif' in enc.lower() for enc in info.get('encoders', [])):
165
formats.append('HEIF')
166
if any('av1' in enc.lower() or 'aom' in enc.lower()
167
for enc in info.get('encoders', [])):
168
formats.append('AVIF')
169
170
return formats
171
172
print(f"Available output formats: {get_available_formats()}")
173
```
174
175
### Plugin Loading
176
177
Loads additional libheif plugins for extended format support and codec capabilities.
178
179
```python { .api }
180
def load_libheif_plugin(plugin_path: str) -> None:
181
"""
182
Load specified LibHeif plugin for extended format support.
183
184
Parameters:
185
- plugin_path: str, path to plugin library file
186
187
Notes:
188
- Extends encoder/decoder capabilities at runtime
189
- Plugin path must point to valid libheif plugin library
190
- Changes are reflected in libheif_info() output after loading
191
192
Raises:
193
OSError: If plugin cannot be loaded or is invalid
194
"""
195
```
196
197
Usage example:
198
```python
199
import pillow_heif
200
import os
201
202
# Check capabilities before loading plugins
203
info_before = pillow_heif.libheif_info()
204
print(f"Encoders before: {info_before.get('encoders', [])}")
205
206
# Load additional plugin (example path)
207
plugin_path = "/usr/local/lib/libheif/plugins/libheif-x265.so"
208
if os.path.exists(plugin_path):
209
try:
210
pillow_heif.load_libheif_plugin(plugin_path)
211
print(f"Successfully loaded plugin: {plugin_path}")
212
213
# Check updated capabilities
214
info_after = pillow_heif.libheif_info()
215
new_encoders = set(info_after.get('encoders', [])) - set(info_before.get('encoders', []))
216
if new_encoders:
217
print(f"New encoders available: {list(new_encoders)}")
218
219
except OSError as e:
220
print(f"Failed to load plugin: {e}")
221
222
# Batch plugin loading
223
def load_available_plugins(plugin_dir="/usr/local/lib/libheif/plugins"):
224
"""Load all available plugins from directory."""
225
if not os.path.exists(plugin_dir):
226
return
227
228
for filename in os.listdir(plugin_dir):
229
if filename.endswith(('.so', '.dll', '.dylib')):
230
plugin_path = os.path.join(plugin_dir, filename)
231
try:
232
pillow_heif.load_libheif_plugin(plugin_path)
233
print(f"Loaded: {filename}")
234
except OSError:
235
print(f"Failed to load: {filename}")
236
```
237
238
## Configuration Options Module
239
240
Runtime configuration variables that control library behavior, available in the `pillow_heif.options` module.
241
242
```python { .api }
243
# Threading configuration
244
DECODE_THREADS = 4 # Maximum threads for image decoding
245
246
# Feature toggles
247
THUMBNAILS = True # Enable/disable thumbnail support
248
DEPTH_IMAGES = True # Enable/disable depth image support
249
AUX_IMAGES = True # Enable/disable auxiliary image support
250
251
# Encoding defaults
252
QUALITY = None # Default encoding quality (None, -1, or 0-100)
253
SAVE_HDR_TO_12_BIT = False # Save 16-bit images as 12-bit vs 10-bit
254
SAVE_NCLX_PROFILE = True # Save NCLX color profiles
255
256
# Codec preferences
257
PREFERRED_ENCODER = {"AVIF": "", "HEIF": ""} # Preferred encoder IDs
258
PREFERRED_DECODER = {"AVIF": "", "HEIF": ""} # Preferred decoder IDs
259
260
# Security and compatibility
261
ALLOW_INCORRECT_HEADERS = False # Allow size mismatch in headers
262
DISABLE_SECURITY_LIMITS = False # Disable libheif security limits
263
```
264
265
Usage example:
266
```python
267
import pillow_heif
268
269
# Configure threading
270
pillow_heif.options.DECODE_THREADS = 8 # Use more threads for faster decoding
271
272
# Disable features for memory savings
273
pillow_heif.options.THUMBNAILS = False
274
pillow_heif.options.DEPTH_IMAGES = False
275
276
# Set default quality
277
pillow_heif.options.QUALITY = 85
278
279
# Configure HDR handling
280
pillow_heif.options.SAVE_HDR_TO_12_BIT = True
281
282
# Set encoder preferences
283
pillow_heif.options.PREFERRED_ENCODER["HEIF"] = "x265"
284
pillow_heif.options.PREFERRED_ENCODER["AVIF"] = "aom"
285
286
# Now all operations use these settings
287
heif_file = pillow_heif.open_heif("image.heic") # Uses 8 decode threads
288
heif_file.save("output.heic") # Uses quality=85, x265 encoder
289
```
290
291
## Color Space Enumerations
292
293
Enumeration types for color space and metadata handling, extending Python's IntEnum.
294
295
```python { .api }
296
class HeifColorPrimaries(IntEnum):
297
"""NCLX color primaries definitions for proper color reproduction."""
298
ITU_R_BT_709_5 = 1
299
UNSPECIFIED = 2
300
ITU_R_BT_470_6_SYSTEM_M = 4
301
ITU_R_BT_470_6_SYSTEM_B_G = 5
302
ITU_R_BT_601_6 = 6
303
SMPTE_240M = 7
304
GENERIC_FILM = 8
305
ITU_R_BT_2020_2_AND_2100_0 = 9
306
SMPTE_ST_428_1 = 10
307
SMPTE_RP_431_2 = 11
308
SMPTE_EG_432_1 = 12
309
EBU_TECH_3213_E = 22
310
311
class HeifTransferCharacteristics(IntEnum):
312
"""NCLX transfer characteristics for gamma/transfer functions."""
313
ITU_R_BT_709_5 = 1
314
UNSPECIFIED = 2
315
ITU_R_BT_470_6_SYSTEM_M = 4
316
ITU_R_BT_470_6_SYSTEM_B_G = 5
317
ITU_R_BT_601_6 = 6
318
SMPTE_240M = 7
319
LINEAR = 8
320
LOGARITHMIC_100 = 9
321
LOGARITHMIC_100_SQRT10 = 10
322
IEC_61966_2_4 = 11
323
ITU_R_BT_1361 = 12
324
IEC_61966_2_1 = 13
325
ITU_R_BT_2020_2_10BIT = 14
326
ITU_R_BT_2020_2_12BIT = 15
327
ITU_R_BT_2100_0_PQ = 16
328
SMPTE_ST_428_1 = 17
329
ITU_R_BT_2100_0_HLG = 18
330
331
class HeifMatrixCoefficients(IntEnum):
332
"""NCLX matrix coefficients for color space conversion."""
333
RGB_GBR = 0
334
ITU_R_BT_709_5 = 1
335
UNSPECIFIED = 2
336
US_FCC_T47 = 4
337
ITU_R_BT_470_6_SYSTEM_B_G = 5
338
ITU_R_BT_601_6 = 6
339
SMPTE_240M = 7
340
YCGCO = 8
341
ITU_R_BT_2020_2_NON_CONSTANT_LUMINANCE = 9
342
ITU_R_BT_2020_2_CONSTANT_LUMINANCE = 10
343
SMPTE_ST_2085 = 11
344
CHROMATICITY_DERIVED_NON_CONSTANT_LUMINANCE = 12
345
CHROMATICITY_DERIVED_CONSTANT_LUMINANCE = 13
346
ICTCP = 14
347
348
class HeifDepthRepresentationType(IntEnum):
349
"""Depth image representation types."""
350
UNIFORM_INVERSE_Z = 0
351
UNIFORM_DISPARITY = 1
352
UNIFORM_Z = 2
353
NON_UNIFORM_DISPARITY = 3
354
```
355
356
Usage example:
357
```python
358
import pillow_heif
359
from pillow_heif import HeifColorPrimaries, HeifTransferCharacteristics
360
361
# Working with color space metadata
362
heif_file = pillow_heif.open_heif("hdr_image.heic")
363
364
# Check color space information in metadata
365
if 'nclx_profile' in heif_file.info:
366
nclx = heif_file.info['nclx_profile']
367
368
# Use enums for color space interpretation
369
if nclx.get('color_primaries') == HeifColorPrimaries.ITU_R_BT_2020_2_AND_2100_0:
370
print("Image uses BT.2020 color primaries (wide color gamut)")
371
372
if nclx.get('transfer_characteristics') == HeifTransferCharacteristics.ITU_R_BT_2100_0_PQ:
373
print("Image uses PQ transfer characteristics (HDR)")
374
375
# Setting color space for encoding
376
encoding_options = {
377
'nclx_profile': {
378
'color_primaries': HeifColorPrimaries.ITU_R_BT_709_5,
379
'transfer_characteristics': HeifTransferCharacteristics.ITU_R_BT_709_5,
380
'matrix_coefficients': pillow_heif.HeifMatrixCoefficients.ITU_R_BT_709_5,
381
'full_range': True
382
}
383
}
384
385
heif_file.save("srgb_image.heic", **encoding_options)
386
```