or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

encoding.mdfile-operations.mdimage-classes.mdindex.mdmetadata-utilities.mdpillow-integration.md

pillow-integration.mddocs/

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

```