Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/PIL/Image.py: 45%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1758 statements  

1# 

2# The Python Imaging Library. 

3# $Id$ 

4# 

5# the Image class wrapper 

6# 

7# partial release history: 

8# 1995-09-09 fl Created 

9# 1996-03-11 fl PIL release 0.0 (proof of concept) 

10# 1996-04-30 fl PIL release 0.1b1 

11# 1999-07-28 fl PIL release 1.0 final 

12# 2000-06-07 fl PIL release 1.1 

13# 2000-10-20 fl PIL release 1.1.1 

14# 2001-05-07 fl PIL release 1.1.2 

15# 2002-03-15 fl PIL release 1.1.3 

16# 2003-05-10 fl PIL release 1.1.4 

17# 2005-03-28 fl PIL release 1.1.5 

18# 2006-12-02 fl PIL release 1.1.6 

19# 2009-11-15 fl PIL release 1.1.7 

20# 

21# Copyright (c) 1997-2009 by Secret Labs AB. All rights reserved. 

22# Copyright (c) 1995-2009 by Fredrik Lundh. 

23# 

24# See the README file for information on usage and redistribution. 

25# 

26 

27from __future__ import annotations 

28 

29import abc 

30import atexit 

31import builtins 

32import io 

33import logging 

34import math 

35import os 

36import re 

37import struct 

38import sys 

39import tempfile 

40import warnings 

41from collections.abc import MutableMapping 

42from enum import IntEnum 

43from typing import IO, Protocol, cast 

44 

45# VERSION was removed in Pillow 6.0.0. 

46# PILLOW_VERSION was removed in Pillow 9.0.0. 

47# Use __version__ instead. 

48from . import ( 

49 ExifTags, 

50 ImageMode, 

51 TiffTags, 

52 UnidentifiedImageError, 

53 __version__, 

54 _plugins, 

55) 

56from ._binary import i32le, o32be, o32le 

57from ._deprecate import deprecate 

58from ._util import DeferredError, is_path 

59 

60ElementTree: ModuleType | None 

61try: 

62 from defusedxml import ElementTree 

63except ImportError: 

64 ElementTree = None 

65 

66TYPE_CHECKING = False 

67if TYPE_CHECKING: 

68 from collections.abc import Callable, Iterator, Sequence 

69 from types import ModuleType 

70 from typing import Any, Literal 

71 

72logger = logging.getLogger(__name__) 

73 

74 

75class DecompressionBombWarning(RuntimeWarning): 

76 pass 

77 

78 

79class DecompressionBombError(Exception): 

80 pass 

81 

82 

83WARN_POSSIBLE_FORMATS: bool = False 

84 

85# Limit to around a quarter gigabyte for a 24-bit (3 bpp) image 

86MAX_IMAGE_PIXELS: int | None = int(1024 * 1024 * 1024 // 4 // 3) 

87 

88 

89try: 

90 # If the _imaging C module is not present, Pillow will not load. 

91 # Note that other modules should not refer to _imaging directly; 

92 # import Image and use the Image.core variable instead. 

93 # Also note that Image.core is not a publicly documented interface, 

94 # and should be considered private and subject to change. 

95 from . import _imaging as core 

96 

97 if __version__ != getattr(core, "PILLOW_VERSION", None): 

98 msg = ( 

99 "The _imaging extension was built for another version of Pillow or PIL:\n" 

100 f"Core version: {getattr(core, 'PILLOW_VERSION', None)}\n" 

101 f"Pillow version: {__version__}" 

102 ) 

103 raise ImportError(msg) 

104 

105except ImportError as v: 

106 # Explanations for ways that we know we might have an import error 

107 if str(v).startswith("Module use of python"): 

108 # The _imaging C module is present, but not compiled for 

109 # the right version (windows only). Print a warning, if 

110 # possible. 

111 warnings.warn( 

112 "The _imaging extension was built for another version of Python.", 

113 RuntimeWarning, 

114 ) 

115 elif str(v).startswith("The _imaging extension"): 

116 warnings.warn(str(v), RuntimeWarning) 

117 # Fail here anyway. Don't let people run with a mostly broken Pillow. 

118 # see docs/porting.rst 

119 raise 

120 

121 

122# 

123# Constants 

124 

125 

126# transpose 

127class Transpose(IntEnum): 

128 FLIP_LEFT_RIGHT = 0 

129 FLIP_TOP_BOTTOM = 1 

130 ROTATE_90 = 2 

131 ROTATE_180 = 3 

132 ROTATE_270 = 4 

133 TRANSPOSE = 5 

134 TRANSVERSE = 6 

135 

136 

137# transforms (also defined in Imaging.h) 

138class Transform(IntEnum): 

139 AFFINE = 0 

140 EXTENT = 1 

141 PERSPECTIVE = 2 

142 QUAD = 3 

143 MESH = 4 

144 

145 

146# resampling filters (also defined in Imaging.h) 

147class Resampling(IntEnum): 

148 NEAREST = 0 

149 BOX = 4 

150 BILINEAR = 2 

151 HAMMING = 5 

152 BICUBIC = 3 

153 LANCZOS = 1 

154 

155 

156_filters_support = { 

157 Resampling.BOX: 0.5, 

158 Resampling.BILINEAR: 1.0, 

159 Resampling.HAMMING: 1.0, 

160 Resampling.BICUBIC: 2.0, 

161 Resampling.LANCZOS: 3.0, 

162} 

163 

164 

165# dithers 

166class Dither(IntEnum): 

167 NONE = 0 

168 ORDERED = 1 # Not yet implemented 

169 RASTERIZE = 2 # Not yet implemented 

170 FLOYDSTEINBERG = 3 # default 

171 

172 

173# palettes/quantizers 

174class Palette(IntEnum): 

175 WEB = 0 

176 ADAPTIVE = 1 

177 

178 

179class Quantize(IntEnum): 

180 MEDIANCUT = 0 

181 MAXCOVERAGE = 1 

182 FASTOCTREE = 2 

183 LIBIMAGEQUANT = 3 

184 

185 

186module = sys.modules[__name__] 

187for enum in (Transpose, Transform, Resampling, Dither, Palette, Quantize): 

188 for item in enum: 

189 setattr(module, item.name, item.value) 

190 

191 

192if hasattr(core, "DEFAULT_STRATEGY"): 

193 DEFAULT_STRATEGY = core.DEFAULT_STRATEGY 

194 FILTERED = core.FILTERED 

195 HUFFMAN_ONLY = core.HUFFMAN_ONLY 

196 RLE = core.RLE 

197 FIXED = core.FIXED 

198 

199 

200# -------------------------------------------------------------------- 

201# Registries 

202 

203TYPE_CHECKING = False 

204if TYPE_CHECKING: 

205 import mmap 

206 from xml.etree.ElementTree import Element 

207 

208 from IPython.lib.pretty import PrettyPrinter 

209 

210 from . import ImageFile, ImageFilter, ImagePalette, ImageQt, TiffImagePlugin 

211 from ._typing import CapsuleType, NumpyArray, StrOrBytesPath 

212ID: list[str] = [] 

213OPEN: dict[ 

214 str, 

215 tuple[ 

216 Callable[[IO[bytes], str | bytes], ImageFile.ImageFile], 

217 Callable[[bytes], bool | str] | None, 

218 ], 

219] = {} 

220MIME: dict[str, str] = {} 

221SAVE: dict[str, Callable[[Image, IO[bytes], str | bytes], None]] = {} 

222SAVE_ALL: dict[str, Callable[[Image, IO[bytes], str | bytes], None]] = {} 

223EXTENSION: dict[str, str] = {} 

224DECODERS: dict[str, type[ImageFile.PyDecoder]] = {} 

225ENCODERS: dict[str, type[ImageFile.PyEncoder]] = {} 

226 

227# -------------------------------------------------------------------- 

228# Modes 

229 

230_ENDIAN = "<" if sys.byteorder == "little" else ">" 

231 

232 

233def _conv_type_shape(im: Image) -> tuple[tuple[int, ...], str]: 

234 m = ImageMode.getmode(im.mode) 

235 shape: tuple[int, ...] = (im.height, im.width) 

236 extra = len(m.bands) 

237 if extra != 1: 

238 shape += (extra,) 

239 return shape, m.typestr 

240 

241 

242MODES = [ 

243 "1", 

244 "CMYK", 

245 "F", 

246 "HSV", 

247 "I", 

248 "I;16", 

249 "I;16B", 

250 "I;16L", 

251 "I;16N", 

252 "L", 

253 "LA", 

254 "La", 

255 "LAB", 

256 "P", 

257 "PA", 

258 "RGB", 

259 "RGBA", 

260 "RGBa", 

261 "RGBX", 

262 "YCbCr", 

263] 

264 

265# raw modes that may be memory mapped. NOTE: if you change this, you 

266# may have to modify the stride calculation in map.c too! 

267_MAPMODES = ("L", "P", "RGBX", "RGBA", "CMYK", "I;16", "I;16L", "I;16B") 

268 

269 

270def getmodebase(mode: str) -> str: 

271 """ 

272 Gets the "base" mode for given mode. This function returns "L" for 

273 images that contain grayscale data, and "RGB" for images that 

274 contain color data. 

275 

276 :param mode: Input mode. 

277 :returns: "L" or "RGB". 

278 :exception KeyError: If the input mode was not a standard mode. 

279 """ 

280 return ImageMode.getmode(mode).basemode 

281 

282 

283def getmodetype(mode: str) -> str: 

284 """ 

285 Gets the storage type mode. Given a mode, this function returns a 

286 single-layer mode suitable for storing individual bands. 

287 

288 :param mode: Input mode. 

289 :returns: "L", "I", or "F". 

290 :exception KeyError: If the input mode was not a standard mode. 

291 """ 

292 return ImageMode.getmode(mode).basetype 

293 

294 

295def getmodebandnames(mode: str) -> tuple[str, ...]: 

296 """ 

297 Gets a list of individual band names. Given a mode, this function returns 

298 a tuple containing the names of individual bands (use 

299 :py:method:`~PIL.Image.getmodetype` to get the mode used to store each 

300 individual band. 

301 

302 :param mode: Input mode. 

303 :returns: A tuple containing band names. The length of the tuple 

304 gives the number of bands in an image of the given mode. 

305 :exception KeyError: If the input mode was not a standard mode. 

306 """ 

307 return ImageMode.getmode(mode).bands 

308 

309 

310def getmodebands(mode: str) -> int: 

311 """ 

312 Gets the number of individual bands for this mode. 

313 

314 :param mode: Input mode. 

315 :returns: The number of bands in this mode. 

316 :exception KeyError: If the input mode was not a standard mode. 

317 """ 

318 return len(ImageMode.getmode(mode).bands) 

319 

320 

321# -------------------------------------------------------------------- 

322# Helpers 

323 

324_initialized = 0 

325 

326# Mapping from file extension to plugin module name for lazy importing 

327_EXTENSION_PLUGIN: dict[str, str] = { 

328 # Common formats (preinit) 

329 ".bmp": "BmpImagePlugin", 

330 ".dib": "BmpImagePlugin", 

331 ".gif": "GifImagePlugin", 

332 ".jfif": "JpegImagePlugin", 

333 ".jpe": "JpegImagePlugin", 

334 ".jpg": "JpegImagePlugin", 

335 ".jpeg": "JpegImagePlugin", 

336 ".pbm": "PpmImagePlugin", 

337 ".pgm": "PpmImagePlugin", 

338 ".pnm": "PpmImagePlugin", 

339 ".ppm": "PpmImagePlugin", 

340 ".pfm": "PpmImagePlugin", 

341 ".png": "PngImagePlugin", 

342 ".apng": "PngImagePlugin", 

343 # Less common formats (init) 

344 ".avif": "AvifImagePlugin", 

345 ".avifs": "AvifImagePlugin", 

346 ".blp": "BlpImagePlugin", 

347 ".bufr": "BufrStubImagePlugin", 

348 ".cur": "CurImagePlugin", 

349 ".dcx": "DcxImagePlugin", 

350 ".dds": "DdsImagePlugin", 

351 ".ps": "EpsImagePlugin", 

352 ".eps": "EpsImagePlugin", 

353 ".fit": "FitsImagePlugin", 

354 ".fits": "FitsImagePlugin", 

355 ".fli": "FliImagePlugin", 

356 ".flc": "FliImagePlugin", 

357 ".fpx": "FpxImagePlugin", 

358 ".ftc": "FtexImagePlugin", 

359 ".ftu": "FtexImagePlugin", 

360 ".gbr": "GbrImagePlugin", 

361 ".grib": "GribStubImagePlugin", 

362 ".h5": "Hdf5StubImagePlugin", 

363 ".hdf": "Hdf5StubImagePlugin", 

364 ".icns": "IcnsImagePlugin", 

365 ".ico": "IcoImagePlugin", 

366 ".im": "ImImagePlugin", 

367 ".iim": "IptcImagePlugin", 

368 ".jp2": "Jpeg2KImagePlugin", 

369 ".j2k": "Jpeg2KImagePlugin", 

370 ".jpc": "Jpeg2KImagePlugin", 

371 ".jpf": "Jpeg2KImagePlugin", 

372 ".jpx": "Jpeg2KImagePlugin", 

373 ".j2c": "Jpeg2KImagePlugin", 

374 ".mic": "MicImagePlugin", 

375 ".mpg": "MpegImagePlugin", 

376 ".mpeg": "MpegImagePlugin", 

377 ".mpo": "MpoImagePlugin", 

378 ".msp": "MspImagePlugin", 

379 ".palm": "PalmImagePlugin", 

380 ".pcd": "PcdImagePlugin", 

381 ".pcx": "PcxImagePlugin", 

382 ".pdf": "PdfImagePlugin", 

383 ".pxr": "PixarImagePlugin", 

384 ".psd": "PsdImagePlugin", 

385 ".qoi": "QoiImagePlugin", 

386 ".bw": "SgiImagePlugin", 

387 ".rgb": "SgiImagePlugin", 

388 ".rgba": "SgiImagePlugin", 

389 ".sgi": "SgiImagePlugin", 

390 ".ras": "SunImagePlugin", 

391 ".tga": "TgaImagePlugin", 

392 ".icb": "TgaImagePlugin", 

393 ".vda": "TgaImagePlugin", 

394 ".vst": "TgaImagePlugin", 

395 ".tif": "TiffImagePlugin", 

396 ".tiff": "TiffImagePlugin", 

397 ".webp": "WebPImagePlugin", 

398 ".wmf": "WmfImagePlugin", 

399 ".emf": "WmfImagePlugin", 

400 ".xbm": "XbmImagePlugin", 

401 ".xpm": "XpmImagePlugin", 

402} 

403 

404 

405def _import_plugin_for_extension(ext: str | bytes) -> bool: 

406 """Import only the plugin needed for a specific file extension.""" 

407 if not ext: 

408 return False 

409 

410 if isinstance(ext, bytes): 

411 ext = ext.decode() 

412 ext = ext.lower() 

413 if ext in EXTENSION: 

414 return True 

415 

416 plugin = _EXTENSION_PLUGIN.get(ext) 

417 if plugin is None: 

418 return False 

419 

420 try: 

421 logger.debug("Importing %s", plugin) 

422 __import__(f"{__spec__.parent}.{plugin}", globals(), locals(), []) 

423 return True 

424 except ImportError as e: 

425 logger.debug("Image: failed to import %s: %s", plugin, e) 

426 return False 

427 

428 

429def preinit() -> None: 

430 """ 

431 Explicitly loads BMP, GIF, JPEG, PPM and PNG file format drivers. 

432 

433 It is called when opening or saving images. 

434 """ 

435 

436 global _initialized 

437 if _initialized >= 1: 

438 return 

439 

440 try: 

441 from . import BmpImagePlugin 

442 

443 assert BmpImagePlugin 

444 except ImportError: 

445 pass 

446 try: 

447 from . import GifImagePlugin 

448 

449 assert GifImagePlugin 

450 except ImportError: 

451 pass 

452 try: 

453 from . import JpegImagePlugin 

454 

455 assert JpegImagePlugin 

456 except ImportError: 

457 pass 

458 try: 

459 from . import PpmImagePlugin 

460 

461 assert PpmImagePlugin 

462 except ImportError: 

463 pass 

464 try: 

465 from . import PngImagePlugin 

466 

467 assert PngImagePlugin 

468 except ImportError: 

469 pass 

470 

471 _initialized = 1 

472 

473 

474def init() -> bool: 

475 """ 

476 Explicitly initializes the Python Imaging Library. This function 

477 loads all available file format drivers. 

478 

479 It is called when opening or saving images if :py:meth:`~preinit()` is 

480 insufficient, and by :py:meth:`~PIL.features.pilinfo`. 

481 """ 

482 

483 global _initialized 

484 if _initialized >= 2: 

485 return False 

486 

487 for plugin in _plugins: 

488 try: 

489 logger.debug("Importing %s", plugin) 

490 __import__(f"{__spec__.parent}.{plugin}", globals(), locals(), []) 

491 except ImportError as e: # noqa: PERF203 

492 logger.debug("Image: failed to import %s: %s", plugin, e) 

493 

494 if OPEN or SAVE: 

495 _initialized = 2 

496 return True 

497 return False 

498 

499 

500# -------------------------------------------------------------------- 

501# Codec factories (used by tobytes/frombytes and ImageFile.load) 

502 

503 

504def _getdecoder( 

505 mode: str, decoder_name: str, args: Any, extra: tuple[Any, ...] = () 

506) -> core.ImagingDecoder | ImageFile.PyDecoder: 

507 # tweak arguments 

508 if args is None: 

509 args = () 

510 elif not isinstance(args, tuple): 

511 args = (args,) 

512 

513 try: 

514 decoder = DECODERS[decoder_name] 

515 except KeyError: 

516 pass 

517 else: 

518 return decoder(mode, *args + extra) 

519 

520 try: 

521 # get decoder 

522 decoder = getattr(core, f"{decoder_name}_decoder") 

523 except AttributeError as e: 

524 msg = f"decoder {decoder_name} not available" 

525 raise OSError(msg) from e 

526 return decoder(mode, *args + extra) 

527 

528 

529def _getencoder( 

530 mode: str, encoder_name: str, args: Any, extra: tuple[Any, ...] = () 

531) -> core.ImagingEncoder | ImageFile.PyEncoder: 

532 # tweak arguments 

533 if args is None: 

534 args = () 

535 elif not isinstance(args, tuple): 

536 args = (args,) 

537 

538 try: 

539 encoder = ENCODERS[encoder_name] 

540 except KeyError: 

541 pass 

542 else: 

543 return encoder(mode, *args + extra) 

544 

545 try: 

546 # get encoder 

547 encoder = getattr(core, f"{encoder_name}_encoder") 

548 except AttributeError as e: 

549 msg = f"encoder {encoder_name} not available" 

550 raise OSError(msg) from e 

551 return encoder(mode, *args + extra) 

552 

553 

554# -------------------------------------------------------------------- 

555# Simple expression analyzer 

556 

557 

558class ImagePointTransform: 

559 """ 

560 Used with :py:meth:`~PIL.Image.Image.point` for single band images with more than 

561 8 bits, this represents an affine transformation, where the value is multiplied by 

562 ``scale`` and ``offset`` is added. 

563 """ 

564 

565 def __init__(self, scale: float, offset: float) -> None: 

566 self.scale = scale 

567 self.offset = offset 

568 

569 def __neg__(self) -> ImagePointTransform: 

570 return ImagePointTransform(-self.scale, -self.offset) 

571 

572 def __add__(self, other: ImagePointTransform | float) -> ImagePointTransform: 

573 if isinstance(other, ImagePointTransform): 

574 return ImagePointTransform( 

575 self.scale + other.scale, self.offset + other.offset 

576 ) 

577 return ImagePointTransform(self.scale, self.offset + other) 

578 

579 __radd__ = __add__ 

580 

581 def __sub__(self, other: ImagePointTransform | float) -> ImagePointTransform: 

582 return self + -other 

583 

584 def __rsub__(self, other: ImagePointTransform | float) -> ImagePointTransform: 

585 return other + -self 

586 

587 def __mul__(self, other: ImagePointTransform | float) -> ImagePointTransform: 

588 if isinstance(other, ImagePointTransform): 

589 return NotImplemented 

590 return ImagePointTransform(self.scale * other, self.offset * other) 

591 

592 __rmul__ = __mul__ 

593 

594 def __truediv__(self, other: ImagePointTransform | float) -> ImagePointTransform: 

595 if isinstance(other, ImagePointTransform): 

596 return NotImplemented 

597 return ImagePointTransform(self.scale / other, self.offset / other) 

598 

599 

600def _getscaleoffset( 

601 expr: Callable[[ImagePointTransform], ImagePointTransform | float], 

602) -> tuple[float, float]: 

603 a = expr(ImagePointTransform(1, 0)) 

604 return (a.scale, a.offset) if isinstance(a, ImagePointTransform) else (0, a) 

605 

606 

607# -------------------------------------------------------------------- 

608# Implementation wrapper 

609 

610 

611class SupportsGetData(Protocol): 

612 def getdata( 

613 self, 

614 ) -> tuple[Transform, Sequence[int]]: ... 

615 

616 

617class Image: 

618 """ 

619 This class represents an image object. To create 

620 :py:class:`~PIL.Image.Image` objects, use the appropriate factory 

621 functions. There's hardly ever any reason to call the Image constructor 

622 directly. 

623 

624 * :py:func:`~PIL.Image.open` 

625 * :py:func:`~PIL.Image.new` 

626 * :py:func:`~PIL.Image.frombytes` 

627 """ 

628 

629 format: str | None = None 

630 format_description: str | None = None 

631 _close_exclusive_fp_after_loading = True 

632 

633 def __init__(self) -> None: 

634 # FIXME: take "new" parameters / other image? 

635 self._im: core.ImagingCore | DeferredError | None = None 

636 self._mode = "" 

637 self._size = (0, 0) 

638 self.palette: ImagePalette.ImagePalette | None = None 

639 self.info: dict[str | tuple[int, int], Any] = {} 

640 self.readonly = 0 

641 self._exif: Exif | None = None 

642 

643 @property 

644 def im(self) -> core.ImagingCore: 

645 if isinstance(self._im, DeferredError): 

646 raise self._im.ex 

647 assert self._im is not None 

648 return self._im 

649 

650 @im.setter 

651 def im(self, im: core.ImagingCore) -> None: 

652 self._im = im 

653 

654 @property 

655 def width(self) -> int: 

656 return self.size[0] 

657 

658 @property 

659 def height(self) -> int: 

660 return self.size[1] 

661 

662 @property 

663 def size(self) -> tuple[int, int]: 

664 return self._size 

665 

666 @property 

667 def mode(self) -> str: 

668 return self._mode 

669 

670 @property 

671 def readonly(self) -> int: 

672 return (self._im and self._im.readonly) or self._readonly 

673 

674 @readonly.setter 

675 def readonly(self, readonly: int) -> None: 

676 self._readonly = readonly 

677 

678 def _new(self, im: core.ImagingCore) -> Image: 

679 new = Image() 

680 new.im = im 

681 new._mode = im.mode 

682 new._size = im.size 

683 if im.mode in ("P", "PA"): 

684 if self.palette: 

685 new.palette = self.palette.copy() 

686 else: 

687 from . import ImagePalette 

688 

689 new.palette = ImagePalette.ImagePalette() 

690 new.info = self.info.copy() 

691 return new 

692 

693 # Context manager support 

694 def __enter__(self) -> Image: 

695 return self 

696 

697 def __exit__(self, *args: object) -> None: 

698 pass 

699 

700 def close(self) -> None: 

701 """ 

702 This operation will destroy the image core and release its memory. 

703 The image data will be unusable afterward. 

704 

705 This function is required to close images that have multiple frames or 

706 have not had their file read and closed by the 

707 :py:meth:`~PIL.Image.Image.load` method. See :ref:`file-handling` for 

708 more information. 

709 """ 

710 if getattr(self, "map", None): 

711 if sys.platform == "win32" and hasattr(sys, "pypy_version_info"): 

712 self.map.close() 

713 self.map: mmap.mmap | None = None 

714 

715 # Instead of simply setting to None, we're setting up a 

716 # deferred error that will better explain that the core image 

717 # object is gone. 

718 self._im = DeferredError(ValueError("Operation on closed image")) 

719 

720 def _copy(self) -> None: 

721 self.load() 

722 self.im = self.im.copy() 

723 self.readonly = 0 

724 

725 def _ensure_mutable(self) -> None: 

726 if self.readonly: 

727 self._copy() 

728 else: 

729 self.load() 

730 

731 def _dump( 

732 self, file: str | None = None, format: str | None = None, **options: Any 

733 ) -> str: 

734 suffix = f".{format}" if format else "" 

735 

736 if file: 

737 filename = file 

738 if not filename.endswith(suffix): 

739 filename += suffix 

740 else: 

741 f, filename = tempfile.mkstemp(suffix) 

742 os.close(f) 

743 

744 self.save(filename, format or "PPM", **options) 

745 

746 return filename 

747 

748 def __eq__(self, other: object) -> bool: 

749 if self.__class__ is not other.__class__: 

750 return False 

751 assert isinstance(other, Image) 

752 return ( 

753 self.mode == other.mode 

754 and self.size == other.size 

755 and self.info == other.info 

756 and self.getpalette() == other.getpalette() 

757 and self.tobytes() == other.tobytes() 

758 ) 

759 

760 def __repr__(self) -> str: 

761 return ( 

762 f"<{self.__class__.__module__}.{self.__class__.__name__} " 

763 f"image mode={self.mode} size={self.size[0]}x{self.size[1]} " 

764 f"at 0x{id(self):X}>" 

765 ) 

766 

767 def _repr_pretty_(self, p: PrettyPrinter, cycle: bool) -> None: 

768 """IPython plain text display support""" 

769 

770 # Same as __repr__ but without unpredictable id(self), 

771 # to keep Jupyter notebook `text/plain` output stable. 

772 p.text( 

773 f"<{self.__class__.__module__}.{self.__class__.__name__} " 

774 f"image mode={self.mode} size={self.size[0]}x{self.size[1]}>" 

775 ) 

776 

777 def _repr_image(self, image_format: str, **kwargs: Any) -> bytes | None: 

778 """Helper function for iPython display hook. 

779 

780 :param image_format: Image format. 

781 :returns: image as bytes, saved into the given format. 

782 """ 

783 b = io.BytesIO() 

784 try: 

785 self.save(b, image_format, **kwargs) 

786 except Exception: 

787 return None 

788 return b.getvalue() 

789 

790 def _repr_png_(self) -> bytes | None: 

791 """iPython display hook support for PNG format. 

792 

793 :returns: PNG version of the image as bytes 

794 """ 

795 return self._repr_image("PNG", compress_level=1) 

796 

797 def _repr_jpeg_(self) -> bytes | None: 

798 """iPython display hook support for JPEG format. 

799 

800 :returns: JPEG version of the image as bytes 

801 """ 

802 return self._repr_image("JPEG") 

803 

804 @property 

805 def __array_interface__(self) -> dict[str, str | bytes | int | tuple[int, ...]]: 

806 # numpy array interface support 

807 new: dict[str, str | bytes | int | tuple[int, ...]] = {"version": 3} 

808 if self.mode == "1": 

809 # Binary images need to be extended from bits to bytes 

810 # See: https://github.com/python-pillow/Pillow/issues/350 

811 new["data"] = self.tobytes("raw", "L") 

812 else: 

813 new["data"] = self.tobytes() 

814 new["shape"], new["typestr"] = _conv_type_shape(self) 

815 return new 

816 

817 def __arrow_c_schema__(self) -> object: 

818 self.load() 

819 return self.im.__arrow_c_schema__() 

820 

821 def __arrow_c_array__( 

822 self, requested_schema: object | None = None 

823 ) -> tuple[object, object]: 

824 self.load() 

825 return (self.im.__arrow_c_schema__(), self.im.__arrow_c_array__()) 

826 

827 def __getstate__(self) -> list[Any]: 

828 im_data = self.tobytes() # load image first 

829 return [self.info, self.mode, self.size, self.getpalette(), im_data] 

830 

831 def __setstate__(self, state: list[Any]) -> None: 

832 Image.__init__(self) 

833 info, mode, size, palette, data = state[:5] 

834 self.info = info 

835 self._mode = mode 

836 self._size = size 

837 self.im = core.new(mode, size) 

838 if mode in ("L", "LA", "P", "PA") and palette: 

839 self.putpalette(palette) 

840 self.frombytes(data) 

841 

842 def tobytes(self, encoder_name: str = "raw", *args: Any) -> bytes: 

843 """ 

844 Return image as a bytes object. 

845 

846 .. warning:: 

847 

848 This method returns raw image data derived from Pillow's internal 

849 storage. For compressed image data (e.g. PNG, JPEG) use 

850 :meth:`~.save`, with a BytesIO parameter for in-memory data. 

851 

852 :param encoder_name: What encoder to use. 

853 

854 The default is to use the standard "raw" encoder. 

855 To see how this packs pixel data into the returned 

856 bytes, see :file:`libImaging/Pack.c`. 

857 

858 A list of C encoders can be seen under codecs 

859 section of the function array in 

860 :file:`_imaging.c`. Python encoders are registered 

861 within the relevant plugins. 

862 :param args: Extra arguments to the encoder. 

863 :returns: A :py:class:`bytes` object. 

864 """ 

865 

866 encoder_args: Any = args 

867 if len(encoder_args) == 1 and isinstance(encoder_args[0], tuple): 

868 # may pass tuple instead of argument list 

869 encoder_args = encoder_args[0] 

870 

871 if encoder_name == "raw" and encoder_args == (): 

872 encoder_args = self.mode 

873 

874 self.load() 

875 

876 if self.width == 0 or self.height == 0: 

877 return b"" 

878 

879 # unpack data 

880 e = _getencoder(self.mode, encoder_name, encoder_args) 

881 e.setimage(self.im, (0, 0) + self.size) 

882 

883 from . import ImageFile 

884 

885 bufsize = max(ImageFile.MAXBLOCK, self.size[0] * 4) # see RawEncode.c 

886 

887 output = [] 

888 while True: 

889 bytes_consumed, errcode, data = e.encode(bufsize) 

890 output.append(data) 

891 if errcode: 

892 break 

893 if errcode < 0: 

894 msg = f"encoder error {errcode} in tobytes" 

895 raise RuntimeError(msg) 

896 

897 return b"".join(output) 

898 

899 def tobitmap(self, name: str = "image") -> bytes: 

900 """ 

901 Returns the image converted to an X11 bitmap. 

902 

903 .. note:: This method only works for mode "1" images. 

904 

905 :param name: The name prefix to use for the bitmap variables. 

906 :returns: A string containing an X11 bitmap. 

907 :raises ValueError: If the mode is not "1" 

908 """ 

909 

910 self.load() 

911 if self.mode != "1": 

912 msg = "not a bitmap" 

913 raise ValueError(msg) 

914 data = self.tobytes("xbm") 

915 return b"".join( 

916 [ 

917 f"#define {name}_width {self.size[0]}\n".encode("ascii"), 

918 f"#define {name}_height {self.size[1]}\n".encode("ascii"), 

919 f"static char {name}_bits[] = {{\n".encode("ascii"), 

920 data, 

921 b"};", 

922 ] 

923 ) 

924 

925 def frombytes( 

926 self, 

927 data: bytes | bytearray | SupportsArrayInterface, 

928 decoder_name: str = "raw", 

929 *args: Any, 

930 ) -> None: 

931 """ 

932 Loads this image with pixel data from a bytes object. 

933 

934 This method is similar to the :py:func:`~PIL.Image.frombytes` function, 

935 but loads data into this image instead of creating a new image object. 

936 """ 

937 

938 if self.width == 0 or self.height == 0: 

939 return 

940 

941 decoder_args: Any = args 

942 if len(decoder_args) == 1 and isinstance(decoder_args[0], tuple): 

943 # may pass tuple instead of argument list 

944 decoder_args = decoder_args[0] 

945 

946 # default format 

947 if decoder_name == "raw" and decoder_args == (): 

948 decoder_args = self.mode 

949 

950 # unpack data 

951 d = _getdecoder(self.mode, decoder_name, decoder_args) 

952 d.setimage(self.im, (0, 0) + self.size) 

953 s = d.decode(data) 

954 

955 if s[0] >= 0: 

956 msg = "not enough image data" 

957 raise ValueError(msg) 

958 if s[1] != 0: 

959 msg = "cannot decode image data" 

960 raise ValueError(msg) 

961 

962 def load(self) -> core.PixelAccess | None: 

963 """ 

964 Allocates storage for the image and loads the pixel data. In 

965 normal cases, you don't need to call this method, since the 

966 Image class automatically loads an opened image when it is 

967 accessed for the first time. 

968 

969 If the file associated with the image was opened by Pillow, then this 

970 method will close it. The exception to this is if the image has 

971 multiple frames, in which case the file will be left open for seek 

972 operations. See :ref:`file-handling` for more information. 

973 

974 :returns: An image access object. 

975 :rtype: :py:class:`.PixelAccess` 

976 """ 

977 if self._im is not None and self.palette and self.palette.dirty: 

978 # realize palette 

979 mode, arr = self.palette.getdata() 

980 self.im.putpalette(self.palette.mode, mode, arr) 

981 self.palette.dirty = 0 

982 self.palette.rawmode = None 

983 if "transparency" in self.info and mode in ("LA", "PA"): 

984 if isinstance(self.info["transparency"], int): 

985 self.im.putpalettealpha(self.info["transparency"], 0) 

986 else: 

987 self.im.putpalettealphas(self.info["transparency"]) 

988 self.palette.mode = "RGBA" 

989 elif self.palette.mode != mode: 

990 # If the palette rawmode is different to the mode, 

991 # then update the Python palette data 

992 self.palette.palette = self.im.getpalette( 

993 self.palette.mode, self.palette.mode 

994 ) 

995 

996 if self._im is not None: 

997 return self.im.pixel_access(self.readonly) 

998 return None 

999 

1000 def verify(self) -> None: 

1001 """ 

1002 Verifies the contents of a file. For data read from a file, this 

1003 method attempts to determine if the file is broken, without 

1004 actually decoding the image data. If this method finds any 

1005 problems, it raises suitable exceptions. If you need to load 

1006 the image after using this method, you must reopen the image 

1007 file. 

1008 """ 

1009 pass 

1010 

1011 def convert( 

1012 self, 

1013 mode: str | None = None, 

1014 matrix: tuple[float, ...] | None = None, 

1015 dither: Dither | None = None, 

1016 palette: Palette = Palette.WEB, 

1017 colors: int = 256, 

1018 ) -> Image: 

1019 """ 

1020 Returns a converted copy of this image. For the "P" mode, this 

1021 method translates pixels through the palette. If mode is 

1022 omitted, a mode is chosen so that all information in the image 

1023 and the palette can be represented without a palette. 

1024 

1025 This supports all possible conversions between "L", "RGB" and "CMYK". The 

1026 ``matrix`` argument only supports "L" and "RGB". 

1027 

1028 When translating a color image to grayscale (mode "L"), 

1029 the library uses the ITU-R 601-2 luma transform:: 

1030 

1031 L = R * 299/1000 + G * 587/1000 + B * 114/1000 

1032 

1033 The default method of converting a grayscale ("L") or "RGB" 

1034 image into a bilevel (mode "1") image uses Floyd-Steinberg 

1035 dither to approximate the original image luminosity levels. If 

1036 dither is ``None``, all values larger than 127 are set to 255 (white), 

1037 all other values to 0 (black). To use other thresholds, use the 

1038 :py:meth:`~PIL.Image.Image.point` method. 

1039 

1040 When converting from "RGBA" to "P" without a ``matrix`` argument, 

1041 this passes the operation to :py:meth:`~PIL.Image.Image.quantize`, 

1042 and ``dither`` and ``palette`` are ignored. 

1043 

1044 When converting from "PA", if an "RGBA" palette is present, the alpha 

1045 channel from the image will be used instead of the values from the palette. 

1046 

1047 :param mode: The requested mode. See: :ref:`concept-modes`. 

1048 :param matrix: An optional conversion matrix. If given, this 

1049 should be 4- or 12-tuple containing floating point values. 

1050 :param dither: Dithering method, used when converting from 

1051 mode "RGB" to "P" or from "RGB" or "L" to "1". 

1052 Available methods are :data:`Dither.NONE` or :data:`Dither.FLOYDSTEINBERG` 

1053 (default). Note that this is not used when ``matrix`` is supplied. 

1054 :param palette: Palette to use when converting from mode "RGB" 

1055 to "P". Available palettes are :data:`Palette.WEB` or 

1056 :data:`Palette.ADAPTIVE`. 

1057 :param colors: Number of colors to use for the :data:`Palette.ADAPTIVE` 

1058 palette. Defaults to 256. 

1059 :rtype: :py:class:`~PIL.Image.Image` 

1060 :returns: An :py:class:`~PIL.Image.Image` object. 

1061 """ 

1062 

1063 self.load() 

1064 

1065 has_transparency = "transparency" in self.info 

1066 if not mode and self.mode == "P": 

1067 # determine default mode 

1068 if self.palette: 

1069 mode = self.palette.mode 

1070 else: 

1071 mode = "RGB" 

1072 if mode == "RGB" and has_transparency: 

1073 mode = "RGBA" 

1074 if not mode or (mode == self.mode and not matrix): 

1075 return self.copy() 

1076 

1077 if matrix: 

1078 # matrix conversion 

1079 if mode not in ("L", "RGB"): 

1080 msg = "illegal conversion" 

1081 raise ValueError(msg) 

1082 im = self.im.convert_matrix(mode, matrix) 

1083 new_im = self._new(im) 

1084 if has_transparency and self.im.bands == 3: 

1085 transparency = new_im.info["transparency"] 

1086 

1087 def convert_transparency( 

1088 m: tuple[float, ...], v: tuple[int, int, int] 

1089 ) -> int: 

1090 value = m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3] * 0.5 

1091 return max(0, min(255, int(value))) 

1092 

1093 if mode == "L": 

1094 transparency = convert_transparency(matrix, transparency) 

1095 elif len(mode) == 3: 

1096 transparency = tuple( 

1097 convert_transparency(matrix[i * 4 : i * 4 + 4], transparency) 

1098 for i in range(len(transparency)) 

1099 ) 

1100 new_im.info["transparency"] = transparency 

1101 return new_im 

1102 

1103 if self.mode == "RGBA": 

1104 if mode == "P": 

1105 return self.quantize(colors) 

1106 elif mode == "PA": 

1107 r, g, b, a = self.split() 

1108 rgb = merge("RGB", (r, g, b)) 

1109 p = rgb.quantize(colors) 

1110 return merge("PA", (p, a)) 

1111 

1112 trns = None 

1113 delete_trns = False 

1114 # transparency handling 

1115 if has_transparency: 

1116 if (self.mode in ("1", "L", "I", "I;16") and mode in ("LA", "RGBA")) or ( 

1117 self.mode == "RGB" and mode in ("La", "LA", "RGBa", "RGBA") 

1118 ): 

1119 # Use transparent conversion to promote from transparent 

1120 # color to an alpha channel. 

1121 new_im = self._new( 

1122 self.im.convert_transparent(mode, self.info["transparency"]) 

1123 ) 

1124 del new_im.info["transparency"] 

1125 return new_im 

1126 elif self.mode in ("L", "RGB", "P") and mode in ("L", "RGB", "P"): 

1127 t = self.info["transparency"] 

1128 if isinstance(t, bytes): 

1129 # Dragons. This can't be represented by a single color 

1130 warnings.warn( 

1131 "Palette images with Transparency expressed in bytes should be " 

1132 "converted to RGBA images" 

1133 ) 

1134 delete_trns = True 

1135 else: 

1136 # get the new transparency color. 

1137 # use existing conversions 

1138 trns_im = new(self.mode, (1, 1)) 

1139 if self.mode == "P": 

1140 assert self.palette is not None 

1141 trns_im.putpalette(self.palette, self.palette.mode) 

1142 if isinstance(t, tuple): 

1143 err = "Couldn't allocate a palette color for transparency" 

1144 assert trns_im.palette is not None 

1145 try: 

1146 t = trns_im.palette.getcolor(t, self) 

1147 except ValueError as e: 

1148 if str(e) == "cannot allocate more than 256 colors": 

1149 # If all 256 colors are in use, 

1150 # then there is no need for transparency 

1151 t = None 

1152 else: 

1153 raise ValueError(err) from e 

1154 if t is None: 

1155 trns = None 

1156 else: 

1157 trns_im.putpixel((0, 0), t) 

1158 

1159 if mode in ("L", "RGB"): 

1160 trns_im = trns_im.convert(mode) 

1161 else: 

1162 # can't just retrieve the palette number, got to do it 

1163 # after quantization. 

1164 trns_im = trns_im.convert("RGB") 

1165 trns = trns_im.getpixel((0, 0)) 

1166 

1167 elif self.mode == "P" and mode in ("LA", "PA", "RGBA"): 

1168 t = self.info["transparency"] 

1169 delete_trns = True 

1170 

1171 if isinstance(t, bytes): 

1172 self.im.putpalettealphas(t) 

1173 elif isinstance(t, int): 

1174 self.im.putpalettealpha(t, 0) 

1175 else: 

1176 msg = "Transparency for P mode should be bytes or int" 

1177 raise ValueError(msg) 

1178 

1179 if mode == "P" and palette == Palette.ADAPTIVE: 

1180 im = self.im.quantize(colors) 

1181 new_im = self._new(im) 

1182 from . import ImagePalette 

1183 

1184 new_im.palette = ImagePalette.ImagePalette( 

1185 "RGB", new_im.im.getpalette("RGB") 

1186 ) 

1187 if delete_trns: 

1188 # This could possibly happen if we requantize to fewer colors. 

1189 # The transparency would be totally off in that case. 

1190 del new_im.info["transparency"] 

1191 if trns is not None: 

1192 try: 

1193 new_im.info["transparency"] = new_im.palette.getcolor( 

1194 cast(tuple[int, ...], trns), # trns was converted to RGB 

1195 new_im, 

1196 ) 

1197 except Exception: 

1198 # if we can't make a transparent color, don't leave the old 

1199 # transparency hanging around to mess us up. 

1200 del new_im.info["transparency"] 

1201 warnings.warn("Couldn't allocate palette entry for transparency") 

1202 return new_im 

1203 

1204 if "LAB" in (self.mode, mode): 

1205 im = self 

1206 if mode == "LAB": 

1207 if im.mode not in ("RGB", "RGBA", "RGBX"): 

1208 im = im.convert("RGBA") 

1209 other_mode = im.mode 

1210 else: 

1211 other_mode = mode 

1212 if other_mode in ("RGB", "RGBA", "RGBX"): 

1213 from . import ImageCms 

1214 

1215 srgb = ImageCms.createProfile("sRGB") 

1216 lab = ImageCms.createProfile("LAB") 

1217 profiles = [lab, srgb] if im.mode == "LAB" else [srgb, lab] 

1218 transform = ImageCms.buildTransform( 

1219 profiles[0], profiles[1], im.mode, mode 

1220 ) 

1221 return transform.apply(im) 

1222 

1223 # colorspace conversion 

1224 if dither is None: 

1225 dither = Dither.FLOYDSTEINBERG 

1226 

1227 try: 

1228 im = self.im.convert(mode, dither) 

1229 except ValueError: 

1230 try: 

1231 # normalize source image and try again 

1232 modebase = getmodebase(self.mode) 

1233 if modebase == self.mode: 

1234 raise 

1235 im = self.im.convert(modebase) 

1236 im = im.convert(mode, dither) 

1237 except KeyError as e: 

1238 msg = "illegal conversion" 

1239 raise ValueError(msg) from e 

1240 

1241 new_im = self._new(im) 

1242 if mode in ("P", "PA") and palette != Palette.ADAPTIVE: 

1243 from . import ImagePalette 

1244 

1245 new_im.palette = ImagePalette.ImagePalette("RGB", im.getpalette("RGB")) 

1246 if delete_trns: 

1247 # crash fail if we leave a bytes transparency in an rgb/l mode. 

1248 del new_im.info["transparency"] 

1249 if trns is not None: 

1250 if new_im.mode == "P" and new_im.palette: 

1251 try: 

1252 new_im.info["transparency"] = new_im.palette.getcolor( 

1253 cast(tuple[int, ...], trns), new_im # trns was converted to RGB 

1254 ) 

1255 except ValueError as e: 

1256 del new_im.info["transparency"] 

1257 if str(e) != "cannot allocate more than 256 colors": 

1258 # If all 256 colors are in use, 

1259 # then there is no need for transparency 

1260 warnings.warn( 

1261 "Couldn't allocate palette entry for transparency" 

1262 ) 

1263 else: 

1264 new_im.info["transparency"] = trns 

1265 return new_im 

1266 

1267 def quantize( 

1268 self, 

1269 colors: int = 256, 

1270 method: int | None = None, 

1271 kmeans: int = 0, 

1272 palette: Image | None = None, 

1273 dither: Dither = Dither.FLOYDSTEINBERG, 

1274 ) -> Image: 

1275 """ 

1276 Convert the image to 'P' mode with the specified number 

1277 of colors. 

1278 

1279 :param colors: The desired number of colors, <= 256 

1280 :param method: :data:`Quantize.MEDIANCUT` (median cut), 

1281 :data:`Quantize.MAXCOVERAGE` (maximum coverage), 

1282 :data:`Quantize.FASTOCTREE` (fast octree), 

1283 :data:`Quantize.LIBIMAGEQUANT` (libimagequant; check support 

1284 using :py:func:`PIL.features.check_feature` with 

1285 ``feature="libimagequant"``). 

1286 

1287 By default, :data:`Quantize.MEDIANCUT` will be used. 

1288 

1289 The exception to this is RGBA images. :data:`Quantize.MEDIANCUT` 

1290 and :data:`Quantize.MAXCOVERAGE` do not support RGBA images, so 

1291 :data:`Quantize.FASTOCTREE` is used by default instead. 

1292 :param kmeans: Integer greater than or equal to zero. 

1293 :param palette: Quantize to the palette of given 

1294 :py:class:`PIL.Image.Image`. 

1295 :param dither: Dithering method, used when converting from 

1296 mode "RGB" to "P" or from "RGB" or "L" to "1". 

1297 Available methods are :data:`Dither.NONE` or :data:`Dither.FLOYDSTEINBERG` 

1298 (default). 

1299 :returns: A new image 

1300 """ 

1301 

1302 self.load() 

1303 

1304 if method is None: 

1305 # defaults: 

1306 method = Quantize.MEDIANCUT 

1307 if self.mode == "RGBA": 

1308 method = Quantize.FASTOCTREE 

1309 

1310 if self.mode == "RGBA" and method not in ( 

1311 Quantize.FASTOCTREE, 

1312 Quantize.LIBIMAGEQUANT, 

1313 ): 

1314 # Caller specified an invalid mode. 

1315 msg = ( 

1316 "Fast Octree (method == 2) and libimagequant (method == 3) " 

1317 "are the only valid methods for quantizing RGBA images" 

1318 ) 

1319 raise ValueError(msg) 

1320 

1321 if palette: 

1322 # use palette from reference image 

1323 palette.load() 

1324 if palette.mode != "P": 

1325 msg = "bad mode for palette image" 

1326 raise ValueError(msg) 

1327 if self.mode not in {"RGB", "L"}: 

1328 msg = "only RGB or L mode images can be quantized to a palette" 

1329 raise ValueError(msg) 

1330 im = self.im.convert("P", dither, palette.im) 

1331 new_im = self._new(im) 

1332 assert palette.palette is not None 

1333 new_im.palette = palette.palette.copy() 

1334 return new_im 

1335 

1336 if kmeans < 0: 

1337 msg = "kmeans must not be negative" 

1338 raise ValueError(msg) 

1339 

1340 im = self._new(self.im.quantize(colors, method, kmeans)) 

1341 

1342 from . import ImagePalette 

1343 

1344 mode = im.im.getpalettemode() 

1345 palette_data = im.im.getpalette(mode, mode)[: colors * len(mode)] 

1346 im.palette = ImagePalette.ImagePalette(mode, palette_data) 

1347 

1348 return im 

1349 

1350 def copy(self) -> Image: 

1351 """ 

1352 Copies this image. Use this method if you wish to paste things 

1353 into an image, but still retain the original. 

1354 

1355 :rtype: :py:class:`~PIL.Image.Image` 

1356 :returns: An :py:class:`~PIL.Image.Image` object. 

1357 """ 

1358 self.load() 

1359 return self._new(self.im.copy()) 

1360 

1361 __copy__ = copy 

1362 

1363 def crop(self, box: tuple[float, float, float, float] | None = None) -> Image: 

1364 """ 

1365 Returns a rectangular region from this image. The box is a 

1366 4-tuple defining the left, upper, right, and lower pixel 

1367 coordinate. See :ref:`coordinate-system`. 

1368 

1369 Note: Prior to Pillow 3.4.0, this was a lazy operation. 

1370 

1371 :param box: The crop rectangle, as a (left, upper, right, lower)-tuple. 

1372 :rtype: :py:class:`~PIL.Image.Image` 

1373 :returns: An :py:class:`~PIL.Image.Image` object. 

1374 """ 

1375 

1376 if box is None: 

1377 return self.copy() 

1378 

1379 if box[2] < box[0]: 

1380 msg = "Coordinate 'right' is less than 'left'" 

1381 raise ValueError(msg) 

1382 elif box[3] < box[1]: 

1383 msg = "Coordinate 'lower' is less than 'upper'" 

1384 raise ValueError(msg) 

1385 

1386 self.load() 

1387 return self._new(self._crop(self.im, box)) 

1388 

1389 def _crop( 

1390 self, im: core.ImagingCore, box: tuple[float, float, float, float] 

1391 ) -> core.ImagingCore: 

1392 """ 

1393 Returns a rectangular region from the core image object im. 

1394 

1395 This is equivalent to calling im.crop((x0, y0, x1, y1)), but 

1396 includes additional sanity checks. 

1397 

1398 :param im: a core image object 

1399 :param box: The crop rectangle, as a (left, upper, right, lower)-tuple. 

1400 :returns: A core image object. 

1401 """ 

1402 

1403 x0, y0, x1, y1 = map(int, map(round, box)) 

1404 

1405 absolute_values = (abs(x1 - x0), abs(y1 - y0)) 

1406 

1407 _decompression_bomb_check(absolute_values) 

1408 

1409 return im.crop((x0, y0, x1, y1)) 

1410 

1411 def draft( 

1412 self, mode: str | None, size: tuple[int, int] | None 

1413 ) -> tuple[str, tuple[int, int, float, float]] | None: 

1414 """ 

1415 Configures the image file loader so it returns a version of the 

1416 image that as closely as possible matches the given mode and 

1417 size. For example, you can use this method to convert a color 

1418 JPEG to grayscale while loading it. 

1419 

1420 If any changes are made, returns a tuple with the chosen ``mode`` and 

1421 ``box`` with coordinates of the original image within the altered one. 

1422 

1423 Note that this method modifies the :py:class:`~PIL.Image.Image` object 

1424 in place. If the image has already been loaded, this method has no 

1425 effect. 

1426 

1427 Note: This method is not implemented for most images. It is 

1428 currently implemented only for JPEG and MPO images. 

1429 

1430 :param mode: The requested mode. 

1431 :param size: The requested size in pixels, as a 2-tuple: 

1432 (width, height). 

1433 """ 

1434 pass 

1435 

1436 def filter(self, filter: ImageFilter.Filter | type[ImageFilter.Filter]) -> Image: 

1437 """ 

1438 Filters this image using the given filter. For a list of 

1439 available filters, see the :py:mod:`~PIL.ImageFilter` module. 

1440 

1441 :param filter: Filter kernel. 

1442 :returns: An :py:class:`~PIL.Image.Image` object.""" 

1443 

1444 from . import ImageFilter 

1445 

1446 self.load() 

1447 

1448 if callable(filter): 

1449 filter = filter() 

1450 if not hasattr(filter, "filter"): 

1451 msg = "filter argument should be ImageFilter.Filter instance or class" 

1452 raise TypeError(msg) 

1453 

1454 multiband = isinstance(filter, ImageFilter.MultibandFilter) 

1455 if self.im.bands == 1 or multiband: 

1456 return self._new(filter.filter(self.im)) 

1457 

1458 ims = [ 

1459 self._new(filter.filter(self.im.getband(c))) for c in range(self.im.bands) 

1460 ] 

1461 return merge(self.mode, ims) 

1462 

1463 def getbands(self) -> tuple[str, ...]: 

1464 """ 

1465 Returns a tuple containing the name of each band in this image. 

1466 For example, ``getbands`` on an RGB image returns ("R", "G", "B"). 

1467 

1468 :returns: A tuple containing band names. 

1469 :rtype: tuple 

1470 """ 

1471 return ImageMode.getmode(self.mode).bands 

1472 

1473 def getbbox(self, *, alpha_only: bool = True) -> tuple[int, int, int, int] | None: 

1474 """ 

1475 Calculates the bounding box of the non-zero regions in the 

1476 image. 

1477 

1478 :param alpha_only: Optional flag, defaulting to ``True``. 

1479 If ``True`` and the image has an alpha channel, trim transparent pixels. 

1480 Otherwise, trim pixels when all channels are zero. 

1481 Keyword-only argument. 

1482 :returns: The bounding box is returned as a 4-tuple defining the 

1483 left, upper, right, and lower pixel coordinate. See 

1484 :ref:`coordinate-system`. If the image is completely empty, this 

1485 method returns None. 

1486 

1487 """ 

1488 

1489 self.load() 

1490 return self.im.getbbox(alpha_only) 

1491 

1492 def getcolors( 

1493 self, maxcolors: int = 256 

1494 ) -> list[tuple[int, tuple[int, ...]]] | list[tuple[int, float]] | None: 

1495 """ 

1496 Returns a list of colors used in this image. 

1497 

1498 The colors will be in the image's mode. For example, an RGB image will 

1499 return a tuple of (red, green, blue) color values, and a P image will 

1500 return the index of the color in the palette. 

1501 

1502 :param maxcolors: Maximum number of colors. If this number is 

1503 exceeded, this method returns None. The default limit is 

1504 256 colors. 

1505 :returns: An unsorted list of (count, pixel) values. 

1506 """ 

1507 

1508 self.load() 

1509 if self.mode in ("1", "L", "P"): 

1510 h = self.im.histogram() 

1511 out: list[tuple[int, float]] = [(h[i], i) for i in range(256) if h[i]] 

1512 if len(out) > maxcolors: 

1513 return None 

1514 return out 

1515 return self.im.getcolors(maxcolors) 

1516 

1517 def getdata(self, band: int | None = None) -> core.ImagingCore: 

1518 """ 

1519 Returns the contents of this image as a sequence object 

1520 containing pixel values. The sequence object is flattened, so 

1521 that values for line one follow directly after the values of 

1522 line zero, and so on. 

1523 

1524 Note that the sequence object returned by this method is an 

1525 internal PIL data type, which only supports certain sequence 

1526 operations. To convert it to an ordinary sequence (e.g. for 

1527 printing), use ``list(im.getdata())``. 

1528 

1529 :param band: What band to return. The default is to return 

1530 all bands. To return a single band, pass in the index 

1531 value (e.g. 0 to get the "R" band from an "RGB" image). 

1532 :returns: A sequence-like object. 

1533 """ 

1534 deprecate("Image.Image.getdata", 14, "get_flattened_data") 

1535 

1536 self.load() 

1537 if band is not None: 

1538 return self.im.getband(band) 

1539 return self.im # could be abused 

1540 

1541 def get_flattened_data( 

1542 self, band: int | None = None 

1543 ) -> tuple[tuple[int, ...], ...] | tuple[float, ...]: 

1544 """ 

1545 Returns the contents of this image as a tuple containing pixel values. 

1546 The sequence object is flattened, so that values for line one follow 

1547 directly after the values of line zero, and so on. 

1548 

1549 :param band: What band to return. The default is to return 

1550 all bands. To return a single band, pass in the index 

1551 value (e.g. 0 to get the "R" band from an "RGB" image). 

1552 :returns: A tuple containing pixel values. 

1553 """ 

1554 self.load() 

1555 if band is not None: 

1556 return tuple(self.im.getband(band)) 

1557 return tuple(self.im) 

1558 

1559 def getextrema(self) -> tuple[float, float] | tuple[tuple[int, int], ...]: 

1560 """ 

1561 Gets the minimum and maximum pixel values for each band in 

1562 the image. 

1563 

1564 :returns: For a single-band image, a 2-tuple containing the 

1565 minimum and maximum pixel value. For a multi-band image, 

1566 a tuple containing one 2-tuple for each band. 

1567 """ 

1568 

1569 self.load() 

1570 if self.im.bands > 1: 

1571 return tuple(self.im.getband(i).getextrema() for i in range(self.im.bands)) 

1572 return self.im.getextrema() 

1573 

1574 def getxmp(self) -> dict[str, Any]: 

1575 """ 

1576 Returns a dictionary containing the XMP tags. 

1577 Requires defusedxml to be installed. 

1578 

1579 :returns: XMP tags in a dictionary. 

1580 """ 

1581 

1582 def get_name(tag: str) -> str: 

1583 return re.sub("^{[^}]+}", "", tag) 

1584 

1585 def get_value(element: Element) -> str | dict[str, Any] | None: 

1586 value: dict[str, Any] = {get_name(k): v for k, v in element.attrib.items()} 

1587 children = list(element) 

1588 if children: 

1589 for child in children: 

1590 name = get_name(child.tag) 

1591 child_value = get_value(child) 

1592 if name in value: 

1593 if not isinstance(value[name], list): 

1594 value[name] = [value[name]] 

1595 value[name].append(child_value) 

1596 else: 

1597 value[name] = child_value 

1598 elif value: 

1599 if element.text: 

1600 value["text"] = element.text 

1601 else: 

1602 return element.text 

1603 return value 

1604 

1605 if ElementTree is None: 

1606 warnings.warn("XMP data cannot be read without defusedxml dependency") 

1607 return {} 

1608 if "xmp" not in self.info: 

1609 return {} 

1610 root = ElementTree.fromstring(self.info["xmp"].rstrip(b"\x00 ")) 

1611 return {get_name(root.tag): get_value(root)} 

1612 

1613 def getexif(self) -> Exif: 

1614 """ 

1615 Gets EXIF data from the image. 

1616 

1617 :returns: an :py:class:`~PIL.Image.Exif` object. 

1618 """ 

1619 if self._exif is None: 

1620 self._exif = Exif() 

1621 elif self._exif._loaded: 

1622 return self._exif 

1623 self._exif._loaded = True 

1624 

1625 exif_info = self.info.get("exif") 

1626 if exif_info is None: 

1627 if "Raw profile type exif" in self.info: 

1628 exif_info = bytes.fromhex( 

1629 "".join(self.info["Raw profile type exif"].split("\n")[3:]) 

1630 ) 

1631 elif hasattr(self, "tag_v2"): 

1632 from . import TiffImagePlugin 

1633 

1634 assert isinstance(self, TiffImagePlugin.TiffImageFile) 

1635 self._exif.bigtiff = self.tag_v2._bigtiff 

1636 self._exif.endian = self.tag_v2._endian 

1637 

1638 assert self.fp is not None 

1639 self._exif.load_from_fp(self.fp, self.tag_v2._offset) 

1640 if exif_info is not None: 

1641 self._exif.load(exif_info) 

1642 

1643 # XMP tags 

1644 if ExifTags.Base.Orientation not in self._exif: 

1645 xmp_tags = self.info.get("XML:com.adobe.xmp") 

1646 pattern: str | bytes = r'tiff:Orientation(="|>)([0-9])' 

1647 if not xmp_tags and (xmp_tags := self.info.get("xmp")): 

1648 pattern = rb'tiff:Orientation(="|>)([0-9])' 

1649 if xmp_tags: 

1650 match = re.search(pattern, xmp_tags) 

1651 if match: 

1652 self._exif[ExifTags.Base.Orientation] = int(match[2]) 

1653 

1654 return self._exif 

1655 

1656 def _reload_exif(self) -> None: 

1657 if self._exif is None or not self._exif._loaded: 

1658 return 

1659 self._exif._loaded = False 

1660 self.getexif() 

1661 

1662 def get_child_images(self) -> list[ImageFile.ImageFile]: 

1663 from . import ImageFile 

1664 

1665 deprecate("Image.Image.get_child_images", 13) 

1666 return ImageFile.ImageFile.get_child_images(self) # type: ignore[arg-type] 

1667 

1668 def getim(self) -> CapsuleType: 

1669 """ 

1670 Returns a capsule that points to the internal image memory. 

1671 

1672 :returns: A capsule object. 

1673 """ 

1674 

1675 self.load() 

1676 return self.im.ptr 

1677 

1678 def getpalette(self, rawmode: str | None = "RGB") -> list[int] | None: 

1679 """ 

1680 Returns the image palette as a list. 

1681 

1682 :param rawmode: The mode in which to return the palette. ``None`` will 

1683 return the palette in its current mode. 

1684 

1685 .. versionadded:: 9.1.0 

1686 

1687 :returns: A list of color values [r, g, b, ...], or None if the 

1688 image has no palette. 

1689 """ 

1690 

1691 self.load() 

1692 try: 

1693 mode = self.im.getpalettemode() 

1694 except ValueError: 

1695 return None # no palette 

1696 if rawmode is None: 

1697 rawmode = mode 

1698 return list(self.im.getpalette(mode, rawmode)) 

1699 

1700 @property 

1701 def has_transparency_data(self) -> bool: 

1702 """ 

1703 Determine if an image has transparency data, whether in the form of an 

1704 alpha channel, a palette with an alpha channel, or a "transparency" key 

1705 in the info dictionary. 

1706 

1707 Note the image might still appear solid, if all of the values shown 

1708 within are opaque. 

1709 

1710 :returns: A boolean. 

1711 """ 

1712 if ( 

1713 self.mode in ("LA", "La", "PA", "RGBA", "RGBa") 

1714 or "transparency" in self.info 

1715 ): 

1716 return True 

1717 if self.mode == "P": 

1718 assert self.palette is not None 

1719 return self.palette.mode.endswith("A") 

1720 return False 

1721 

1722 def apply_transparency(self) -> None: 

1723 """ 

1724 If a P mode image has a "transparency" key in the info dictionary, 

1725 remove the key and instead apply the transparency to the palette. 

1726 Otherwise, the image is unchanged. 

1727 """ 

1728 if self.mode != "P" or "transparency" not in self.info: 

1729 return 

1730 

1731 from . import ImagePalette 

1732 

1733 palette = self.getpalette("RGBA") 

1734 assert palette is not None 

1735 transparency = self.info["transparency"] 

1736 if isinstance(transparency, bytes): 

1737 for i, alpha in enumerate(transparency): 

1738 palette[i * 4 + 3] = alpha 

1739 else: 

1740 palette[transparency * 4 + 3] = 0 

1741 self.palette = ImagePalette.ImagePalette("RGBA", bytes(palette)) 

1742 self.palette.dirty = 1 

1743 

1744 del self.info["transparency"] 

1745 

1746 def getpixel( 

1747 self, xy: tuple[int, int] | list[int] 

1748 ) -> float | tuple[int, ...] | None: 

1749 """ 

1750 Returns the pixel value at a given position. 

1751 

1752 :param xy: The coordinate, given as (x, y). See 

1753 :ref:`coordinate-system`. 

1754 :returns: The pixel value. If the image is a multi-layer image, 

1755 this method returns a tuple. 

1756 """ 

1757 

1758 self.load() 

1759 return self.im.getpixel(tuple(xy)) 

1760 

1761 def getprojection(self) -> tuple[list[int], list[int]]: 

1762 """ 

1763 Get projection to x and y axes 

1764 

1765 :returns: Two sequences, indicating where there are non-zero 

1766 pixels along the X-axis and the Y-axis, respectively. 

1767 """ 

1768 

1769 self.load() 

1770 x, y = self.im.getprojection() 

1771 return list(x), list(y) 

1772 

1773 def histogram( 

1774 self, mask: Image | None = None, extrema: tuple[float, float] | None = None 

1775 ) -> list[int]: 

1776 """ 

1777 Returns a histogram for the image. The histogram is returned as a 

1778 list of pixel counts, one for each pixel value in the source 

1779 image. Counts are grouped into 256 bins for each band, even if 

1780 the image has more than 8 bits per band. If the image has more 

1781 than one band, the histograms for all bands are concatenated (for 

1782 example, the histogram for an "RGB" image contains 768 values). 

1783 

1784 A bilevel image (mode "1") is treated as a grayscale ("L") image 

1785 by this method. 

1786 

1787 If a mask is provided, the method returns a histogram for those 

1788 parts of the image where the mask image is non-zero. The mask 

1789 image must have the same size as the image, and be either a 

1790 bi-level image (mode "1") or a grayscale image ("L"). 

1791 

1792 :param mask: An optional mask. 

1793 :param extrema: An optional tuple of manually-specified extrema. 

1794 :returns: A list containing pixel counts. 

1795 """ 

1796 self.load() 

1797 if mask: 

1798 mask.load() 

1799 return self.im.histogram((0, 0), mask.im) 

1800 if self.mode in ("I", "F"): 

1801 return self.im.histogram( 

1802 extrema if extrema is not None else self.getextrema() 

1803 ) 

1804 return self.im.histogram() 

1805 

1806 def entropy( 

1807 self, mask: Image | None = None, extrema: tuple[float, float] | None = None 

1808 ) -> float: 

1809 """ 

1810 Calculates and returns the entropy for the image. 

1811 

1812 A bilevel image (mode "1") is treated as a grayscale ("L") 

1813 image by this method. 

1814 

1815 If a mask is provided, the method employs the histogram for 

1816 those parts of the image where the mask image is non-zero. 

1817 The mask image must have the same size as the image, and be 

1818 either a bi-level image (mode "1") or a grayscale image ("L"). 

1819 

1820 :param mask: An optional mask. 

1821 :param extrema: An optional tuple of manually-specified extrema. 

1822 :returns: A float value representing the image entropy 

1823 """ 

1824 self.load() 

1825 if mask: 

1826 mask.load() 

1827 return self.im.entropy((0, 0), mask.im) 

1828 if self.mode in ("I", "F"): 

1829 return self.im.entropy( 

1830 extrema if extrema is not None else self.getextrema() 

1831 ) 

1832 return self.im.entropy() 

1833 

1834 def paste( 

1835 self, 

1836 im: Image | str | float | tuple[float, ...], 

1837 box: Image | tuple[int, int, int, int] | tuple[int, int] | None = None, 

1838 mask: Image | None = None, 

1839 ) -> None: 

1840 """ 

1841 Pastes another image into this image. The box argument is either 

1842 a 2-tuple giving the upper left corner, a 4-tuple defining the 

1843 left, upper, right, and lower pixel coordinate, or None (same as 

1844 (0, 0)). See :ref:`coordinate-system`. If a 4-tuple is given, the size 

1845 of the pasted image must match the size of the region. 

1846 

1847 If the modes don't match, the pasted image is converted to the mode of 

1848 this image (see the :py:meth:`~PIL.Image.Image.convert` method for 

1849 details). 

1850 

1851 Instead of an image, the source can be a integer or tuple 

1852 containing pixel values. The method then fills the region 

1853 with the given color. When creating RGB images, you can 

1854 also use color strings as supported by the ImageColor module. See 

1855 :ref:`colors` for more information. 

1856 

1857 If a mask is given, this method updates only the regions 

1858 indicated by the mask. You can use either "1", "L", "LA", "RGBA" 

1859 or "RGBa" images (if present, the alpha band is used as mask). 

1860 Where the mask is 255, the given image is copied as is. Where 

1861 the mask is 0, the current value is preserved. Intermediate 

1862 values will mix the two images together, including their alpha 

1863 channels if they have them. 

1864 

1865 See :py:meth:`~PIL.Image.Image.alpha_composite` if you want to 

1866 combine images with respect to their alpha channels. 

1867 

1868 :param im: Source image or pixel value (integer, float or tuple). 

1869 :param box: An optional 4-tuple giving the region to paste into. 

1870 If a 2-tuple is used instead, it's treated as the upper left 

1871 corner. If omitted or None, the source is pasted into the 

1872 upper left corner. 

1873 

1874 If an image is given as the second argument and there is no 

1875 third, the box defaults to (0, 0), and the second argument 

1876 is interpreted as a mask image. 

1877 :param mask: An optional mask image. 

1878 """ 

1879 

1880 if isinstance(box, Image): 

1881 if mask is not None: 

1882 msg = "If using second argument as mask, third argument must be None" 

1883 raise ValueError(msg) 

1884 # abbreviated paste(im, mask) syntax 

1885 mask = box 

1886 box = None 

1887 

1888 if box is None: 

1889 box = (0, 0) 

1890 

1891 if len(box) == 2: 

1892 # upper left corner given; get size from image or mask 

1893 if isinstance(im, Image): 

1894 size = im.size 

1895 elif isinstance(mask, Image): 

1896 size = mask.size 

1897 else: 

1898 # FIXME: use self.size here? 

1899 msg = "cannot determine region size; use 4-item box" 

1900 raise ValueError(msg) 

1901 box += (box[0] + size[0], box[1] + size[1]) 

1902 

1903 source: core.ImagingCore | str | float | tuple[float, ...] 

1904 if isinstance(im, str): 

1905 from . import ImageColor 

1906 

1907 source = ImageColor.getcolor(im, self.mode) 

1908 elif isinstance(im, Image): 

1909 im.load() 

1910 if self.mode != im.mode: 

1911 if self.mode != "RGB" or im.mode not in ("LA", "RGBA", "RGBa"): 

1912 # should use an adapter for this! 

1913 im = im.convert(self.mode) 

1914 source = im.im 

1915 else: 

1916 source = im 

1917 

1918 self._ensure_mutable() 

1919 

1920 if mask: 

1921 mask.load() 

1922 self.im.paste(source, box, mask.im) 

1923 else: 

1924 self.im.paste(source, box) 

1925 

1926 def alpha_composite( 

1927 self, im: Image, dest: Sequence[int] = (0, 0), source: Sequence[int] = (0, 0) 

1928 ) -> None: 

1929 """'In-place' analog of Image.alpha_composite. Composites an image 

1930 onto this image. 

1931 

1932 :param im: image to composite over this one 

1933 :param dest: Optional 2 tuple (left, top) specifying the upper 

1934 left corner in this (destination) image. 

1935 :param source: Optional 2 (left, top) tuple for the upper left 

1936 corner in the overlay source image, or 4 tuple (left, top, right, 

1937 bottom) for the bounds of the source rectangle 

1938 

1939 Performance Note: Not currently implemented in-place in the core layer. 

1940 """ 

1941 

1942 if not isinstance(source, (list, tuple)): 

1943 msg = "Source must be a list or tuple" 

1944 raise ValueError(msg) 

1945 if not isinstance(dest, (list, tuple)): 

1946 msg = "Destination must be a list or tuple" 

1947 raise ValueError(msg) 

1948 

1949 if len(source) == 4: 

1950 overlay_crop_box = tuple(source) 

1951 elif len(source) == 2: 

1952 overlay_crop_box = tuple(source) + im.size 

1953 else: 

1954 msg = "Source must be a sequence of length 2 or 4" 

1955 raise ValueError(msg) 

1956 

1957 if not len(dest) == 2: 

1958 msg = "Destination must be a sequence of length 2" 

1959 raise ValueError(msg) 

1960 if min(source) < 0: 

1961 msg = "Source must be non-negative" 

1962 raise ValueError(msg) 

1963 

1964 # over image, crop if it's not the whole image. 

1965 if overlay_crop_box == (0, 0) + im.size: 

1966 overlay = im 

1967 else: 

1968 overlay = im.crop(overlay_crop_box) 

1969 

1970 # target for the paste 

1971 box = tuple(dest) + (dest[0] + overlay.width, dest[1] + overlay.height) 

1972 

1973 # destination image. don't copy if we're using the whole image. 

1974 if box == (0, 0) + self.size: 

1975 background = self 

1976 else: 

1977 background = self.crop(box) 

1978 

1979 result = alpha_composite(background, overlay) 

1980 self.paste(result, box) 

1981 

1982 def point( 

1983 self, 

1984 lut: ( 

1985 Sequence[float] 

1986 | NumpyArray 

1987 | Callable[[int], float] 

1988 | Callable[[ImagePointTransform], ImagePointTransform | float] 

1989 | ImagePointHandler 

1990 ), 

1991 mode: str | None = None, 

1992 ) -> Image: 

1993 """ 

1994 Maps this image through a lookup table or function. 

1995 

1996 :param lut: A lookup table, containing 256 (or 65536 if 

1997 self.mode=="I" and mode == "L") values per band in the 

1998 image. A function can be used instead, it should take a 

1999 single argument. The function is called once for each 

2000 possible pixel value, and the resulting table is applied to 

2001 all bands of the image. 

2002 

2003 It may also be an :py:class:`~PIL.Image.ImagePointHandler` 

2004 object:: 

2005 

2006 class Example(Image.ImagePointHandler): 

2007 def point(self, im: Image) -> Image: 

2008 # Return result 

2009 :param mode: Output mode (default is same as input). This can only be used if 

2010 the source image has mode "L" or "P", and the output has mode "1" or the 

2011 source image mode is "I" and the output mode is "L". 

2012 :returns: An :py:class:`~PIL.Image.Image` object. 

2013 """ 

2014 

2015 self.load() 

2016 

2017 if isinstance(lut, ImagePointHandler): 

2018 return lut.point(self) 

2019 

2020 if callable(lut): 

2021 # if it isn't a list, it should be a function 

2022 if self.mode in ("I", "I;16", "F"): 

2023 # check if the function can be used with point_transform 

2024 # UNDONE wiredfool -- I think this prevents us from ever doing 

2025 # a gamma function point transform on > 8bit images. 

2026 scale, offset = _getscaleoffset(lut) # type: ignore[arg-type] 

2027 return self._new(self.im.point_transform(scale, offset)) 

2028 # for other modes, convert the function to a table 

2029 flatLut = [lut(i) for i in range(256)] * self.im.bands # type: ignore[arg-type] 

2030 else: 

2031 flatLut = lut 

2032 

2033 if self.mode == "F": 

2034 # FIXME: _imaging returns a confusing error message for this case 

2035 msg = "point operation not supported for this mode" 

2036 raise ValueError(msg) 

2037 

2038 if mode != "F": 

2039 flatLut = [round(i) for i in flatLut] 

2040 return self._new(self.im.point(flatLut, mode)) 

2041 

2042 def putalpha(self, alpha: Image | int) -> None: 

2043 """ 

2044 Adds or replaces the alpha layer in this image. If the image 

2045 does not have an alpha layer, it's converted to "LA" or "RGBA". 

2046 The new layer must be either "L" or "1". 

2047 

2048 :param alpha: The new alpha layer. This can either be an "L" or "1" 

2049 image having the same size as this image, or an integer. 

2050 """ 

2051 

2052 self._ensure_mutable() 

2053 

2054 if self.mode not in ("LA", "PA", "RGBA"): 

2055 # attempt to promote self to a matching alpha mode 

2056 try: 

2057 mode = getmodebase(self.mode) + "A" 

2058 try: 

2059 self.im.setmode(mode) 

2060 except (AttributeError, ValueError) as e: 

2061 # do things the hard way 

2062 im = self.im.convert(mode) 

2063 if im.mode not in ("LA", "PA", "RGBA"): 

2064 msg = "alpha channel could not be added" 

2065 raise ValueError(msg) from e # sanity check 

2066 self.im = im 

2067 self._mode = self.im.mode 

2068 except KeyError as e: 

2069 msg = "illegal image mode" 

2070 raise ValueError(msg) from e 

2071 

2072 if self.mode in ("LA", "PA"): 

2073 band = 1 

2074 else: 

2075 band = 3 

2076 

2077 if isinstance(alpha, Image): 

2078 # alpha layer 

2079 if alpha.mode not in ("1", "L"): 

2080 msg = "illegal image mode" 

2081 raise ValueError(msg) 

2082 alpha.load() 

2083 if alpha.mode == "1": 

2084 alpha = alpha.convert("L") 

2085 else: 

2086 # constant alpha 

2087 try: 

2088 self.im.fillband(band, alpha) 

2089 except (AttributeError, ValueError): 

2090 # do things the hard way 

2091 alpha = new("L", self.size, alpha) 

2092 else: 

2093 return 

2094 

2095 self.im.putband(alpha.im, band) 

2096 

2097 def putdata( 

2098 self, 

2099 data: Sequence[float] | Sequence[Sequence[int]] | core.ImagingCore | NumpyArray, 

2100 scale: float = 1.0, 

2101 offset: float = 0.0, 

2102 ) -> None: 

2103 """ 

2104 Copies pixel data from a flattened sequence object into the image. The 

2105 values should start at the upper left corner (0, 0), continue to the 

2106 end of the line, followed directly by the first value of the second 

2107 line, and so on. Data will be read until either the image or the 

2108 sequence ends. The scale and offset values are used to adjust the 

2109 sequence values: **pixel = value*scale + offset**. 

2110 

2111 :param data: A flattened sequence object. See :ref:`colors` for more 

2112 information about values. 

2113 :param scale: An optional scale value. The default is 1.0. 

2114 :param offset: An optional offset value. The default is 0.0. 

2115 """ 

2116 

2117 self._ensure_mutable() 

2118 

2119 self.im.putdata(data, scale, offset) 

2120 

2121 def putpalette( 

2122 self, 

2123 data: ImagePalette.ImagePalette | bytes | Sequence[int], 

2124 rawmode: str = "RGB", 

2125 ) -> None: 

2126 """ 

2127 Attaches a palette to this image. The image must be a "P", "PA", "L" 

2128 or "LA" image. 

2129 

2130 The palette sequence must contain at most 256 colors, made up of one 

2131 integer value for each channel in the raw mode. 

2132 For example, if the raw mode is "RGB", then it can contain at most 768 

2133 values, made up of red, green and blue values for the corresponding pixel 

2134 index in the 256 colors. 

2135 If the raw mode is "RGBA", then it can contain at most 1024 values, 

2136 containing red, green, blue and alpha values. 

2137 

2138 Alternatively, an 8-bit string may be used instead of an integer sequence. 

2139 

2140 :param data: A palette sequence (either a list or a string). 

2141 :param rawmode: The raw mode of the palette. Either "RGB", "RGBA", "CMYK", or a 

2142 mode that can be transformed to one of those modes (e.g. "R", "RGBA;L"). 

2143 """ 

2144 from . import ImagePalette 

2145 

2146 if self.mode not in ("L", "LA", "P", "PA"): 

2147 msg = "illegal image mode" 

2148 raise ValueError(msg) 

2149 if isinstance(data, ImagePalette.ImagePalette): 

2150 if data.rawmode is not None: 

2151 palette = ImagePalette.raw(data.rawmode, data.palette) 

2152 else: 

2153 palette = ImagePalette.ImagePalette(palette=data.palette) 

2154 palette.dirty = 1 

2155 else: 

2156 if not isinstance(data, bytes): 

2157 data = bytes(data) 

2158 palette = ImagePalette.raw(rawmode, data) 

2159 self._mode = "PA" if "A" in self.mode else "P" 

2160 self.palette = palette 

2161 if rawmode.startswith("CMYK"): 

2162 self.palette.mode = "CMYK" 

2163 elif "A" in rawmode: 

2164 self.palette.mode = "RGBA" 

2165 else: 

2166 self.palette.mode = "RGB" 

2167 self.load() # install new palette 

2168 

2169 def putpixel( 

2170 self, xy: tuple[int, int], value: float | tuple[int, ...] | list[int] 

2171 ) -> None: 

2172 """ 

2173 Modifies the pixel at the given position. The color is given as 

2174 a single numerical value for single-band images, and a tuple for 

2175 multi-band images. In addition to this, RGB and RGBA tuples are 

2176 accepted for P and PA images. See :ref:`colors` for more information. 

2177 

2178 Note that this method is relatively slow. For more extensive changes, 

2179 use :py:meth:`~PIL.Image.Image.paste` or the :py:mod:`~PIL.ImageDraw` 

2180 module instead. 

2181 

2182 See: 

2183 

2184 * :py:meth:`~PIL.Image.Image.paste` 

2185 * :py:meth:`~PIL.Image.Image.putdata` 

2186 * :py:mod:`~PIL.ImageDraw` 

2187 

2188 :param xy: The pixel coordinate, given as (x, y). See 

2189 :ref:`coordinate-system`. 

2190 :param value: The pixel value. 

2191 """ 

2192 

2193 self._ensure_mutable() 

2194 

2195 if ( 

2196 self.mode in ("P", "PA") 

2197 and isinstance(value, (list, tuple)) 

2198 and len(value) in [3, 4] 

2199 ): 

2200 # RGB or RGBA value for a P or PA image 

2201 if self.mode == "PA": 

2202 alpha = value[3] if len(value) == 4 else 255 

2203 value = value[:3] 

2204 assert self.palette is not None 

2205 palette_index = self.palette.getcolor(tuple(value), self) 

2206 value = (palette_index, alpha) if self.mode == "PA" else palette_index 

2207 return self.im.putpixel(xy, value) 

2208 

2209 def remap_palette( 

2210 self, dest_map: list[int], source_palette: bytes | bytearray | None = None 

2211 ) -> Image: 

2212 """ 

2213 Rewrites the image to reorder the palette. 

2214 

2215 :param dest_map: A list of indexes into the original palette. 

2216 e.g. ``[1,0]`` would swap a two item palette, and ``list(range(256))`` 

2217 is the identity transform. 

2218 :param source_palette: Bytes or None. 

2219 :returns: An :py:class:`~PIL.Image.Image` object. 

2220 

2221 """ 

2222 from . import ImagePalette 

2223 

2224 if self.mode not in ("L", "P"): 

2225 msg = "illegal image mode" 

2226 raise ValueError(msg) 

2227 

2228 bands = 3 

2229 palette_mode = "RGB" 

2230 if source_palette is None: 

2231 if self.mode == "P": 

2232 self.load() 

2233 palette_mode = self.im.getpalettemode() 

2234 if palette_mode == "RGBA": 

2235 bands = 4 

2236 source_palette = self.im.getpalette(palette_mode, palette_mode) 

2237 else: # L-mode 

2238 source_palette = bytearray(i // 3 for i in range(768)) 

2239 elif len(source_palette) > 768: 

2240 bands = 4 

2241 palette_mode = "RGBA" 

2242 

2243 palette_bytes = b"" 

2244 new_positions = [0] * 256 

2245 

2246 # pick only the used colors from the palette 

2247 for i, oldPosition in enumerate(dest_map): 

2248 palette_bytes += source_palette[ 

2249 oldPosition * bands : oldPosition * bands + bands 

2250 ] 

2251 new_positions[oldPosition] = i 

2252 

2253 # replace the palette color id of all pixel with the new id 

2254 

2255 # Palette images are [0..255], mapped through a 1 or 3 

2256 # byte/color map. We need to remap the whole image 

2257 # from palette 1 to palette 2. New_positions is 

2258 # an array of indexes into palette 1. Palette 2 is 

2259 # palette 1 with any holes removed. 

2260 

2261 # We're going to leverage the convert mechanism to use the 

2262 # C code to remap the image from palette 1 to palette 2, 

2263 # by forcing the source image into 'L' mode and adding a 

2264 # mapping 'L' mode palette, then converting back to 'L' 

2265 # sans palette thus converting the image bytes, then 

2266 # assigning the optimized RGB palette. 

2267 

2268 # perf reference, 9500x4000 gif, w/~135 colors 

2269 # 14 sec prepatch, 1 sec postpatch with optimization forced. 

2270 

2271 mapping_palette = bytearray(new_positions) 

2272 

2273 m_im = self.copy() 

2274 m_im._mode = "P" 

2275 

2276 m_im.palette = ImagePalette.ImagePalette( 

2277 palette_mode, palette=mapping_palette * bands 

2278 ) 

2279 # possibly set palette dirty, then 

2280 # m_im.putpalette(mapping_palette, 'L') # converts to 'P' 

2281 # or just force it. 

2282 # UNDONE -- this is part of the general issue with palettes 

2283 m_im.im.putpalette(palette_mode, palette_mode + ";L", m_im.palette.tobytes()) 

2284 

2285 m_im = m_im.convert("L") 

2286 

2287 m_im.putpalette(palette_bytes, palette_mode) 

2288 m_im.palette = ImagePalette.ImagePalette(palette_mode, palette=palette_bytes) 

2289 

2290 if "transparency" in self.info: 

2291 try: 

2292 m_im.info["transparency"] = dest_map.index(self.info["transparency"]) 

2293 except ValueError: 

2294 if "transparency" in m_im.info: 

2295 del m_im.info["transparency"] 

2296 

2297 return m_im 

2298 

2299 def _get_safe_box( 

2300 self, 

2301 size: tuple[int, int], 

2302 resample: Resampling, 

2303 box: tuple[float, float, float, float], 

2304 ) -> tuple[int, int, int, int]: 

2305 """Expands the box so it includes adjacent pixels 

2306 that may be used by resampling with the given resampling filter. 

2307 """ 

2308 filter_support = _filters_support[resample] - 0.5 

2309 scale_x = (box[2] - box[0]) / size[0] 

2310 scale_y = (box[3] - box[1]) / size[1] 

2311 support_x = filter_support * scale_x 

2312 support_y = filter_support * scale_y 

2313 

2314 return ( 

2315 max(0, int(box[0] - support_x)), 

2316 max(0, int(box[1] - support_y)), 

2317 min(self.size[0], math.ceil(box[2] + support_x)), 

2318 min(self.size[1], math.ceil(box[3] + support_y)), 

2319 ) 

2320 

2321 def resize( 

2322 self, 

2323 size: tuple[int, int] | list[int] | NumpyArray, 

2324 resample: int | None = None, 

2325 box: tuple[float, float, float, float] | None = None, 

2326 reducing_gap: float | None = None, 

2327 ) -> Image: 

2328 """ 

2329 Returns a resized copy of this image. 

2330 

2331 :param size: The requested size in pixels, as a tuple or array: 

2332 (width, height). 

2333 :param resample: An optional resampling filter. This can be 

2334 one of :py:data:`Resampling.NEAREST`, :py:data:`Resampling.BOX`, 

2335 :py:data:`Resampling.BILINEAR`, :py:data:`Resampling.HAMMING`, 

2336 :py:data:`Resampling.BICUBIC` or :py:data:`Resampling.LANCZOS`. 

2337 If the image has mode "1" or "P", it is always set to 

2338 :py:data:`Resampling.NEAREST`. Otherwise, the default filter is 

2339 :py:data:`Resampling.BICUBIC`. See: :ref:`concept-filters`. 

2340 :param box: An optional 4-tuple of floats providing 

2341 the source image region to be scaled. 

2342 The values must be within (0, 0, width, height) rectangle. 

2343 If omitted or None, the entire source is used. 

2344 :param reducing_gap: Apply optimization by resizing the image 

2345 in two steps. First, reducing the image by integer times 

2346 using :py:meth:`~PIL.Image.Image.reduce`. 

2347 Second, resizing using regular resampling. The last step 

2348 changes size no less than by ``reducing_gap`` times. 

2349 ``reducing_gap`` may be None (no first step is performed) 

2350 or should be greater than 1.0. The bigger ``reducing_gap``, 

2351 the closer the result to the fair resampling. 

2352 The smaller ``reducing_gap``, the faster resizing. 

2353 With ``reducing_gap`` greater or equal to 3.0, the result is 

2354 indistinguishable from fair resampling in most cases. 

2355 The default value is None (no optimization). 

2356 :returns: An :py:class:`~PIL.Image.Image` object. 

2357 """ 

2358 

2359 if resample is None: 

2360 resample = Resampling.BICUBIC 

2361 elif resample not in ( 

2362 Resampling.NEAREST, 

2363 Resampling.BILINEAR, 

2364 Resampling.BICUBIC, 

2365 Resampling.LANCZOS, 

2366 Resampling.BOX, 

2367 Resampling.HAMMING, 

2368 ): 

2369 msg = f"Unknown resampling filter ({resample})." 

2370 

2371 filters = [ 

2372 f"{filter[1]} ({filter[0]})" 

2373 for filter in ( 

2374 (Resampling.NEAREST, "Image.Resampling.NEAREST"), 

2375 (Resampling.LANCZOS, "Image.Resampling.LANCZOS"), 

2376 (Resampling.BILINEAR, "Image.Resampling.BILINEAR"), 

2377 (Resampling.BICUBIC, "Image.Resampling.BICUBIC"), 

2378 (Resampling.BOX, "Image.Resampling.BOX"), 

2379 (Resampling.HAMMING, "Image.Resampling.HAMMING"), 

2380 ) 

2381 ] 

2382 msg += f" Use {', '.join(filters[:-1])} or {filters[-1]}" 

2383 raise ValueError(msg) 

2384 

2385 if reducing_gap is not None and reducing_gap < 1.0: 

2386 msg = "reducing_gap must be 1.0 or greater" 

2387 raise ValueError(msg) 

2388 

2389 if box is None: 

2390 box = (0, 0) + self.size 

2391 

2392 size = tuple(size) 

2393 if self.size == size and box == (0, 0) + self.size: 

2394 return self.copy() 

2395 

2396 if self.mode in ("1", "P"): 

2397 resample = Resampling.NEAREST 

2398 

2399 if self.mode in ["LA", "RGBA"] and resample != Resampling.NEAREST: 

2400 im = self.convert({"LA": "La", "RGBA": "RGBa"}[self.mode]) 

2401 im = im.resize(size, resample, box) 

2402 return im.convert(self.mode) 

2403 

2404 self.load() 

2405 

2406 if reducing_gap is not None and resample != Resampling.NEAREST: 

2407 factor_x = int((box[2] - box[0]) / size[0] / reducing_gap) or 1 

2408 factor_y = int((box[3] - box[1]) / size[1] / reducing_gap) or 1 

2409 if factor_x > 1 or factor_y > 1: 

2410 reduce_box = self._get_safe_box(size, cast(Resampling, resample), box) 

2411 factor = (factor_x, factor_y) 

2412 self = ( 

2413 self.reduce(factor, box=reduce_box) 

2414 if callable(self.reduce) 

2415 else Image.reduce(self, factor, box=reduce_box) 

2416 ) 

2417 box = ( 

2418 (box[0] - reduce_box[0]) / factor_x, 

2419 (box[1] - reduce_box[1]) / factor_y, 

2420 (box[2] - reduce_box[0]) / factor_x, 

2421 (box[3] - reduce_box[1]) / factor_y, 

2422 ) 

2423 

2424 if self.size[1] > self.size[0] * 100 and size[1] < self.size[1]: 

2425 im = self.im.resize( 

2426 (self.size[0], size[1]), resample, (0, box[1], self.size[0], box[3]) 

2427 ) 

2428 im = im.resize(size, resample, (box[0], 0, box[2], size[1])) 

2429 else: 

2430 im = self.im.resize(size, resample, box) 

2431 return self._new(im) 

2432 

2433 def reduce( 

2434 self, 

2435 factor: int | tuple[int, int], 

2436 box: tuple[int, int, int, int] | None = None, 

2437 ) -> Image: 

2438 """ 

2439 Returns a copy of the image reduced ``factor`` times. 

2440 If the size of the image is not dividable by ``factor``, 

2441 the resulting size will be rounded up. 

2442 

2443 :param factor: A greater than 0 integer or tuple of two integers 

2444 for width and height separately. 

2445 :param box: An optional 4-tuple of ints providing 

2446 the source image region to be reduced. 

2447 The values must be within ``(0, 0, width, height)`` rectangle. 

2448 If omitted or ``None``, the entire source is used. 

2449 """ 

2450 if not isinstance(factor, (list, tuple)): 

2451 factor = (factor, factor) 

2452 

2453 if box is None: 

2454 box = (0, 0) + self.size 

2455 

2456 if factor == (1, 1) and box == (0, 0) + self.size: 

2457 return self.copy() 

2458 

2459 if self.mode in ["LA", "RGBA"]: 

2460 im = self.convert({"LA": "La", "RGBA": "RGBa"}[self.mode]) 

2461 im = im.reduce(factor, box) 

2462 return im.convert(self.mode) 

2463 

2464 self.load() 

2465 

2466 return self._new(self.im.reduce(factor, box)) 

2467 

2468 def rotate( 

2469 self, 

2470 angle: float, 

2471 resample: Resampling = Resampling.NEAREST, 

2472 expand: int | bool = False, 

2473 center: tuple[float, float] | None = None, 

2474 translate: tuple[int, int] | None = None, 

2475 fillcolor: float | tuple[float, ...] | str | None = None, 

2476 ) -> Image: 

2477 """ 

2478 Returns a rotated copy of this image. This method returns a 

2479 copy of this image, rotated the given number of degrees counter 

2480 clockwise around its centre. 

2481 

2482 :param angle: In degrees counter clockwise. 

2483 :param resample: An optional resampling filter. This can be 

2484 one of :py:data:`Resampling.NEAREST` (use nearest neighbour), 

2485 :py:data:`Resampling.BILINEAR` (linear interpolation in a 2x2 

2486 environment), or :py:data:`Resampling.BICUBIC` (cubic spline 

2487 interpolation in a 4x4 environment). If omitted, or if the image has 

2488 mode "1" or "P", it is set to :py:data:`Resampling.NEAREST`. 

2489 See :ref:`concept-filters`. 

2490 :param expand: Optional expansion flag. If true, expands the output 

2491 image to make it large enough to hold the entire rotated image. 

2492 If false or omitted, make the output image the same size as the 

2493 input image. Note that the expand flag assumes rotation around 

2494 the center and no translation. 

2495 :param center: Optional center of rotation (a 2-tuple). Origin is 

2496 the upper left corner. Default is the center of the image. 

2497 :param translate: An optional post-rotate translation (a 2-tuple). 

2498 :param fillcolor: An optional color for area outside the rotated image. 

2499 :returns: An :py:class:`~PIL.Image.Image` object. 

2500 """ 

2501 

2502 angle = angle % 360.0 

2503 

2504 # Fast paths regardless of filter, as long as we're not 

2505 # translating or changing the center. 

2506 if not (center or translate): 

2507 if angle == 0: 

2508 return self.copy() 

2509 if angle == 180: 

2510 return self.transpose(Transpose.ROTATE_180) 

2511 if angle in (90, 270) and (expand or self.width == self.height): 

2512 return self.transpose( 

2513 Transpose.ROTATE_90 if angle == 90 else Transpose.ROTATE_270 

2514 ) 

2515 

2516 # Calculate the affine matrix. Note that this is the reverse 

2517 # transformation (from destination image to source) because we 

2518 # want to interpolate the (discrete) destination pixel from 

2519 # the local area around the (floating) source pixel. 

2520 

2521 # The matrix we actually want (note that it operates from the right): 

2522 # (1, 0, tx) (1, 0, cx) ( cos a, sin a, 0) (1, 0, -cx) 

2523 # (0, 1, ty) * (0, 1, cy) * (-sin a, cos a, 0) * (0, 1, -cy) 

2524 # (0, 0, 1) (0, 0, 1) ( 0, 0, 1) (0, 0, 1) 

2525 

2526 # The reverse matrix is thus: 

2527 # (1, 0, cx) ( cos -a, sin -a, 0) (1, 0, -cx) (1, 0, -tx) 

2528 # (0, 1, cy) * (-sin -a, cos -a, 0) * (0, 1, -cy) * (0, 1, -ty) 

2529 # (0, 0, 1) ( 0, 0, 1) (0, 0, 1) (0, 0, 1) 

2530 

2531 # In any case, the final translation may be updated at the end to 

2532 # compensate for the expand flag. 

2533 

2534 w, h = self.size 

2535 

2536 if translate is None: 

2537 post_trans = (0, 0) 

2538 else: 

2539 post_trans = translate 

2540 if center is None: 

2541 center = (w / 2, h / 2) 

2542 

2543 angle = -math.radians(angle) 

2544 matrix = [ 

2545 round(math.cos(angle), 15), 

2546 round(math.sin(angle), 15), 

2547 0.0, 

2548 round(-math.sin(angle), 15), 

2549 round(math.cos(angle), 15), 

2550 0.0, 

2551 ] 

2552 

2553 def transform(x: float, y: float, matrix: list[float]) -> tuple[float, float]: 

2554 a, b, c, d, e, f = matrix 

2555 return a * x + b * y + c, d * x + e * y + f 

2556 

2557 matrix[2], matrix[5] = transform( 

2558 -center[0] - post_trans[0], -center[1] - post_trans[1], matrix 

2559 ) 

2560 matrix[2] += center[0] 

2561 matrix[5] += center[1] 

2562 

2563 if expand: 

2564 # calculate output size 

2565 xx = [] 

2566 yy = [] 

2567 for x, y in ((0, 0), (w, 0), (w, h), (0, h)): 

2568 transformed_x, transformed_y = transform(x, y, matrix) 

2569 xx.append(transformed_x) 

2570 yy.append(transformed_y) 

2571 nw = math.ceil(max(xx)) - math.floor(min(xx)) 

2572 nh = math.ceil(max(yy)) - math.floor(min(yy)) 

2573 

2574 # We multiply a translation matrix from the right. Because of its 

2575 # special form, this is the same as taking the image of the 

2576 # translation vector as new translation vector. 

2577 matrix[2], matrix[5] = transform(-(nw - w) / 2.0, -(nh - h) / 2.0, matrix) 

2578 w, h = nw, nh 

2579 

2580 return self.transform( 

2581 (w, h), Transform.AFFINE, matrix, resample, fillcolor=fillcolor 

2582 ) 

2583 

2584 def save( 

2585 self, fp: StrOrBytesPath | IO[bytes], format: str | None = None, **params: Any 

2586 ) -> None: 

2587 """ 

2588 Saves this image under the given filename. If no format is 

2589 specified, the format to use is determined from the filename 

2590 extension, if possible. 

2591 

2592 Keyword options can be used to provide additional instructions 

2593 to the writer. If a writer doesn't recognise an option, it is 

2594 silently ignored. The available options are described in the 

2595 :doc:`image format documentation 

2596 <../handbook/image-file-formats>` for each writer. 

2597 

2598 You can use a file object instead of a filename. In this case, 

2599 you must always specify the format. The file object must 

2600 implement the ``seek``, ``tell``, and ``write`` 

2601 methods, and be opened in binary mode. 

2602 

2603 :param fp: A filename (string), os.PathLike object or file object. 

2604 :param format: Optional format override. If omitted, the 

2605 format to use is determined from the filename extension. 

2606 If a file object was used instead of a filename, this 

2607 parameter should always be used. 

2608 :param params: Extra parameters to the image writer. These can also be 

2609 set on the image itself through ``encoderinfo``. This is useful when 

2610 saving multiple images:: 

2611 

2612 # Saving XMP data to a single image 

2613 from PIL import Image 

2614 red = Image.new("RGB", (1, 1), "#f00") 

2615 red.save("out.mpo", xmp=b"test") 

2616 

2617 # Saving XMP data to the second frame of an image 

2618 from PIL import Image 

2619 black = Image.new("RGB", (1, 1)) 

2620 red = Image.new("RGB", (1, 1), "#f00") 

2621 red.encoderinfo = {"xmp": b"test"} 

2622 black.save("out.mpo", save_all=True, append_images=[red]) 

2623 :returns: None 

2624 :exception ValueError: If the output format could not be determined 

2625 from the file name. Use the format option to solve this. 

2626 :exception OSError: If the file could not be written. The file 

2627 may have been created, and may contain partial data. 

2628 """ 

2629 

2630 filename: str | bytes = "" 

2631 open_fp = False 

2632 if is_path(fp): 

2633 filename = os.fspath(fp) 

2634 open_fp = True 

2635 elif fp == sys.stdout and isinstance(sys.stdout, io.TextIOWrapper): 

2636 fp = sys.stdout.buffer 

2637 if not filename and hasattr(fp, "name") and is_path(fp.name): 

2638 # only set the name for metadata purposes 

2639 filename = os.fspath(fp.name) 

2640 

2641 if format: 

2642 preinit() 

2643 else: 

2644 filename_ext = os.path.splitext(filename)[1].lower() 

2645 ext = ( 

2646 filename_ext.decode() 

2647 if isinstance(filename_ext, bytes) 

2648 else filename_ext 

2649 ) 

2650 

2651 # Try importing only the plugin for this extension first 

2652 if not _import_plugin_for_extension(ext): 

2653 preinit() 

2654 

2655 if ext not in EXTENSION: 

2656 init() 

2657 try: 

2658 format = EXTENSION[ext] 

2659 except KeyError as e: 

2660 msg = f"unknown file extension: {ext}" 

2661 raise ValueError(msg) from e 

2662 

2663 from . import ImageFile 

2664 

2665 # may mutate self! 

2666 if isinstance(self, ImageFile.ImageFile) and os.path.abspath( 

2667 filename 

2668 ) == os.path.abspath(self.filename): 

2669 self._ensure_mutable() 

2670 else: 

2671 self.load() 

2672 

2673 save_all = params.pop("save_all", None) 

2674 self._default_encoderinfo = params 

2675 encoderinfo = getattr(self, "encoderinfo", {}) 

2676 self._attach_default_encoderinfo(self) 

2677 self.encoderconfig: tuple[Any, ...] = () 

2678 

2679 if format.upper() not in SAVE: 

2680 init() 

2681 if save_all or ( 

2682 save_all is None 

2683 and params.get("append_images") 

2684 and format.upper() in SAVE_ALL 

2685 ): 

2686 save_handler = SAVE_ALL[format.upper()] 

2687 else: 

2688 save_handler = SAVE[format.upper()] 

2689 

2690 created = False 

2691 if open_fp: 

2692 created = not os.path.exists(filename) 

2693 if params.get("append", False): 

2694 # Open also for reading ("+"), because TIFF save_all 

2695 # writer needs to go back and edit the written data. 

2696 fp = builtins.open(filename, "r+b") 

2697 else: 

2698 fp = builtins.open(filename, "w+b") 

2699 else: 

2700 fp = cast(IO[bytes], fp) 

2701 

2702 try: 

2703 save_handler(self, fp, filename) 

2704 except Exception: 

2705 if open_fp: 

2706 fp.close() 

2707 if created: 

2708 try: 

2709 os.remove(filename) 

2710 except PermissionError: 

2711 pass 

2712 raise 

2713 finally: 

2714 self.encoderinfo = encoderinfo 

2715 if open_fp: 

2716 fp.close() 

2717 

2718 def _attach_default_encoderinfo(self, im: Image) -> dict[str, Any]: 

2719 encoderinfo = getattr(self, "encoderinfo", {}) 

2720 self.encoderinfo = {**im._default_encoderinfo, **encoderinfo} 

2721 return encoderinfo 

2722 

2723 def seek(self, frame: int) -> None: 

2724 """ 

2725 Seeks to the given frame in this sequence file. If you seek 

2726 beyond the end of the sequence, the method raises an 

2727 ``EOFError`` exception. When a sequence file is opened, the 

2728 library automatically seeks to frame 0. 

2729 

2730 See :py:meth:`~PIL.Image.Image.tell`. 

2731 

2732 If defined, :attr:`~PIL.Image.Image.n_frames` refers to the 

2733 number of available frames. 

2734 

2735 :param frame: Frame number, starting at 0. 

2736 :exception EOFError: If the call attempts to seek beyond the end 

2737 of the sequence. 

2738 """ 

2739 

2740 # overridden by file handlers 

2741 if frame != 0: 

2742 msg = "no more images in file" 

2743 raise EOFError(msg) 

2744 

2745 def show(self, title: str | None = None) -> None: 

2746 """ 

2747 Displays this image. This method is mainly intended for debugging purposes. 

2748 

2749 This method calls :py:func:`PIL.ImageShow.show` internally. You can use 

2750 :py:func:`PIL.ImageShow.register` to override its default behaviour. 

2751 

2752 The image is first saved to a temporary file. By default, it will be in 

2753 PNG format. 

2754 

2755 On Unix, the image is then opened using the **xdg-open**, **display**, 

2756 **gm**, **eog** or **xv** utility, depending on which one can be found. 

2757 

2758 On macOS, the image is opened with the native Preview application. 

2759 

2760 On Windows, the image is opened with the standard PNG display utility. 

2761 

2762 :param title: Optional title to use for the image window, where possible. 

2763 """ 

2764 

2765 from . import ImageShow 

2766 

2767 ImageShow.show(self, title) 

2768 

2769 def split(self) -> tuple[Image, ...]: 

2770 """ 

2771 Split this image into individual bands. This method returns a 

2772 tuple of individual image bands from an image. For example, 

2773 splitting an "RGB" image creates three new images each 

2774 containing a copy of one of the original bands (red, green, 

2775 blue). 

2776 

2777 If you need only one band, :py:meth:`~PIL.Image.Image.getchannel` 

2778 method can be more convenient and faster. 

2779 

2780 :returns: A tuple containing bands. 

2781 """ 

2782 

2783 self.load() 

2784 if self.im.bands == 1: 

2785 return (self.copy(),) 

2786 return tuple(map(self._new, self.im.split())) 

2787 

2788 def getchannel(self, channel: int | str) -> Image: 

2789 """ 

2790 Returns an image containing a single channel of the source image. 

2791 

2792 :param channel: What channel to return. Could be index 

2793 (0 for "R" channel of "RGB") or channel name 

2794 ("A" for alpha channel of "RGBA"). 

2795 :returns: An image in "L" mode. 

2796 

2797 .. versionadded:: 4.3.0 

2798 """ 

2799 self.load() 

2800 

2801 if isinstance(channel, str): 

2802 try: 

2803 channel = self.getbands().index(channel) 

2804 except ValueError as e: 

2805 msg = f'The image has no channel "{channel}"' 

2806 raise ValueError(msg) from e 

2807 

2808 return self._new(self.im.getband(channel)) 

2809 

2810 def tell(self) -> int: 

2811 """ 

2812 Returns the current frame number. See :py:meth:`~PIL.Image.Image.seek`. 

2813 

2814 If defined, :attr:`~PIL.Image.Image.n_frames` refers to the 

2815 number of available frames. 

2816 

2817 :returns: Frame number, starting with 0. 

2818 """ 

2819 return 0 

2820 

2821 def thumbnail( 

2822 self, 

2823 size: tuple[float, float], 

2824 resample: Resampling = Resampling.BICUBIC, 

2825 reducing_gap: float | None = 2.0, 

2826 ) -> None: 

2827 """ 

2828 Make this image into a thumbnail. This method modifies the 

2829 image to contain a thumbnail version of itself, no larger than 

2830 the given size. This method calculates an appropriate thumbnail 

2831 size to preserve the aspect of the image, calls the 

2832 :py:meth:`~PIL.Image.Image.draft` method to configure the file reader 

2833 (where applicable), and finally resizes the image. 

2834 

2835 Note that this function modifies the :py:class:`~PIL.Image.Image` 

2836 object in place. If you need to use the full resolution image as well, 

2837 apply this method to a :py:meth:`~PIL.Image.Image.copy` of the original 

2838 image. 

2839 

2840 :param size: The requested size in pixels, as a 2-tuple: 

2841 (width, height). 

2842 :param resample: Optional resampling filter. This can be one 

2843 of :py:data:`Resampling.NEAREST`, :py:data:`Resampling.BOX`, 

2844 :py:data:`Resampling.BILINEAR`, :py:data:`Resampling.HAMMING`, 

2845 :py:data:`Resampling.BICUBIC` or :py:data:`Resampling.LANCZOS`. 

2846 If omitted, it defaults to :py:data:`Resampling.BICUBIC`. 

2847 (was :py:data:`Resampling.NEAREST` prior to version 2.5.0). 

2848 See: :ref:`concept-filters`. 

2849 :param reducing_gap: Apply optimization by resizing the image 

2850 in two steps. First, reducing the image by integer times 

2851 using :py:meth:`~PIL.Image.Image.reduce` or 

2852 :py:meth:`~PIL.Image.Image.draft` for JPEG images. 

2853 Second, resizing using regular resampling. The last step 

2854 changes size no less than by ``reducing_gap`` times. 

2855 ``reducing_gap`` may be None (no first step is performed) 

2856 or should be greater than 1.0. The bigger ``reducing_gap``, 

2857 the closer the result to the fair resampling. 

2858 The smaller ``reducing_gap``, the faster resizing. 

2859 With ``reducing_gap`` greater or equal to 3.0, the result is 

2860 indistinguishable from fair resampling in most cases. 

2861 The default value is 2.0 (very close to fair resampling 

2862 while still being faster in many cases). 

2863 :returns: None 

2864 """ 

2865 

2866 provided_size = tuple(map(math.floor, size)) 

2867 

2868 def preserve_aspect_ratio() -> tuple[int, int] | None: 

2869 def round_aspect(number: float, key: Callable[[int], float]) -> int: 

2870 return max(min(math.floor(number), math.ceil(number), key=key), 1) 

2871 

2872 x, y = provided_size 

2873 if x >= self.width and y >= self.height: 

2874 return None 

2875 

2876 aspect = self.width / self.height 

2877 if x / y >= aspect: 

2878 x = round_aspect(y * aspect, key=lambda n: abs(aspect - n / y)) 

2879 else: 

2880 y = round_aspect( 

2881 x / aspect, key=lambda n: 0 if n == 0 else abs(aspect - x / n) 

2882 ) 

2883 return x, y 

2884 

2885 preserved_size = preserve_aspect_ratio() 

2886 if preserved_size is None: 

2887 return 

2888 final_size = preserved_size 

2889 

2890 box = None 

2891 if reducing_gap is not None: 

2892 res = self.draft( 

2893 None, (int(size[0] * reducing_gap), int(size[1] * reducing_gap)) 

2894 ) 

2895 if res is not None: 

2896 box = res[1] 

2897 

2898 if self.size != final_size: 

2899 im = self.resize(final_size, resample, box=box, reducing_gap=reducing_gap) 

2900 

2901 self.im = im.im 

2902 self._size = final_size 

2903 self._mode = self.im.mode 

2904 

2905 self.readonly = 0 

2906 

2907 # FIXME: the different transform methods need further explanation 

2908 # instead of bloating the method docs, add a separate chapter. 

2909 def transform( 

2910 self, 

2911 size: tuple[int, int], 

2912 method: Transform | ImageTransformHandler | SupportsGetData, 

2913 data: Sequence[Any] | None = None, 

2914 resample: int = Resampling.NEAREST, 

2915 fill: int = 1, 

2916 fillcolor: float | tuple[float, ...] | str | None = None, 

2917 ) -> Image: 

2918 """ 

2919 Transforms this image. This method creates a new image with the 

2920 given size, and the same mode as the original, and copies data 

2921 to the new image using the given transform. 

2922 

2923 :param size: The output size in pixels, as a 2-tuple: 

2924 (width, height). 

2925 :param method: The transformation method. This is one of 

2926 :py:data:`Transform.EXTENT` (cut out a rectangular subregion), 

2927 :py:data:`Transform.AFFINE` (affine transform), 

2928 :py:data:`Transform.PERSPECTIVE` (perspective transform), 

2929 :py:data:`Transform.QUAD` (map a quadrilateral to a rectangle), or 

2930 :py:data:`Transform.MESH` (map a number of source quadrilaterals 

2931 in one operation). 

2932 

2933 It may also be an :py:class:`~PIL.Image.ImageTransformHandler` 

2934 object:: 

2935 

2936 class Example(Image.ImageTransformHandler): 

2937 def transform(self, size, data, resample, fill=1): 

2938 # Return result 

2939 

2940 Implementations of :py:class:`~PIL.Image.ImageTransformHandler` 

2941 for some of the :py:class:`Transform` methods are provided 

2942 in :py:mod:`~PIL.ImageTransform`. 

2943 

2944 It may also be an object with a ``method.getdata`` method 

2945 that returns a tuple supplying new ``method`` and ``data`` values:: 

2946 

2947 class Example: 

2948 def getdata(self): 

2949 method = Image.Transform.EXTENT 

2950 data = (0, 0, 100, 100) 

2951 return method, data 

2952 :param data: Extra data to the transformation method. 

2953 :param resample: Optional resampling filter. It can be one of 

2954 :py:data:`Resampling.NEAREST` (use nearest neighbour), 

2955 :py:data:`Resampling.BILINEAR` (linear interpolation in a 2x2 

2956 environment), or :py:data:`Resampling.BICUBIC` (cubic spline 

2957 interpolation in a 4x4 environment). If omitted, or if the image 

2958 has mode "1" or "P", it is set to :py:data:`Resampling.NEAREST`. 

2959 See: :ref:`concept-filters`. 

2960 :param fill: If ``method`` is an 

2961 :py:class:`~PIL.Image.ImageTransformHandler` object, this is one of 

2962 the arguments passed to it. Otherwise, it is unused. 

2963 :param fillcolor: Optional fill color for the area outside the 

2964 transform in the output image. 

2965 :returns: An :py:class:`~PIL.Image.Image` object. 

2966 """ 

2967 

2968 if self.mode in ("LA", "RGBA") and resample != Resampling.NEAREST: 

2969 return ( 

2970 self.convert({"LA": "La", "RGBA": "RGBa"}[self.mode]) 

2971 .transform(size, method, data, resample, fill, fillcolor) 

2972 .convert(self.mode) 

2973 ) 

2974 

2975 if isinstance(method, ImageTransformHandler): 

2976 return method.transform(size, self, resample=resample, fill=fill) 

2977 

2978 if hasattr(method, "getdata"): 

2979 # compatibility w. old-style transform objects 

2980 method, data = method.getdata() 

2981 

2982 if data is None: 

2983 msg = "missing method data" 

2984 raise ValueError(msg) 

2985 

2986 im = new(self.mode, size, fillcolor) 

2987 if self.mode == "P" and self.palette: 

2988 im.palette = self.palette.copy() 

2989 im.info = self.info.copy() 

2990 if method == Transform.MESH: 

2991 # list of quads 

2992 for box, quad in data: 

2993 im.__transformer( 

2994 box, self, Transform.QUAD, quad, resample, fillcolor is None 

2995 ) 

2996 else: 

2997 im.__transformer( 

2998 (0, 0) + size, self, method, data, resample, fillcolor is None 

2999 ) 

3000 

3001 return im 

3002 

3003 def __transformer( 

3004 self, 

3005 box: tuple[int, int, int, int], 

3006 image: Image, 

3007 method: Transform, 

3008 data: Sequence[float], 

3009 resample: int = Resampling.NEAREST, 

3010 fill: bool = True, 

3011 ) -> None: 

3012 w = box[2] - box[0] 

3013 h = box[3] - box[1] 

3014 

3015 if method == Transform.AFFINE: 

3016 data = data[:6] 

3017 

3018 elif method == Transform.EXTENT: 

3019 # convert extent to an affine transform 

3020 x0, y0, x1, y1 = data 

3021 xs = (x1 - x0) / w 

3022 ys = (y1 - y0) / h 

3023 method = Transform.AFFINE 

3024 data = (xs, 0, x0, 0, ys, y0) 

3025 

3026 elif method == Transform.PERSPECTIVE: 

3027 data = data[:8] 

3028 

3029 elif method == Transform.QUAD: 

3030 # quadrilateral warp. data specifies the four corners 

3031 # given as NW, SW, SE, and NE. 

3032 nw = data[:2] 

3033 sw = data[2:4] 

3034 se = data[4:6] 

3035 ne = data[6:8] 

3036 x0, y0 = nw 

3037 As = 1.0 / w 

3038 At = 1.0 / h 

3039 data = ( 

3040 x0, 

3041 (ne[0] - x0) * As, 

3042 (sw[0] - x0) * At, 

3043 (se[0] - sw[0] - ne[0] + x0) * As * At, 

3044 y0, 

3045 (ne[1] - y0) * As, 

3046 (sw[1] - y0) * At, 

3047 (se[1] - sw[1] - ne[1] + y0) * As * At, 

3048 ) 

3049 

3050 else: 

3051 msg = "unknown transformation method" 

3052 raise ValueError(msg) 

3053 

3054 if resample not in ( 

3055 Resampling.NEAREST, 

3056 Resampling.BILINEAR, 

3057 Resampling.BICUBIC, 

3058 ): 

3059 if resample in (Resampling.BOX, Resampling.HAMMING, Resampling.LANCZOS): 

3060 unusable: dict[int, str] = { 

3061 Resampling.BOX: "Image.Resampling.BOX", 

3062 Resampling.HAMMING: "Image.Resampling.HAMMING", 

3063 Resampling.LANCZOS: "Image.Resampling.LANCZOS", 

3064 } 

3065 msg = unusable[resample] + f" ({resample}) cannot be used." 

3066 else: 

3067 msg = f"Unknown resampling filter ({resample})." 

3068 

3069 filters = [ 

3070 f"{filter[1]} ({filter[0]})" 

3071 for filter in ( 

3072 (Resampling.NEAREST, "Image.Resampling.NEAREST"), 

3073 (Resampling.BILINEAR, "Image.Resampling.BILINEAR"), 

3074 (Resampling.BICUBIC, "Image.Resampling.BICUBIC"), 

3075 ) 

3076 ] 

3077 msg += f" Use {', '.join(filters[:-1])} or {filters[-1]}" 

3078 raise ValueError(msg) 

3079 

3080 image.load() 

3081 

3082 self.load() 

3083 

3084 if image.mode in ("1", "P"): 

3085 resample = Resampling.NEAREST 

3086 

3087 self.im.transform(box, image.im, method, data, resample, fill) 

3088 

3089 def transpose(self, method: Transpose) -> Image: 

3090 """ 

3091 Transpose image (flip or rotate in 90 degree steps) 

3092 

3093 :param method: One of :py:data:`Transpose.FLIP_LEFT_RIGHT`, 

3094 :py:data:`Transpose.FLIP_TOP_BOTTOM`, :py:data:`Transpose.ROTATE_90`, 

3095 :py:data:`Transpose.ROTATE_180`, :py:data:`Transpose.ROTATE_270`, 

3096 :py:data:`Transpose.TRANSPOSE` or :py:data:`Transpose.TRANSVERSE`. 

3097 :returns: Returns a flipped or rotated copy of this image. 

3098 """ 

3099 

3100 self.load() 

3101 return self._new(self.im.transpose(method)) 

3102 

3103 def effect_spread(self, distance: int) -> Image: 

3104 """ 

3105 Randomly spread pixels in an image. 

3106 

3107 :param distance: Distance to spread pixels. 

3108 """ 

3109 self.load() 

3110 return self._new(self.im.effect_spread(distance)) 

3111 

3112 def toqimage(self) -> ImageQt.ImageQt: 

3113 """Returns a QImage copy of this image""" 

3114 from . import ImageQt 

3115 

3116 if not ImageQt.qt_is_installed: 

3117 msg = "Qt bindings are not installed" 

3118 raise ImportError(msg) 

3119 return ImageQt.toqimage(self) 

3120 

3121 def toqpixmap(self) -> ImageQt.QPixmap: 

3122 """Returns a QPixmap copy of this image""" 

3123 from . import ImageQt 

3124 

3125 if not ImageQt.qt_is_installed: 

3126 msg = "Qt bindings are not installed" 

3127 raise ImportError(msg) 

3128 return ImageQt.toqpixmap(self) 

3129 

3130 

3131# -------------------------------------------------------------------- 

3132# Abstract handlers. 

3133 

3134 

3135class ImagePointHandler(abc.ABC): 

3136 """ 

3137 Used as a mixin by point transforms 

3138 (for use with :py:meth:`~PIL.Image.Image.point`) 

3139 """ 

3140 

3141 @abc.abstractmethod 

3142 def point(self, im: Image) -> Image: 

3143 pass 

3144 

3145 

3146class ImageTransformHandler(abc.ABC): 

3147 """ 

3148 Used as a mixin by geometry transforms 

3149 (for use with :py:meth:`~PIL.Image.Image.transform`) 

3150 """ 

3151 

3152 @abc.abstractmethod 

3153 def transform( 

3154 self, 

3155 size: tuple[int, int], 

3156 image: Image, 

3157 **options: Any, 

3158 ) -> Image: 

3159 pass 

3160 

3161 

3162# -------------------------------------------------------------------- 

3163# Factories 

3164 

3165 

3166def _check_size(size: Any) -> None: 

3167 """ 

3168 Common check to enforce type and sanity check on size tuples 

3169 

3170 :param size: Should be a 2 tuple of (width, height) 

3171 :returns: None, or raises a ValueError 

3172 """ 

3173 

3174 if not isinstance(size, (list, tuple)): 

3175 msg = "Size must be a list or tuple" 

3176 raise ValueError(msg) 

3177 if len(size) != 2: 

3178 msg = "Size must be a sequence of length 2" 

3179 raise ValueError(msg) 

3180 if size[0] < 0 or size[1] < 0: 

3181 msg = "Width and height must be >= 0" 

3182 raise ValueError(msg) 

3183 

3184 

3185def new( 

3186 mode: str, 

3187 size: tuple[int, int] | list[int], 

3188 color: float | tuple[float, ...] | str | None = 0, 

3189) -> Image: 

3190 """ 

3191 Creates a new image with the given mode and size. 

3192 

3193 :param mode: The mode to use for the new image. See: 

3194 :ref:`concept-modes`. 

3195 :param size: A 2-tuple, containing (width, height) in pixels. 

3196 :param color: What color to use for the image. Default is black. If given, 

3197 this should be a single integer or floating point value for single-band 

3198 modes, and a tuple for multi-band modes (one value per band). When 

3199 creating RGB or HSV images, you can also use color strings as supported 

3200 by the ImageColor module. See :ref:`colors` for more information. If the 

3201 color is None, the image is not initialised. 

3202 :returns: An :py:class:`~PIL.Image.Image` object. 

3203 """ 

3204 

3205 _check_size(size) 

3206 

3207 if color is None: 

3208 # don't initialize 

3209 return Image()._new(core.new(mode, size)) 

3210 

3211 if isinstance(color, str): 

3212 # css3-style specifier 

3213 

3214 from . import ImageColor 

3215 

3216 color = ImageColor.getcolor(color, mode) 

3217 

3218 im = Image() 

3219 if ( 

3220 mode == "P" 

3221 and isinstance(color, (list, tuple)) 

3222 and all(isinstance(i, int) for i in color) 

3223 ): 

3224 color_ints: tuple[int, ...] = cast(tuple[int, ...], tuple(color)) 

3225 if len(color_ints) == 3 or len(color_ints) == 4: 

3226 # RGB or RGBA value for a P image 

3227 from . import ImagePalette 

3228 

3229 im.palette = ImagePalette.ImagePalette() 

3230 color = im.palette.getcolor(color_ints) 

3231 return im._new(core.fill(mode, size, color)) 

3232 

3233 

3234def frombytes( 

3235 mode: str, 

3236 size: tuple[int, int], 

3237 data: bytes | bytearray | SupportsArrayInterface, 

3238 decoder_name: str = "raw", 

3239 *args: Any, 

3240) -> Image: 

3241 """ 

3242 Creates a copy of an image memory from pixel data in a buffer. 

3243 

3244 In its simplest form, this function takes three arguments 

3245 (mode, size, and unpacked pixel data). 

3246 

3247 You can also use any pixel decoder supported by PIL. For more 

3248 information on available decoders, see the section 

3249 :ref:`Writing Your Own File Codec <file-codecs>`. 

3250 

3251 Note that this function decodes pixel data only, not entire images. 

3252 If you have an entire image in a string, wrap it in a 

3253 :py:class:`~io.BytesIO` object, and use :py:func:`~PIL.Image.open` to load 

3254 it. 

3255 

3256 :param mode: The image mode. See: :ref:`concept-modes`. 

3257 :param size: The image size. 

3258 :param data: A byte buffer containing raw data for the given mode. 

3259 :param decoder_name: What decoder to use. 

3260 :param args: Additional parameters for the given decoder. 

3261 :returns: An :py:class:`~PIL.Image.Image` object. 

3262 """ 

3263 

3264 _check_size(size) 

3265 

3266 im = new(mode, size) 

3267 if im.width != 0 and im.height != 0: 

3268 decoder_args: Any = args 

3269 if len(decoder_args) == 1 and isinstance(decoder_args[0], tuple): 

3270 # may pass tuple instead of argument list 

3271 decoder_args = decoder_args[0] 

3272 

3273 if decoder_name == "raw" and decoder_args == (): 

3274 decoder_args = mode 

3275 

3276 im.frombytes(data, decoder_name, decoder_args) 

3277 return im 

3278 

3279 

3280def frombuffer( 

3281 mode: str, 

3282 size: tuple[int, int], 

3283 data: bytes | SupportsArrayInterface, 

3284 decoder_name: str = "raw", 

3285 *args: Any, 

3286) -> Image: 

3287 """ 

3288 Creates an image memory referencing pixel data in a byte buffer. 

3289 

3290 This function is similar to :py:func:`~PIL.Image.frombytes`, but uses data 

3291 in the byte buffer, where possible. This means that changes to the 

3292 original buffer object are reflected in this image). Not all modes can 

3293 share memory; supported modes include "L", "RGBX", "RGBA", and "CMYK". 

3294 

3295 Note that this function decodes pixel data only, not entire images. 

3296 If you have an entire image file in a string, wrap it in a 

3297 :py:class:`~io.BytesIO` object, and use :py:func:`~PIL.Image.open` to load it. 

3298 

3299 The default parameters used for the "raw" decoder differs from that used for 

3300 :py:func:`~PIL.Image.frombytes`. This is a bug, and will probably be fixed in a 

3301 future release. The current release issues a warning if you do this; to disable 

3302 the warning, you should provide the full set of parameters. See below for details. 

3303 

3304 :param mode: The image mode. See: :ref:`concept-modes`. 

3305 :param size: The image size. 

3306 :param data: A bytes or other buffer object containing raw 

3307 data for the given mode. 

3308 :param decoder_name: What decoder to use. 

3309 :param args: Additional parameters for the given decoder. For the 

3310 default encoder ("raw"), it's recommended that you provide the 

3311 full set of parameters:: 

3312 

3313 frombuffer(mode, size, data, "raw", mode, 0, 1) 

3314 

3315 :returns: An :py:class:`~PIL.Image.Image` object. 

3316 

3317 .. versionadded:: 1.1.4 

3318 """ 

3319 

3320 _check_size(size) 

3321 

3322 # may pass tuple instead of argument list 

3323 if len(args) == 1 and isinstance(args[0], tuple): 

3324 args = args[0] 

3325 

3326 if decoder_name == "raw": 

3327 if args == (): 

3328 args = mode, 0, 1 

3329 if args[0] in _MAPMODES: 

3330 im = new(mode, (0, 0)) 

3331 im = im._new(core.map_buffer(data, size, decoder_name, 0, args)) 

3332 if mode == "P": 

3333 from . import ImagePalette 

3334 

3335 im.palette = ImagePalette.ImagePalette("RGB", im.im.getpalette("RGB")) 

3336 im.readonly = 1 

3337 return im 

3338 

3339 return frombytes(mode, size, data, decoder_name, args) 

3340 

3341 

3342class SupportsArrayInterface(Protocol): 

3343 """ 

3344 An object that has an ``__array_interface__`` dictionary. 

3345 """ 

3346 

3347 @property 

3348 def __array_interface__(self) -> dict[str, Any]: 

3349 raise NotImplementedError() 

3350 

3351 

3352class SupportsArrowArrayInterface(Protocol): 

3353 """ 

3354 An object that has an ``__arrow_c_array__`` method corresponding to the arrow c 

3355 data interface. 

3356 """ 

3357 

3358 def __arrow_c_array__( 

3359 self, requested_schema: "PyCapsule" = None # type: ignore[name-defined] # noqa: F821, UP037 

3360 ) -> tuple["PyCapsule", "PyCapsule"]: # type: ignore[name-defined] # noqa: F821, UP037 

3361 raise NotImplementedError() 

3362 

3363 

3364def fromarray(obj: SupportsArrayInterface, mode: str | None = None) -> Image: 

3365 """ 

3366 Creates an image memory from an object exporting the array interface 

3367 (using the buffer protocol):: 

3368 

3369 from PIL import Image 

3370 import numpy as np 

3371 a = np.zeros((5, 5)) 

3372 im = Image.fromarray(a) 

3373 

3374 If ``obj`` is not contiguous, then the ``tobytes`` method is called 

3375 and :py:func:`~PIL.Image.frombuffer` is used. 

3376 

3377 In the case of NumPy, be aware that Pillow modes do not always correspond 

3378 to NumPy dtypes. Pillow modes only offer 1-bit pixels, 8-bit pixels, 

3379 32-bit signed integer pixels, and 32-bit floating point pixels. 

3380 

3381 Pillow images can also be converted to arrays:: 

3382 

3383 from PIL import Image 

3384 import numpy as np 

3385 im = Image.open("hopper.jpg") 

3386 a = np.asarray(im) 

3387 

3388 When converting Pillow images to arrays however, only pixel values are 

3389 transferred. This means that P and PA mode images will lose their palette. 

3390 

3391 :param obj: Object with array interface 

3392 :param mode: Optional mode to use when reading ``obj``. Since pixel values do not 

3393 contain information about palettes or color spaces, this can be used to place 

3394 grayscale L mode data within a P mode image, or read RGB data as YCbCr for 

3395 example. 

3396 

3397 See: :ref:`concept-modes` for general information about modes. 

3398 :returns: An image object. 

3399 

3400 .. versionadded:: 1.1.6 

3401 """ 

3402 arr = obj.__array_interface__ 

3403 shape = arr["shape"] 

3404 ndim = len(shape) 

3405 strides = arr.get("strides", None) 

3406 try: 

3407 typekey = (1, 1) + shape[2:], arr["typestr"] 

3408 except KeyError as e: 

3409 if mode is not None: 

3410 typekey = None 

3411 color_modes: list[str] = [] 

3412 else: 

3413 msg = "Cannot handle this data type" 

3414 raise TypeError(msg) from e 

3415 if typekey is not None: 

3416 try: 

3417 typemode, rawmode, color_modes = _fromarray_typemap[typekey] 

3418 except KeyError as e: 

3419 typekey_shape, typestr = typekey 

3420 msg = f"Cannot handle this data type: {typekey_shape}, {typestr}" 

3421 raise TypeError(msg) from e 

3422 if mode is not None: 

3423 if mode != typemode and mode not in color_modes: 

3424 deprecate("'mode' parameter for changing data types", 13) 

3425 rawmode = mode 

3426 else: 

3427 mode = typemode 

3428 if mode in ["1", "L", "I", "P", "F"]: 

3429 ndmax = 2 

3430 elif mode == "RGB": 

3431 ndmax = 3 

3432 else: 

3433 ndmax = 4 

3434 if ndim > ndmax: 

3435 msg = f"Too many dimensions: {ndim} > {ndmax}." 

3436 raise ValueError(msg) 

3437 

3438 size = 1 if ndim == 1 else shape[1], shape[0] 

3439 if strides is not None: 

3440 if hasattr(obj, "tobytes"): 

3441 obj = obj.tobytes() 

3442 elif hasattr(obj, "tostring"): 

3443 obj = obj.tostring() 

3444 else: 

3445 msg = "'strides' requires either tobytes() or tostring()" 

3446 raise ValueError(msg) 

3447 

3448 return frombuffer(mode, size, obj, "raw", rawmode, 0, 1) 

3449 

3450 

3451def fromarrow( 

3452 obj: SupportsArrowArrayInterface, mode: str, size: tuple[int, int] 

3453) -> Image: 

3454 """Creates an image with zero-copy shared memory from an object exporting 

3455 the arrow_c_array interface protocol:: 

3456 

3457 from PIL import Image 

3458 import pyarrow as pa 

3459 arr = pa.array([0]*(5*5*4), type=pa.uint8()) 

3460 im = Image.fromarrow(arr, 'RGBA', (5, 5)) 

3461 

3462 If the data representation of the ``obj`` is not compatible with 

3463 Pillow internal storage, a ValueError is raised. 

3464 

3465 Pillow images can also be converted to Arrow objects:: 

3466 

3467 from PIL import Image 

3468 import pyarrow as pa 

3469 im = Image.open('hopper.jpg') 

3470 arr = pa.array(im) 

3471 

3472 As with array support, when converting Pillow images to arrays, 

3473 only pixel values are transferred. This means that P and PA mode 

3474 images will lose their palette. 

3475 

3476 :param obj: Object with an arrow_c_array interface 

3477 :param mode: Image mode. 

3478 :param size: Image size. This must match the storage of the arrow object. 

3479 :returns: An Image object 

3480 

3481 Note that according to the Arrow spec, both the producer and the 

3482 consumer should consider the exported array to be immutable, as 

3483 unsynchronized updates will potentially cause inconsistent data. 

3484 

3485 See: :ref:`arrow-support` for more detailed information 

3486 

3487 .. versionadded:: 11.2.1 

3488 

3489 """ 

3490 if not hasattr(obj, "__arrow_c_array__"): 

3491 msg = "arrow_c_array interface not found" 

3492 raise ValueError(msg) 

3493 

3494 schema_capsule, array_capsule = obj.__arrow_c_array__() 

3495 _im = core.new_arrow(mode, size, schema_capsule, array_capsule) 

3496 if _im: 

3497 return Image()._new(_im) 

3498 

3499 msg = "new_arrow returned None without an exception" 

3500 raise ValueError(msg) 

3501 

3502 

3503def fromqimage(im: ImageQt.QImage) -> ImageFile.ImageFile: 

3504 """Creates an image instance from a QImage image""" 

3505 from . import ImageQt 

3506 

3507 if not ImageQt.qt_is_installed: 

3508 msg = "Qt bindings are not installed" 

3509 raise ImportError(msg) 

3510 return ImageQt.fromqimage(im) 

3511 

3512 

3513def fromqpixmap(im: ImageQt.QPixmap) -> ImageFile.ImageFile: 

3514 """Creates an image instance from a QPixmap image""" 

3515 from . import ImageQt 

3516 

3517 if not ImageQt.qt_is_installed: 

3518 msg = "Qt bindings are not installed" 

3519 raise ImportError(msg) 

3520 return ImageQt.fromqpixmap(im) 

3521 

3522 

3523_fromarray_typemap = { 

3524 # (shape, typestr) => mode, rawmode, color modes 

3525 # first two members of shape are set to one 

3526 ((1, 1), "|b1"): ("1", "1;8", []), 

3527 ((1, 1), "|u1"): ("L", "L", ["P"]), 

3528 ((1, 1), "|i1"): ("I", "I;8", []), 

3529 ((1, 1), "<u2"): ("I", "I;16", []), 

3530 ((1, 1), ">u2"): ("I", "I;16B", []), 

3531 ((1, 1), "<i2"): ("I", "I;16S", []), 

3532 ((1, 1), ">i2"): ("I", "I;16BS", []), 

3533 ((1, 1), "<u4"): ("I", "I;32", []), 

3534 ((1, 1), ">u4"): ("I", "I;32B", []), 

3535 ((1, 1), "<i4"): ("I", "I;32S", []), 

3536 ((1, 1), ">i4"): ("I", "I;32BS", []), 

3537 ((1, 1), "<f4"): ("F", "F;32F", []), 

3538 ((1, 1), ">f4"): ("F", "F;32BF", []), 

3539 ((1, 1), "<f8"): ("F", "F;64F", []), 

3540 ((1, 1), ">f8"): ("F", "F;64BF", []), 

3541 ((1, 1, 2), "|u1"): ("LA", "LA", ["La", "PA"]), 

3542 ((1, 1, 3), "|u1"): ("RGB", "RGB", ["YCbCr", "LAB", "HSV"]), 

3543 ((1, 1, 4), "|u1"): ("RGBA", "RGBA", ["RGBa", "RGBX", "CMYK"]), 

3544 # shortcuts: 

3545 ((1, 1), f"{_ENDIAN}i4"): ("I", "I", []), 

3546 ((1, 1), f"{_ENDIAN}f4"): ("F", "F", []), 

3547} 

3548 

3549 

3550def _decompression_bomb_check(size: tuple[int, int]) -> None: 

3551 if MAX_IMAGE_PIXELS is None: 

3552 return 

3553 

3554 pixels = max(1, size[0]) * max(1, size[1]) 

3555 

3556 if pixels > 2 * MAX_IMAGE_PIXELS: 

3557 msg = ( 

3558 f"Image size ({pixels} pixels) exceeds limit of {2 * MAX_IMAGE_PIXELS} " 

3559 "pixels, could be decompression bomb DOS attack." 

3560 ) 

3561 raise DecompressionBombError(msg) 

3562 

3563 if pixels > MAX_IMAGE_PIXELS: 

3564 warnings.warn( 

3565 f"Image size ({pixels} pixels) exceeds limit of {MAX_IMAGE_PIXELS} pixels, " 

3566 "could be decompression bomb DOS attack.", 

3567 DecompressionBombWarning, 

3568 ) 

3569 

3570 

3571def open( 

3572 fp: StrOrBytesPath | IO[bytes], 

3573 mode: Literal["r"] = "r", 

3574 formats: list[str] | tuple[str, ...] | None = None, 

3575) -> ImageFile.ImageFile: 

3576 """ 

3577 Opens and identifies the given image file. 

3578 

3579 This is a lazy operation; this function identifies the file, but 

3580 the file remains open and the actual image data is not read from 

3581 the file until you try to process the data (or call the 

3582 :py:meth:`~PIL.Image.Image.load` method). See 

3583 :py:func:`~PIL.Image.new`. See :ref:`file-handling`. 

3584 

3585 :param fp: A filename (string), os.PathLike object or a file object. 

3586 The file object must implement ``file.read``, 

3587 ``file.seek``, and ``file.tell`` methods, 

3588 and be opened in binary mode. The file object will also seek to zero 

3589 before reading. 

3590 :param mode: The mode. If given, this argument must be "r". 

3591 :param formats: A list or tuple of formats to attempt to load the file in. 

3592 This can be used to restrict the set of formats checked. 

3593 Pass ``None`` to try all supported formats. You can print the set of 

3594 available formats by running ``python3 -m PIL`` or using 

3595 the :py:func:`PIL.features.pilinfo` function. 

3596 :returns: An :py:class:`~PIL.Image.Image` object. 

3597 :exception FileNotFoundError: If the file cannot be found. 

3598 :exception PIL.UnidentifiedImageError: If the image cannot be opened and 

3599 identified. 

3600 :exception ValueError: If the ``mode`` is not "r", or if a ``StringIO`` 

3601 instance is used for ``fp``. 

3602 :exception TypeError: If ``formats`` is not ``None``, a list or a tuple. 

3603 """ 

3604 

3605 if mode != "r": 

3606 msg = f"bad mode {repr(mode)}" # type: ignore[unreachable] 

3607 raise ValueError(msg) 

3608 elif isinstance(fp, io.StringIO): 

3609 msg = ( # type: ignore[unreachable] 

3610 "StringIO cannot be used to open an image. " 

3611 "Binary data must be used instead." 

3612 ) 

3613 raise ValueError(msg) 

3614 

3615 if formats is None: 

3616 formats = ID 

3617 elif not isinstance(formats, (list, tuple)): 

3618 msg = "formats must be a list or tuple" # type: ignore[unreachable] 

3619 raise TypeError(msg) 

3620 

3621 exclusive_fp = False 

3622 filename: str | bytes = "" 

3623 if is_path(fp): 

3624 filename = os.fspath(fp) 

3625 fp = builtins.open(filename, "rb") 

3626 exclusive_fp = True 

3627 else: 

3628 fp = cast(IO[bytes], fp) 

3629 

3630 try: 

3631 fp.seek(0) 

3632 except (AttributeError, io.UnsupportedOperation): 

3633 fp = io.BytesIO(fp.read()) 

3634 exclusive_fp = True 

3635 

3636 prefix = fp.read(16) 

3637 

3638 # Try to import just the plugin needed for this file extension 

3639 # before falling back to preinit() which imports common plugins 

3640 ext = os.path.splitext(filename)[1] if filename else "" 

3641 if not _import_plugin_for_extension(ext): 

3642 preinit() 

3643 

3644 warning_messages: list[str] = [] 

3645 

3646 def _open_core( 

3647 fp: IO[bytes], 

3648 filename: str | bytes, 

3649 prefix: bytes, 

3650 formats: list[str] | tuple[str, ...], 

3651 ) -> ImageFile.ImageFile | None: 

3652 for i in formats: 

3653 i = i.upper() 

3654 if i not in OPEN: 

3655 init() 

3656 try: 

3657 factory, accept = OPEN[i] 

3658 result = not accept or accept(prefix) 

3659 if isinstance(result, str): 

3660 warning_messages.append(result) 

3661 elif result: 

3662 fp.seek(0) 

3663 im = factory(fp, filename) 

3664 _decompression_bomb_check(im.size) 

3665 return im 

3666 except (SyntaxError, IndexError, TypeError, struct.error) as e: 

3667 if WARN_POSSIBLE_FORMATS: 

3668 warning_messages.append(i + " opening failed. " + str(e)) 

3669 except BaseException: 

3670 if exclusive_fp: 

3671 fp.close() 

3672 raise 

3673 return None 

3674 

3675 im = _open_core(fp, filename, prefix, formats) 

3676 

3677 if im is None and formats is ID: 

3678 # Try preinit (few common plugins) then init (all plugins) 

3679 for loader in (preinit, init): 

3680 checked_formats = ID.copy() 

3681 loader() 

3682 if formats != checked_formats: 

3683 im = _open_core( 

3684 fp, 

3685 filename, 

3686 prefix, 

3687 tuple(f for f in formats if f not in checked_formats), 

3688 ) 

3689 if im is not None: 

3690 break 

3691 

3692 if im: 

3693 im._exclusive_fp = exclusive_fp 

3694 return im 

3695 

3696 if exclusive_fp: 

3697 fp.close() 

3698 for message in warning_messages: 

3699 warnings.warn(message) 

3700 msg = "cannot identify image file %r" % (filename if filename else fp) 

3701 raise UnidentifiedImageError(msg) 

3702 

3703 

3704# 

3705# Image processing. 

3706 

3707 

3708def alpha_composite(im1: Image, im2: Image) -> Image: 

3709 """ 

3710 Alpha composite im2 over im1. 

3711 

3712 :param im1: The first image. Must have mode RGBA or LA. 

3713 :param im2: The second image. Must have the same mode and size as the first image. 

3714 :returns: An :py:class:`~PIL.Image.Image` object. 

3715 """ 

3716 

3717 im1.load() 

3718 im2.load() 

3719 return im1._new(core.alpha_composite(im1.im, im2.im)) 

3720 

3721 

3722def blend(im1: Image, im2: Image, alpha: float) -> Image: 

3723 """ 

3724 Creates a new image by interpolating between two input images, using 

3725 a constant alpha:: 

3726 

3727 out = image1 * (1.0 - alpha) + image2 * alpha 

3728 

3729 :param im1: The first image. 

3730 :param im2: The second image. Must have the same mode and size as 

3731 the first image. 

3732 :param alpha: The interpolation alpha factor. If alpha is 0.0, a 

3733 copy of the first image is returned. If alpha is 1.0, a copy of 

3734 the second image is returned. There are no restrictions on the 

3735 alpha value. If necessary, the result is clipped to fit into 

3736 the allowed output range. 

3737 :returns: An :py:class:`~PIL.Image.Image` object. 

3738 """ 

3739 

3740 im1.load() 

3741 im2.load() 

3742 return im1._new(core.blend(im1.im, im2.im, alpha)) 

3743 

3744 

3745def composite(image1: Image, image2: Image, mask: Image) -> Image: 

3746 """ 

3747 Create composite image by blending images using a transparency mask. 

3748 

3749 :param image1: The first image. 

3750 :param image2: The second image. Must have the same mode and 

3751 size as the first image. 

3752 :param mask: A mask image. This image can have mode 

3753 "1", "L", or "RGBA", and must have the same size as the 

3754 other two images. 

3755 """ 

3756 

3757 image = image2.copy() 

3758 image.paste(image1, None, mask) 

3759 return image 

3760 

3761 

3762def eval(image: Image, *args: Callable[[int], float]) -> Image: 

3763 """ 

3764 Applies the function (which should take one argument) to each pixel 

3765 in the given image. If the image has more than one band, the same 

3766 function is applied to each band. Note that the function is 

3767 evaluated once for each possible pixel value, so you cannot use 

3768 random components or other generators. 

3769 

3770 :param image: The input image. 

3771 :param function: A function object, taking one integer argument. 

3772 :returns: An :py:class:`~PIL.Image.Image` object. 

3773 """ 

3774 

3775 return image.point(args[0]) 

3776 

3777 

3778def merge(mode: str, bands: Sequence[Image]) -> Image: 

3779 """ 

3780 Merge a set of single band images into a new multiband image. 

3781 

3782 :param mode: The mode to use for the output image. See: 

3783 :ref:`concept-modes`. 

3784 :param bands: A sequence containing one single-band image for 

3785 each band in the output image. All bands must have the 

3786 same size. 

3787 :returns: An :py:class:`~PIL.Image.Image` object. 

3788 """ 

3789 

3790 if getmodebands(mode) != len(bands) or "*" in mode: 

3791 msg = "wrong number of bands" 

3792 raise ValueError(msg) 

3793 for band in bands[1:]: 

3794 if band.mode != getmodetype(mode): 

3795 msg = "mode mismatch" 

3796 raise ValueError(msg) 

3797 if band.size != bands[0].size: 

3798 msg = "size mismatch" 

3799 raise ValueError(msg) 

3800 for band in bands: 

3801 band.load() 

3802 return bands[0]._new(core.merge(mode, *[b.im for b in bands])) 

3803 

3804 

3805# -------------------------------------------------------------------- 

3806# Plugin registry 

3807 

3808 

3809def register_open( 

3810 id: str, 

3811 factory: ( 

3812 Callable[[IO[bytes], str | bytes], ImageFile.ImageFile] 

3813 | type[ImageFile.ImageFile] 

3814 ), 

3815 accept: Callable[[bytes], bool | str] | None = None, 

3816) -> None: 

3817 """ 

3818 Register an image file plugin. This function should not be used 

3819 in application code. 

3820 

3821 :param id: An image format identifier. 

3822 :param factory: An image file factory method. 

3823 :param accept: An optional function that can be used to quickly 

3824 reject images having another format. 

3825 """ 

3826 id = id.upper() 

3827 if id not in ID: 

3828 ID.append(id) 

3829 OPEN[id] = factory, accept 

3830 

3831 

3832def register_mime(id: str, mimetype: str) -> None: 

3833 """ 

3834 Registers an image MIME type by populating ``Image.MIME``. This function 

3835 should not be used in application code. 

3836 

3837 ``Image.MIME`` provides a mapping from image format identifiers to mime 

3838 formats, but :py:meth:`~PIL.ImageFile.ImageFile.get_format_mimetype` can 

3839 provide a different result for specific images. 

3840 

3841 :param id: An image format identifier. 

3842 :param mimetype: The image MIME type for this format. 

3843 """ 

3844 MIME[id.upper()] = mimetype 

3845 

3846 

3847def register_save( 

3848 id: str, driver: Callable[[Image, IO[bytes], str | bytes], None] 

3849) -> None: 

3850 """ 

3851 Registers an image save function. This function should not be 

3852 used in application code. 

3853 

3854 :param id: An image format identifier. 

3855 :param driver: A function to save images in this format. 

3856 """ 

3857 SAVE[id.upper()] = driver 

3858 

3859 

3860def register_save_all( 

3861 id: str, driver: Callable[[Image, IO[bytes], str | bytes], None] 

3862) -> None: 

3863 """ 

3864 Registers an image function to save all the frames 

3865 of a multiframe format. This function should not be 

3866 used in application code. 

3867 

3868 :param id: An image format identifier. 

3869 :param driver: A function to save images in this format. 

3870 """ 

3871 SAVE_ALL[id.upper()] = driver 

3872 

3873 

3874def register_extension(id: str, extension: str) -> None: 

3875 """ 

3876 Registers an image extension. This function should not be 

3877 used in application code. 

3878 

3879 :param id: An image format identifier. 

3880 :param extension: An extension used for this format. 

3881 """ 

3882 EXTENSION[extension.lower()] = id.upper() 

3883 

3884 

3885def register_extensions(id: str, extensions: list[str]) -> None: 

3886 """ 

3887 Registers image extensions. This function should not be 

3888 used in application code. 

3889 

3890 :param id: An image format identifier. 

3891 :param extensions: A list of extensions used for this format. 

3892 """ 

3893 for extension in extensions: 

3894 register_extension(id, extension) 

3895 

3896 

3897def registered_extensions() -> dict[str, str]: 

3898 """ 

3899 Returns a dictionary containing all file extensions belonging 

3900 to registered plugins 

3901 """ 

3902 init() 

3903 return EXTENSION 

3904 

3905 

3906def register_decoder(name: str, decoder: type[ImageFile.PyDecoder]) -> None: 

3907 """ 

3908 Registers an image decoder. This function should not be 

3909 used in application code. 

3910 

3911 :param name: The name of the decoder 

3912 :param decoder: An ImageFile.PyDecoder object 

3913 

3914 .. versionadded:: 4.1.0 

3915 """ 

3916 DECODERS[name] = decoder 

3917 

3918 

3919def register_encoder(name: str, encoder: type[ImageFile.PyEncoder]) -> None: 

3920 """ 

3921 Registers an image encoder. This function should not be 

3922 used in application code. 

3923 

3924 :param name: The name of the encoder 

3925 :param encoder: An ImageFile.PyEncoder object 

3926 

3927 .. versionadded:: 4.1.0 

3928 """ 

3929 ENCODERS[name] = encoder 

3930 

3931 

3932# -------------------------------------------------------------------- 

3933# Simple display support. 

3934 

3935 

3936def _show(image: Image, **options: Any) -> None: 

3937 from . import ImageShow 

3938 

3939 deprecate("Image._show", 13, "ImageShow.show") 

3940 ImageShow.show(image, **options) 

3941 

3942 

3943# -------------------------------------------------------------------- 

3944# Effects 

3945 

3946 

3947def effect_mandelbrot( 

3948 size: tuple[int, int], extent: tuple[float, float, float, float], quality: int 

3949) -> Image: 

3950 """ 

3951 Generate a Mandelbrot set covering the given extent. 

3952 

3953 :param size: The requested size in pixels, as a 2-tuple: 

3954 (width, height). 

3955 :param extent: The extent to cover, as a 4-tuple: 

3956 (x0, y0, x1, y1). 

3957 :param quality: Quality. 

3958 """ 

3959 return Image()._new(core.effect_mandelbrot(size, extent, quality)) 

3960 

3961 

3962def effect_noise(size: tuple[int, int], sigma: float) -> Image: 

3963 """ 

3964 Generate Gaussian noise centered around 128. 

3965 

3966 :param size: The requested size in pixels, as a 2-tuple: 

3967 (width, height). 

3968 :param sigma: Standard deviation of noise. 

3969 """ 

3970 return Image()._new(core.effect_noise(size, sigma)) 

3971 

3972 

3973def linear_gradient(mode: str) -> Image: 

3974 """ 

3975 Generate 256x256 linear gradient from black to white, top to bottom. 

3976 

3977 :param mode: Input mode. 

3978 """ 

3979 return Image()._new(core.linear_gradient(mode)) 

3980 

3981 

3982def radial_gradient(mode: str) -> Image: 

3983 """ 

3984 Generate 256x256 radial gradient from black to white, centre to edge. 

3985 

3986 :param mode: Input mode. 

3987 """ 

3988 return Image()._new(core.radial_gradient(mode)) 

3989 

3990 

3991# -------------------------------------------------------------------- 

3992# Resources 

3993 

3994 

3995def _apply_env_variables(env: dict[str, str] | None = None) -> None: 

3996 env_dict = env if env is not None else os.environ 

3997 

3998 for var_name, setter in [ 

3999 ("PILLOW_ALIGNMENT", core.set_alignment), 

4000 ("PILLOW_BLOCK_SIZE", core.set_block_size), 

4001 ("PILLOW_BLOCKS_MAX", core.set_blocks_max), 

4002 ]: 

4003 if var_name not in env_dict: 

4004 continue 

4005 

4006 var = env_dict[var_name].lower() 

4007 

4008 units = 1 

4009 for postfix, mul in [("k", 1024), ("m", 1024 * 1024)]: 

4010 if var.endswith(postfix): 

4011 units = mul 

4012 var = var[: -len(postfix)] 

4013 

4014 try: 

4015 var_int = int(var) * units 

4016 except ValueError: 

4017 warnings.warn(f"{var_name} is not int") 

4018 continue 

4019 

4020 try: 

4021 setter(var_int) 

4022 except ValueError as e: 

4023 warnings.warn(f"{var_name}: {e}") 

4024 

4025 

4026_apply_env_variables() 

4027atexit.register(core.clear_cache) 

4028 

4029 

4030if TYPE_CHECKING: 

4031 _ExifBase = MutableMapping[int, Any] 

4032else: 

4033 _ExifBase = MutableMapping 

4034 

4035 

4036class Exif(_ExifBase): 

4037 """ 

4038 This class provides read and write access to EXIF image data:: 

4039 

4040 from PIL import Image 

4041 im = Image.open("exif.png") 

4042 exif = im.getexif() # Returns an instance of this class 

4043 

4044 Information can be read and written, iterated over or deleted:: 

4045 

4046 print(exif[274]) # 1 

4047 exif[274] = 2 

4048 for k, v in exif.items(): 

4049 print("Tag", k, "Value", v) # Tag 274 Value 2 

4050 del exif[274] 

4051 

4052 To access information beyond IFD0, :py:meth:`~PIL.Image.Exif.get_ifd` 

4053 returns a dictionary:: 

4054 

4055 from PIL import ExifTags 

4056 im = Image.open("exif_gps.jpg") 

4057 exif = im.getexif() 

4058 gps_ifd = exif.get_ifd(ExifTags.IFD.GPSInfo) 

4059 print(gps_ifd) 

4060 

4061 Other IFDs include ``ExifTags.IFD.Exif``, ``ExifTags.IFD.MakerNote``, 

4062 ``ExifTags.IFD.Interop`` and ``ExifTags.IFD.IFD1``. 

4063 

4064 :py:mod:`~PIL.ExifTags` also has enum classes to provide names for data:: 

4065 

4066 print(exif[ExifTags.Base.Software]) # PIL 

4067 print(gps_ifd[ExifTags.GPS.GPSDateStamp]) # 1999:99:99 99:99:99 

4068 """ 

4069 

4070 endian: str | None = None 

4071 bigtiff = False 

4072 _loaded = False 

4073 

4074 def __init__(self) -> None: 

4075 self._data: dict[int, Any] = {} 

4076 self._hidden_data: dict[int, Any] = {} 

4077 self._ifds: dict[int, dict[int, Any]] = {} 

4078 self._info: TiffImagePlugin.ImageFileDirectory_v2 | None = None 

4079 self._loaded_exif: bytes | None = None 

4080 

4081 def _fixup(self, value: Any) -> Any: 

4082 try: 

4083 if len(value) == 1 and isinstance(value, tuple): 

4084 return value[0] 

4085 except Exception: 

4086 pass 

4087 return value 

4088 

4089 def _fixup_dict(self, src_dict: dict[int, Any]) -> dict[int, Any]: 

4090 # Helper function 

4091 # returns a dict with any single item tuples/lists as individual values 

4092 return {k: self._fixup(v) for k, v in src_dict.items()} 

4093 

4094 def _get_ifd_dict( 

4095 self, offset: int, group: int | None = None 

4096 ) -> dict[int, Any] | None: 

4097 try: 

4098 # an offset pointer to the location of the nested embedded IFD. 

4099 # It should be a long, but may be corrupted. 

4100 self.fp.seek(offset) 

4101 except (KeyError, TypeError): 

4102 return None 

4103 else: 

4104 from . import TiffImagePlugin 

4105 

4106 info = TiffImagePlugin.ImageFileDirectory_v2(self.head, group=group) 

4107 info.load(self.fp) 

4108 return self._fixup_dict(dict(info)) 

4109 

4110 def _get_head(self) -> bytes: 

4111 version = b"\x2b" if self.bigtiff else b"\x2a" 

4112 if self.endian == "<": 

4113 head = b"II" + version + b"\x00" + o32le(8) 

4114 else: 

4115 head = b"MM\x00" + version + o32be(8) 

4116 if self.bigtiff: 

4117 head += o32le(8) if self.endian == "<" else o32be(8) 

4118 head += b"\x00\x00\x00\x00" 

4119 return head 

4120 

4121 def load(self, data: bytes) -> None: 

4122 # Extract EXIF information. This is highly experimental, 

4123 # and is likely to be replaced with something better in a future 

4124 # version. 

4125 

4126 # The EXIF record consists of a TIFF file embedded in a JPEG 

4127 # application marker (!). 

4128 if data == self._loaded_exif: 

4129 return 

4130 self._loaded_exif = data 

4131 self._data.clear() 

4132 self._hidden_data.clear() 

4133 self._ifds.clear() 

4134 while data and data.startswith(b"Exif\x00\x00"): 

4135 data = data[6:] 

4136 if not data: 

4137 self._info = None 

4138 return 

4139 

4140 self.fp: IO[bytes] = io.BytesIO(data) 

4141 self.head = self.fp.read(8) 

4142 # process dictionary 

4143 from . import TiffImagePlugin 

4144 

4145 self._info = TiffImagePlugin.ImageFileDirectory_v2(self.head) 

4146 self.endian = self._info._endian 

4147 self.fp.seek(self._info.next) 

4148 self._info.load(self.fp) 

4149 

4150 def load_from_fp(self, fp: IO[bytes], offset: int | None = None) -> None: 

4151 self._loaded_exif = None 

4152 self._data.clear() 

4153 self._hidden_data.clear() 

4154 self._ifds.clear() 

4155 

4156 # process dictionary 

4157 from . import TiffImagePlugin 

4158 

4159 self.fp = fp 

4160 if offset is not None: 

4161 self.head = self._get_head() 

4162 else: 

4163 self.head = self.fp.read(8) 

4164 self._info = TiffImagePlugin.ImageFileDirectory_v2(self.head) 

4165 if self.endian is None: 

4166 self.endian = self._info._endian 

4167 if offset is None: 

4168 offset = self._info.next 

4169 self.fp.tell() 

4170 self.fp.seek(offset) 

4171 self._info.load(self.fp) 

4172 

4173 def _get_merged_dict(self) -> dict[int, Any]: 

4174 merged_dict = dict(self) 

4175 

4176 # get EXIF extension 

4177 if ExifTags.IFD.Exif in self: 

4178 ifd = self._get_ifd_dict(self[ExifTags.IFD.Exif], ExifTags.IFD.Exif) 

4179 if ifd: 

4180 merged_dict.update(ifd) 

4181 

4182 # GPS 

4183 if ExifTags.IFD.GPSInfo in self: 

4184 merged_dict[ExifTags.IFD.GPSInfo] = self._get_ifd_dict( 

4185 self[ExifTags.IFD.GPSInfo], ExifTags.IFD.GPSInfo 

4186 ) 

4187 

4188 return merged_dict 

4189 

4190 def tobytes(self, offset: int = 8) -> bytes: 

4191 from . import TiffImagePlugin 

4192 

4193 head = self._get_head() 

4194 ifd = TiffImagePlugin.ImageFileDirectory_v2(ifh=head) 

4195 for tag, ifd_dict in self._ifds.items(): 

4196 if tag not in self: 

4197 ifd[tag] = ifd_dict 

4198 for tag, value in self.items(): 

4199 if tag in [ 

4200 ExifTags.IFD.Exif, 

4201 ExifTags.IFD.GPSInfo, 

4202 ] and not isinstance(value, dict): 

4203 value = self.get_ifd(tag) 

4204 if ( 

4205 tag == ExifTags.IFD.Exif 

4206 and ExifTags.IFD.Interop in value 

4207 and not isinstance(value[ExifTags.IFD.Interop], dict) 

4208 ): 

4209 value = value.copy() 

4210 value[ExifTags.IFD.Interop] = self.get_ifd(ExifTags.IFD.Interop) 

4211 ifd[tag] = value 

4212 return b"Exif\x00\x00" + head + ifd.tobytes(offset) 

4213 

4214 def get_ifd(self, tag: int) -> dict[int, Any]: 

4215 if tag not in self._ifds: 

4216 if tag == ExifTags.IFD.IFD1: 

4217 if self._info is not None and self._info.next != 0: 

4218 ifd = self._get_ifd_dict(self._info.next) 

4219 if ifd is not None: 

4220 self._ifds[tag] = ifd 

4221 elif tag in [ExifTags.IFD.Exif, ExifTags.IFD.GPSInfo]: 

4222 offset = self._hidden_data.get(tag, self.get(tag)) 

4223 if offset is not None: 

4224 ifd = self._get_ifd_dict(offset, tag) 

4225 if ifd is not None: 

4226 self._ifds[tag] = ifd 

4227 elif tag in [ExifTags.IFD.Interop, ExifTags.IFD.MakerNote]: 

4228 if ExifTags.IFD.Exif not in self._ifds: 

4229 self.get_ifd(ExifTags.IFD.Exif) 

4230 tag_data = self._ifds[ExifTags.IFD.Exif][tag] 

4231 if tag == ExifTags.IFD.MakerNote: 

4232 from .TiffImagePlugin import ImageFileDirectory_v2 

4233 

4234 try: 

4235 if tag_data.startswith(b"FUJIFILM"): 

4236 ifd_offset = i32le(tag_data, 8) 

4237 ifd_data = tag_data[ifd_offset:] 

4238 

4239 makernote = {} 

4240 for i in range(struct.unpack("<H", ifd_data[:2])[0]): 

4241 ifd_tag, typ, count, data = struct.unpack( 

4242 "<HHL4s", ifd_data[i * 12 + 2 : (i + 1) * 12 + 2] 

4243 ) 

4244 try: 

4245 ( 

4246 unit_size, 

4247 handler, 

4248 ) = ImageFileDirectory_v2._load_dispatch[typ] 

4249 except KeyError: 

4250 continue 

4251 size = count * unit_size 

4252 if size > 4: 

4253 (offset,) = struct.unpack("<L", data) 

4254 data = ifd_data[offset - 12 : offset + size - 12] 

4255 else: 

4256 data = data[:size] 

4257 

4258 if len(data) != size: 

4259 warnings.warn( 

4260 "Possibly corrupt EXIF MakerNote data. " 

4261 f"Expecting to read {size} bytes but only got " 

4262 f"{len(data)}. Skipping tag {ifd_tag}" 

4263 ) 

4264 continue 

4265 

4266 if not data: 

4267 continue 

4268 

4269 makernote[ifd_tag] = handler( 

4270 ImageFileDirectory_v2(), data, False 

4271 ) 

4272 self._ifds[tag] = dict(self._fixup_dict(makernote)) 

4273 elif self.get(0x010F) == "Nintendo": 

4274 makernote = {} 

4275 for i in range(struct.unpack(">H", tag_data[:2])[0]): 

4276 ifd_tag, typ, count, data = struct.unpack( 

4277 ">HHL4s", tag_data[i * 12 + 2 : (i + 1) * 12 + 2] 

4278 ) 

4279 if ifd_tag == 0x1101: 

4280 # CameraInfo 

4281 (offset,) = struct.unpack(">L", data) 

4282 self.fp.seek(offset) 

4283 

4284 camerainfo: dict[str, int | bytes] = { 

4285 "ModelID": self.fp.read(4) 

4286 } 

4287 

4288 self.fp.read(4) 

4289 # Seconds since 2000 

4290 camerainfo["TimeStamp"] = i32le(self.fp.read(12)) 

4291 

4292 self.fp.read(4) 

4293 camerainfo["InternalSerialNumber"] = self.fp.read(4) 

4294 

4295 self.fp.read(12) 

4296 parallax = self.fp.read(4) 

4297 handler = ImageFileDirectory_v2._load_dispatch[ 

4298 TiffTags.FLOAT 

4299 ][1] 

4300 camerainfo["Parallax"] = handler( 

4301 ImageFileDirectory_v2(), parallax, False 

4302 )[0] 

4303 

4304 self.fp.read(4) 

4305 camerainfo["Category"] = self.fp.read(2) 

4306 

4307 makernote = {0x1101: camerainfo} 

4308 self._ifds[tag] = makernote 

4309 except struct.error: 

4310 pass 

4311 else: 

4312 # Interop 

4313 ifd = self._get_ifd_dict(tag_data, tag) 

4314 if ifd is not None: 

4315 self._ifds[tag] = ifd 

4316 ifd = self._ifds.setdefault(tag, {}) 

4317 if tag == ExifTags.IFD.Exif and self._hidden_data: 

4318 ifd = { 

4319 k: v 

4320 for (k, v) in ifd.items() 

4321 if k not in (ExifTags.IFD.Interop, ExifTags.IFD.MakerNote) 

4322 } 

4323 return ifd 

4324 

4325 def hide_offsets(self) -> None: 

4326 for tag in (ExifTags.IFD.Exif, ExifTags.IFD.GPSInfo): 

4327 if tag in self: 

4328 self._hidden_data[tag] = self[tag] 

4329 del self[tag] 

4330 

4331 def __str__(self) -> str: 

4332 if self._info is not None: 

4333 # Load all keys into self._data 

4334 for tag in self._info: 

4335 self[tag] 

4336 

4337 return str(self._data) 

4338 

4339 def __len__(self) -> int: 

4340 keys = set(self._data) 

4341 if self._info is not None: 

4342 keys.update(self._info) 

4343 return len(keys) 

4344 

4345 def __getitem__(self, tag: int) -> Any: 

4346 if self._info is not None and tag not in self._data and tag in self._info: 

4347 self._data[tag] = self._fixup(self._info[tag]) 

4348 del self._info[tag] 

4349 return self._data[tag] 

4350 

4351 def __contains__(self, tag: object) -> bool: 

4352 return tag in self._data or (self._info is not None and tag in self._info) 

4353 

4354 def __setitem__(self, tag: int, value: Any) -> None: 

4355 if self._info is not None and tag in self._info: 

4356 del self._info[tag] 

4357 self._data[tag] = value 

4358 

4359 def __delitem__(self, tag: int) -> None: 

4360 if self._info is not None and tag in self._info: 

4361 del self._info[tag] 

4362 else: 

4363 del self._data[tag] 

4364 if tag in self._ifds: 

4365 del self._ifds[tag] 

4366 

4367 def __iter__(self) -> Iterator[int]: 

4368 keys = set(self._data) 

4369 if self._info is not None: 

4370 keys.update(self._info) 

4371 return iter(keys)