0
# Pillow Integration
1
2
Plugin functionality that adds seamless HEIF/AVIF support to Pillow. This integration allows existing PIL/Pillow applications to work with HEIF/AVIF files without code changes, providing full format support through Pillow's standard interface.
3
4
## Capabilities
5
6
### Plugin Registration
7
8
Registers HEIF/AVIF format support with Pillow, enabling standard PIL operations on HEIF/AVIF files.
9
10
```python { .api }
11
def register_heif_opener(**kwargs) -> None:
12
"""
13
Register HEIF/AVIF format support with Pillow.
14
15
Parameters:
16
- **kwargs: options passed to HeifImageFile for all opened files
17
18
Options:
19
- convert_hdr_to_8bit: bool, convert HDR images to 8-bit (default: True)
20
- bgr_mode: bool, use BGR pixel order (default: False)
21
22
Notes:
23
- Must be called before using PIL.Image.open() on HEIF/AVIF files
24
- Registration persists for the entire Python session
25
- Can be called multiple times with different options
26
"""
27
```
28
29
Usage example:
30
```python
31
from PIL import Image
32
from pillow_heif import register_heif_opener
33
34
# Register HEIF support with default settings
35
register_heif_opener()
36
37
# Now Pillow can handle HEIF files
38
im = Image.open("image.heic")
39
im = im.resize((800, 600))
40
im.save("resized.jpg")
41
42
# Register with custom options
43
register_heif_opener(convert_hdr_to_8bit=False, bgr_mode=False)
44
45
# HDR images will preserve their bit depth
46
hdr_image = Image.open("hdr.heic")
47
print(f"Mode: {hdr_image.mode}") # May show high bit depth modes
48
```
49
50
### Automatic Plugin Loading
51
52
Alternative method for plugin registration through import:
53
54
```python
55
# Automatic registration - imports and registers the plugin
56
import pillow_heif.HeifImagePlugin
57
58
# Now PIL can handle HEIF files
59
from PIL import Image
60
im = Image.open("image.heic")
61
```
62
63
### HeifImageFile - Pillow ImageFile Class
64
65
Pillow ImageFile subclass that provides HEIF/AVIF format support with multi-frame capabilities.
66
67
```python { .api }
68
class HeifImageFile:
69
"""
70
Pillow ImageFile subclass for HEIF/AVIF files.
71
72
Class Attributes:
73
- format: str = "HEIF", Pillow format identifier
74
- format_description: str = "HEIF container", format description
75
76
Properties:
77
- n_frames: int, number of frames/images in file
78
- is_animated: bool, True if file contains multiple frames
79
80
Inherited Properties (from PIL.ImageFile.ImageFile):
81
- size: tuple[int, int], image dimensions
82
- mode: str, color mode
83
- info: dict, image metadata including EXIF, XMP, IPTC
84
"""
85
86
def seek(self, frame):
87
"""
88
Seek to specific frame in multi-image file.
89
90
Parameters:
91
- frame: int, frame number to seek to (0-indexed)
92
93
Raises:
94
EOFError: If frame number is out of range
95
"""
96
97
def tell(self) -> int:
98
"""
99
Get current frame number.
100
101
Returns:
102
int: Current frame index (0-indexed)
103
"""
104
105
def verify(self):
106
"""
107
Verify image file integrity.
108
109
Raises:
110
Exception: If file is corrupted or invalid
111
"""
112
```
113
114
Usage example:
115
```python
116
from PIL import Image
117
from pillow_heif import register_heif_opener
118
119
register_heif_opener()
120
121
# Open multi-frame HEIF file
122
with Image.open("burst_photos.heic") as im:
123
print(f"Format: {im.format}") # "HEIF"
124
print(f"Total frames: {im.n_frames}")
125
print(f"Is animated: {im.is_animated}")
126
127
# Process each frame
128
for frame in range(im.n_frames):
129
im.seek(frame)
130
print(f"Frame {frame}: {im.size} {im.mode}")
131
im.save(f"frame_{frame}.jpg")
132
133
# Return to first frame
134
im.seek(0)
135
```
136
137
## Integration Patterns
138
139
### Standard Pillow Workflows
140
141
```python
142
from PIL import Image, ImageFilter, ImageEnhance
143
from pillow_heif import register_heif_opener
144
145
register_heif_opener()
146
147
# Standard PIL operations work seamlessly
148
image = Image.open("photo.heic")
149
150
# Image processing
151
enhanced = ImageEnhance.Sharpness(image).enhance(1.5)
152
blurred = enhanced.filter(ImageFilter.BLUR)
153
154
# Format conversion
155
blurred.save("processed.jpg", quality=95)
156
blurred.save("processed.png")
157
158
# Save back to HEIF
159
blurred.save("processed.heic", quality=90)
160
```
161
162
### Batch Processing with Pillow
163
164
```python
165
from PIL import Image
166
from pillow_heif import register_heif_opener
167
import os
168
169
register_heif_opener()
170
171
def process_images(input_dir, output_dir, size=(800, 600)):
172
"""Process all images in directory using standard PIL operations."""
173
os.makedirs(output_dir, exist_ok=True)
174
175
for filename in os.listdir(input_dir):
176
if filename.lower().endswith(('.heic', '.heif', '.avif', '.jpg', '.png')):
177
input_path = os.path.join(input_dir, filename)
178
output_path = os.path.join(output_dir, filename)
179
180
try:
181
with Image.open(input_path) as im:
182
# Standard PIL operations
183
im.thumbnail(size, Image.Resampling.LANCZOS)
184
im.save(output_path, quality=85)
185
print(f"Processed: {filename}")
186
except Exception as e:
187
print(f"Error processing {filename}: {e}")
188
189
process_images("photos/", "thumbnails/")
190
```
191
192
### Multi-Frame Animation Support
193
194
```python
195
from PIL import Image
196
from pillow_heif import register_heif_opener
197
198
register_heif_opener()
199
200
def create_gif_from_heif(heif_path, gif_path, duration=500):
201
"""Convert multi-frame HEIF to animated GIF."""
202
frames = []
203
204
with Image.open(heif_path) as im:
205
for frame in range(im.n_frames):
206
im.seek(frame)
207
# Convert to RGB for GIF compatibility
208
frame_rgb = im.convert('RGB')
209
frames.append(frame_rgb.copy())
210
211
# Save as animated GIF
212
frames[0].save(
213
gif_path,
214
save_all=True,
215
append_images=frames[1:],
216
duration=duration,
217
loop=0
218
)
219
220
create_gif_from_heif("burst.heic", "animation.gif")
221
```
222
223
### Metadata Preservation
224
225
```python
226
from PIL import Image
227
from pillow_heif import register_heif_opener
228
229
register_heif_opener()
230
231
# Open image with metadata
232
with Image.open("photo_with_exif.heic") as im:
233
print("Original metadata:")
234
for key, value in im.info.items():
235
print(f" {key}: {type(value).__name__}")
236
237
# Process image
238
resized = im.resize((1024, 768))
239
240
# Save with metadata preserved
241
resized.save("resized_with_metadata.heic",
242
quality=90,
243
exif=im.info.get('exif'),
244
icc_profile=im.info.get('icc_profile'))
245
```
246
247
### Format Detection and Conversion
248
249
```python
250
from PIL import Image
251
from pillow_heif import register_heif_opener
252
import os
253
254
register_heif_opener()
255
256
def convert_to_heif(source_path, target_path, quality=85):
257
"""Convert any supported format to HEIF."""
258
with Image.open(source_path) as im:
259
print(f"Source format: {im.format}")
260
print(f"Size: {im.size}")
261
print(f"Mode: {im.mode}")
262
263
# Convert to RGB if necessary
264
if im.mode in ('RGBA', 'LA'):
265
# Keep transparency
266
im.save(target_path, quality=quality)
267
elif im.mode not in ('RGB', 'L'):
268
# Convert to RGB
269
rgb_im = im.convert('RGB')
270
rgb_im.save(target_path, quality=quality)
271
else:
272
im.save(target_path, quality=quality)
273
274
# Convert various formats to HEIF
275
convert_to_heif("photo.jpg", "photo.heic")
276
convert_to_heif("image.png", "image.heic")
277
convert_to_heif("old_photo.tiff", "old_photo.heic")
278
```
279
280
### HDR Image Handling
281
282
```python
283
from PIL import Image
284
from pillow_heif import register_heif_opener
285
286
# Register with HDR preservation
287
register_heif_opener(convert_hdr_to_8bit=False)
288
289
with Image.open("hdr_photo.heic") as im:
290
print(f"HDR mode: {im.mode}") # May show modes like 'RGB;10' or 'RGB;12'
291
292
# For display, convert to 8-bit
293
display_image = im.copy()
294
if ';' in display_image.mode: # HDR mode
295
display_image = display_image.convert('RGB')
296
297
display_image.show()
298
299
# Save preserving HDR
300
im.save("hdr_copy.heic", quality=-1) # Preserve original quality/depth
301
```
302
303
## Error Handling and Compatibility
304
305
```python
306
from PIL import Image
307
from pillow_heif import register_heif_opener
308
import os
309
310
def safe_image_open(filepath):
311
"""Safely open image with fallback handling."""
312
try:
313
# Try to register HEIF support
314
register_heif_opener()
315
except ImportError:
316
print("HEIF support not available")
317
318
try:
319
with Image.open(filepath) as im:
320
print(f"Successfully opened {os.path.basename(filepath)}")
321
print(f"Format: {im.format}, Size: {im.size}, Mode: {im.mode}")
322
return im.copy()
323
except Exception as e:
324
print(f"Error opening {filepath}: {e}")
325
return None
326
327
# Usage
328
image = safe_image_open("test.heic")
329
if image:
330
image.save("converted.jpg")
331
```
332
333
### Checking Format Support
334
335
```python
336
from PIL import Image
337
from pillow_heif import register_heif_opener
338
339
# Check if HEIF support is available
340
try:
341
register_heif_opener()
342
print("HEIF support available")
343
344
# Check which formats are supported
345
print("Supported formats:", Image.registered_extensions())
346
347
# Test HEIF opening
348
if '.heic' in Image.registered_extensions():
349
print("HEIC files supported")
350
if '.avif' in Image.registered_extensions():
351
print("AVIF files supported")
352
353
except ImportError as e:
354
print(f"HEIF support not available: {e}")
355
```