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

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

1787 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 

29__lazy_modules__ = { 

30 "PIL._binary", 

31 "PIL._deprecate", 

32 "PIL._util", 

33 "io", 

34 "math", 

35 "re", 

36 "struct", 

37} 

38 

39import abc 

40import atexit 

41import builtins 

42import io 

43import math 

44import os 

45import re 

46import struct 

47import sys 

48import warnings 

49from collections.abc import MutableMapping 

50from enum import IntEnum 

51from typing import IO, Protocol, cast 

52 

53# VERSION was removed in Pillow 6.0.0. 

54# PILLOW_VERSION was removed in Pillow 9.0.0. 

55# Use __version__ instead. 

56from . import ( 

57 ExifTags, 

58 ImageMode, 

59 TiffTags, 

60 UnidentifiedImageError, 

61 __version__, 

62 _plugins, 

63) 

64from ._binary import i32le, o32be, o32le 

65from ._deprecate import deprecate 

66from ._util import DeferredError, is_path 

67 

68TYPE_CHECKING = False 

69if TYPE_CHECKING: 

70 from collections.abc import Callable, Iterator, Sequence 

71 from typing import Any, Literal, Self 

72 

73 

74class DecompressionBombWarning(RuntimeWarning): 

75 pass 

76 

77 

78class DecompressionBombError(Exception): 

79 pass 

80 

81 

82WARN_POSSIBLE_FORMATS: bool = False 

83 

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

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

86 

87 

88try: 

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

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

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

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

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

94 from . import _imaging as core 

95 

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

97 msg = ( 

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

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

100 f"Pillow version: {__version__}" 

101 ) 

102 raise ImportError(msg) 

103 

104except ImportError as v: 

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

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

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

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

109 # possible. 

110 warnings.warn( 

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

112 RuntimeWarning, 

113 ) 

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

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

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

117 # see docs/porting.rst 

118 raise 

119 

120 

121# 

122# Constants 

123 

124 

125# transpose 

126class Transpose(IntEnum): 

127 FLIP_LEFT_RIGHT = 0 

128 FLIP_TOP_BOTTOM = 1 

129 ROTATE_90 = 2 

130 ROTATE_180 = 3 

131 ROTATE_270 = 4 

132 TRANSPOSE = 5 

133 TRANSVERSE = 6 

134 

135 

136# transforms (also defined in Imaging.h) 

137class Transform(IntEnum): 

138 AFFINE = 0 

139 EXTENT = 1 

140 PERSPECTIVE = 2 

141 QUAD = 3 

142 MESH = 4 

143 

144 

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

146class Resampling(IntEnum): 

147 NEAREST = 0 

148 BOX = 4 

149 BILINEAR = 2 

150 HAMMING = 5 

151 BICUBIC = 3 

152 LANCZOS = 1 

153 MKS2013 = 6 

154 MKS2021 = 7 

155 

156 

157_filters_support = { 

158 Resampling.BOX: 0.5, 

159 Resampling.BILINEAR: 1.0, 

160 Resampling.HAMMING: 1.0, 

161 Resampling.BICUBIC: 2.0, 

162 Resampling.LANCZOS: 3.0, 

163 Resampling.MKS2013: 2.5, 

164 Resampling.MKS2021: 4.5, 

165} 

166 

167 

168# dithers 

169class Dither(IntEnum): 

170 NONE = 0 

171 ORDERED = 1 # Not yet implemented 

172 RASTERIZE = 2 # Not yet implemented 

173 FLOYDSTEINBERG = 3 # default 

174 

175 

176# palettes/quantizers 

177class Palette(IntEnum): 

178 WEB = 0 

179 ADAPTIVE = 1 

180 

181 

182class Quantize(IntEnum): 

183 MEDIANCUT = 0 

184 MAXCOVERAGE = 1 

185 FASTOCTREE = 2 

186 LIBIMAGEQUANT = 3 

187 

188 

189module = sys.modules[__name__] 

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

191 for item in enum: 

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

193 

194 

195if hasattr(core, "DEFAULT_STRATEGY"): 

196 DEFAULT_STRATEGY = core.DEFAULT_STRATEGY 

197 FILTERED = core.FILTERED 

198 HUFFMAN_ONLY = core.HUFFMAN_ONLY 

199 RLE = core.RLE 

200 FIXED = core.FIXED 

201 

202 

203# -------------------------------------------------------------------- 

204# Registries 

205 

206TYPE_CHECKING = False 

207if TYPE_CHECKING: 

208 import mmap 

209 from xml.etree.ElementTree import Element 

210 

211 from IPython.lib.pretty import PrettyPrinter 

212 

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

214 from ._typing import CapsuleType, NumpyArray, StrOrBytesPath 

215ID: list[str] = [] 

216OPEN: dict[ 

217 str, 

218 tuple[ 

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

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

221 ], 

222] = {} 

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

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

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

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

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

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

229 

230# -------------------------------------------------------------------- 

231# Modes 

232 

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

234 

235 

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

237 m = ImageMode.getmode(im.mode) 

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

239 extra = len(m.bands) 

240 if extra != 1: 

241 shape += (extra,) 

242 return shape, m.typestr 

243 

244 

245MODES = [ 

246 "1", 

247 "CMYK", 

248 "F", 

249 "HSV", 

250 "I", 

251 "I;16", 

252 "I;16B", 

253 "I;16L", 

254 "I;16N", 

255 "L", 

256 "LA", 

257 "La", 

258 "LAB", 

259 "P", 

260 "PA", 

261 "RGB", 

262 "RGBA", 

263 "RGBa", 

264 "RGBX", 

265 "YCbCr", 

266] 

267 

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

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

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

271 

272 

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

274 """ 

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

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

277 contain color data. 

278 

279 :param mode: Input mode. 

280 :returns: "L" or "RGB". 

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

282 """ 

283 return ImageMode.getmode(mode).basemode 

284 

285 

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

287 """ 

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

289 single-layer mode suitable for storing individual bands. 

290 

291 :param mode: Input mode. 

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

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

294 """ 

295 return ImageMode.getmode(mode).basetype 

296 

297 

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

299 """ 

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

301 a tuple containing the names of individual bands (use 

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

303 individual band. 

304 

305 :param mode: Input mode. 

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

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

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

309 """ 

310 return ImageMode.getmode(mode).bands 

311 

312 

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

314 """ 

315 Gets the number of individual bands for this mode. 

316 

317 :param mode: Input mode. 

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

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

320 """ 

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

322 

323 

324# -------------------------------------------------------------------- 

325# Helpers 

326 

327_initialized = 0 

328 

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

330_EXTENSION_PLUGIN: dict[str, str] = { 

331 # Common formats (preinit) 

332 ".bmp": "BmpImagePlugin", 

333 ".dib": "BmpImagePlugin", 

334 ".gif": "GifImagePlugin", 

335 ".jfif": "JpegImagePlugin", 

336 ".jpe": "JpegImagePlugin", 

337 ".jpg": "JpegImagePlugin", 

338 ".jpeg": "JpegImagePlugin", 

339 ".pbm": "PpmImagePlugin", 

340 ".pgm": "PpmImagePlugin", 

341 ".pnm": "PpmImagePlugin", 

342 ".ppm": "PpmImagePlugin", 

343 ".pfm": "PpmImagePlugin", 

344 ".png": "PngImagePlugin", 

345 ".apng": "PngImagePlugin", 

346 # Less common formats (init) 

347 ".avif": "AvifImagePlugin", 

348 ".avifs": "AvifImagePlugin", 

349 ".blp": "BlpImagePlugin", 

350 ".bufr": "BufrStubImagePlugin", 

351 ".cur": "CurImagePlugin", 

352 ".dcx": "DcxImagePlugin", 

353 ".dds": "DdsImagePlugin", 

354 ".ps": "EpsImagePlugin", 

355 ".eps": "EpsImagePlugin", 

356 ".fit": "FitsImagePlugin", 

357 ".fits": "FitsImagePlugin", 

358 ".fli": "FliImagePlugin", 

359 ".flc": "FliImagePlugin", 

360 ".fpx": "FpxImagePlugin", 

361 ".ftc": "FtexImagePlugin", 

362 ".ftu": "FtexImagePlugin", 

363 ".gbr": "GbrImagePlugin", 

364 ".grib": "GribStubImagePlugin", 

365 ".h5": "Hdf5StubImagePlugin", 

366 ".hdf": "Hdf5StubImagePlugin", 

367 ".icns": "IcnsImagePlugin", 

368 ".ico": "IcoImagePlugin", 

369 ".im": "ImImagePlugin", 

370 ".iim": "IptcImagePlugin", 

371 ".jp2": "Jpeg2KImagePlugin", 

372 ".j2k": "Jpeg2KImagePlugin", 

373 ".jpc": "Jpeg2KImagePlugin", 

374 ".jpf": "Jpeg2KImagePlugin", 

375 ".jpx": "Jpeg2KImagePlugin", 

376 ".j2c": "Jpeg2KImagePlugin", 

377 ".mic": "MicImagePlugin", 

378 ".mpg": "MpegImagePlugin", 

379 ".mpeg": "MpegImagePlugin", 

380 ".mpo": "MpoImagePlugin", 

381 ".msp": "MspImagePlugin", 

382 ".palm": "PalmImagePlugin", 

383 ".pcd": "PcdImagePlugin", 

384 ".pcx": "PcxImagePlugin", 

385 ".pdf": "PdfImagePlugin", 

386 ".pxr": "PixarImagePlugin", 

387 ".psd": "PsdImagePlugin", 

388 ".qoi": "QoiImagePlugin", 

389 ".bw": "SgiImagePlugin", 

390 ".rgb": "SgiImagePlugin", 

391 ".rgba": "SgiImagePlugin", 

392 ".sgi": "SgiImagePlugin", 

393 ".ras": "SunImagePlugin", 

394 ".tga": "TgaImagePlugin", 

395 ".icb": "TgaImagePlugin", 

396 ".vda": "TgaImagePlugin", 

397 ".vst": "TgaImagePlugin", 

398 ".tif": "TiffImagePlugin", 

399 ".tiff": "TiffImagePlugin", 

400 ".webp": "WebPImagePlugin", 

401 ".wmf": "WmfImagePlugin", 

402 ".emf": "WmfImagePlugin", 

403 ".xbm": "XbmImagePlugin", 

404 ".xpm": "XpmImagePlugin", 

405} 

406 

407 

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

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

410 if not ext: 

411 return False 

412 

413 if isinstance(ext, bytes): 

414 ext = ext.decode() 

415 ext = ext.lower() 

416 if ext in EXTENSION: 

417 return True 

418 

419 plugin = _EXTENSION_PLUGIN.get(ext) 

420 if plugin is None: 

421 return False 

422 

423 try: 

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

425 return True 

426 except ImportError: 

427 return False 

428 

429 

430def preinit() -> None: 

431 """ 

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

433 

434 It is called when opening or saving images. 

435 """ 

436 

437 global _initialized 

438 if _initialized >= 1: 

439 return 

440 

441 try: 

442 from . import BmpImagePlugin 

443 

444 assert BmpImagePlugin 

445 except ImportError: 

446 pass 

447 try: 

448 from . import GifImagePlugin 

449 

450 assert GifImagePlugin 

451 except ImportError: 

452 pass 

453 try: 

454 from . import JpegImagePlugin 

455 

456 assert JpegImagePlugin 

457 except ImportError: 

458 pass 

459 try: 

460 from . import PpmImagePlugin 

461 

462 assert PpmImagePlugin 

463 except ImportError: 

464 pass 

465 try: 

466 from . import PngImagePlugin 

467 

468 assert PngImagePlugin 

469 except ImportError: 

470 pass 

471 

472 _initialized = 1 

473 

474 

475def init() -> bool: 

476 """ 

477 Explicitly initializes the Python Imaging Library. This function 

478 loads all available file format drivers. 

479 

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

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

482 """ 

483 

484 global _initialized 

485 if _initialized >= 2: 

486 return False 

487 

488 for plugin in _plugins: 

489 try: 

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

491 except ImportError: 

492 pass 

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 def _copy_info(self) -> dict[str | tuple[int, int], Any]: 

671 return {k: v.copy() if isinstance(v, list) else v for k, v in self.info.items()} 

672 

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

674 new = Image() 

675 new.im = im 

676 new.readonly = im.readonly 

677 new._mode = im.mode 

678 new._size = im.size 

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

680 if self.palette: 

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

682 new.palette.dirty = 1 

683 else: 

684 from . import ImagePalette 

685 

686 new.palette = ImagePalette.ImagePalette() 

687 new.info = self._copy_info() 

688 return new 

689 

690 # Context manager support 

691 def __enter__(self) -> Self: 

692 return self 

693 

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

695 pass 

696 

697 def close(self) -> None: 

698 """ 

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

700 The image data will be unusable afterward. 

701 

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

703 have not had their file read and closed by the 

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

705 more information. 

706 """ 

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

708 if sys.platform == "win32" and sys.implementation.name == "pypy": 

709 self.map.close() 

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

711 

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

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

714 # object is gone. 

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

716 

717 def _copy(self) -> None: 

718 self.im = self.im.copy() 

719 self.readonly = 0 

720 

721 def _ensure_mutable(self) -> None: 

722 self.load() 

723 if self.readonly: 

724 self._copy() 

725 

726 def _dump( 

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

728 ) -> str: 

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

730 

731 if file: 

732 filename = file 

733 if not filename.endswith(suffix): 

734 filename += suffix 

735 else: 

736 import tempfile 

737 

738 f, filename = tempfile.mkstemp(suffix) 

739 os.close(f) 

740 

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

742 

743 return filename 

744 

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

746 if self.__class__ is not other.__class__: 

747 return False 

748 assert isinstance(other, Image) 

749 return ( 

750 self.mode == other.mode 

751 and self.size == other.size 

752 and self.info == other.info 

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

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

755 ) 

756 

757 def __repr__(self) -> str: 

758 return ( 

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

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

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

762 ) 

763 

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

765 """IPython plain text display support""" 

766 

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

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

769 p.text( 

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

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

772 ) 

773 

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

775 """Helper function for iPython display hook. 

776 

777 :param image_format: Image format. 

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

779 """ 

780 b = io.BytesIO() 

781 try: 

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

783 except Exception: 

784 return None 

785 return b.getvalue() 

786 

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

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

789 

790 :returns: PNG version of the image as bytes 

791 """ 

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

793 

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

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

796 

797 :returns: JPEG version of the image as bytes 

798 """ 

799 return self._repr_image("JPEG") 

800 

801 @property 

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

803 # numpy array interface support 

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

805 if self.mode == "1": 

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

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

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

809 else: 

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

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

812 return new 

813 

814 def __arrow_c_schema__(self) -> object: 

815 self.load() 

816 return self.im.__arrow_c_schema__() 

817 

818 def __arrow_c_array__( 

819 self, requested_schema: object | None = None 

820 ) -> tuple[object, object]: 

821 self.load() 

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

823 

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

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

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

827 

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

829 Image.__init__(self) 

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

831 self.info = info 

832 self._mode = mode 

833 self._size = size 

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

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

836 self.putpalette(palette) 

837 self.frombytes(data) 

838 

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

840 """ 

841 Return image as a bytes object. 

842 

843 .. warning:: 

844 

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

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

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

848 

849 :param encoder_name: What encoder to use. 

850 

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

852 To see how this packs pixel data into the returned 

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

854 

855 A list of C encoders can be seen under codecs 

856 section of the function array in 

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

858 within the relevant plugins. 

859 :param args: Extra arguments to the encoder. 

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

861 """ 

862 

863 encoder_args: Any = args 

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

865 # may pass tuple instead of argument list 

866 encoder_args = encoder_args[0] 

867 

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

869 encoder_args = self.mode 

870 

871 self.load() 

872 

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

874 return b"" 

875 

876 # unpack data 

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

878 try: 

879 e.setimage(self.im) 

880 

881 from . import ImageFile 

882 

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

884 

885 output = [] 

886 while True: 

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

888 output.append(data) 

889 if errcode: 

890 break 

891 if errcode < 0: 

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

893 raise RuntimeError(msg) 

894 finally: 

895 e.cleanup() 

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: DecoderInput, 

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 if self._im is None: 

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

954 # Plugins may call this from load() while ImageFile.readonly is still set, 

955 # so check whether the image memory itself is read-only 

956 elif self.im.readonly: 

957 self._copy() 

958 d.setimage(self.im) 

959 s = d.decode(data) 

960 

961 if s[0] >= 0: 

962 msg = "not enough image data" 

963 raise ValueError(msg) 

964 if s[1] != 0: 

965 msg = "cannot decode image data" 

966 raise ValueError(msg) 

967 

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

969 """ 

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

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

972 Image class automatically loads an opened image when it is 

973 accessed for the first time. 

974 

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

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

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

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

979 

980 :returns: An image access object. 

981 """ 

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

983 # realize palette 

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

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

986 self.palette.dirty = 0 

987 self.palette.rawmode = None 

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

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

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

991 else: 

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

993 self.palette.mode = "RGBA" 

994 elif self.palette.mode != mode: 

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

996 # then update the Python palette data 

997 self.palette.palette = self.im.getpalette(self.palette.mode) 

998 

999 if self._im is not None: 

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

1001 return None 

1002 

1003 def verify(self) -> None: 

1004 """ 

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

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

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

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

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

1010 file. 

1011 """ 

1012 pass 

1013 

1014 def convert( 

1015 self, 

1016 mode: str | None = None, 

1017 matrix: list[float] | tuple[float, ...] | None = None, 

1018 dither: Dither | None = None, 

1019 palette: Palette = Palette.WEB, 

1020 colors: int = 256, 

1021 ) -> Image: 

1022 """ 

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

1024 method translates pixels through the palette. If mode is 

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

1026 and the palette can be represented without a palette. 

1027 

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

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

1030 

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

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

1033 

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

1035 

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

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

1038 dither to approximate the original image luminosity levels. If 

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

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

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

1042 

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

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

1045 and ``dither`` and ``palette`` are ignored. 

1046 

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

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

1049 

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

1051 :param matrix: An optional conversion matrix containing floating point values. 

1052 When converting to L mode, the sequence should have length 4. For RGB, it 

1053 should have length 12. 

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

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

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

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

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

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

1060 :data:`Palette.ADAPTIVE`. 

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

1062 palette. Defaults to 256. 

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

1064 """ 

1065 

1066 self.load() 

1067 

1068 has_transparency = "transparency" in self.info 

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

1070 # determine default mode 

1071 if self.palette: 

1072 mode = self.palette.mode 

1073 else: 

1074 mode = "RGB" 

1075 if mode == "RGB" and has_transparency: 

1076 mode = "RGBA" 

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

1078 return self.copy() 

1079 

1080 if matrix: 

1081 # matrix conversion 

1082 try: 

1083 matrix_length = {"L": 4, "RGB": 12}[mode] 

1084 except KeyError: 

1085 msg = "illegal conversion" 

1086 raise ValueError(msg) 

1087 if matrix_length != len(matrix): 

1088 msg = f"matrix must have length {matrix_length} for mode {mode}" 

1089 raise TypeError(msg) 

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

1091 new_im = self._new(im) 

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

1093 transparency = new_im.info["transparency"] 

1094 

1095 def convert_transparency( 

1096 m: list[float] | tuple[float, ...], v: tuple[int, int, int] 

1097 ) -> int: 

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

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

1100 

1101 if mode == "L": 

1102 transparency = convert_transparency(matrix, transparency) 

1103 elif len(mode) == 3: 

1104 transparency = tuple( 

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

1106 for i in range(len(transparency)) 

1107 ) 

1108 new_im.info["transparency"] = transparency 

1109 return new_im 

1110 

1111 if self.mode == "RGBA": 

1112 if mode == "P": 

1113 return self.quantize(colors) 

1114 elif mode == "PA": 

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

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

1117 p = rgb.quantize(colors) 

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

1119 

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

1121 im = self 

1122 if mode == "LAB": 

1123 if im.mode not in {"RGB", "RGBA", "RGBX"}: 

1124 im = im.convert("RGBA") 

1125 other_mode = im.mode 

1126 else: 

1127 other_mode = mode 

1128 if other_mode in {"RGB", "RGBA", "RGBX"}: 

1129 from . import ImageCms 

1130 

1131 srgb = ImageCms.createProfile("sRGB") 

1132 lab = ImageCms.createProfile("LAB") 

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

1134 transform = ImageCms.buildTransform( 

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

1136 ) 

1137 return transform.apply(im) 

1138 

1139 im = self.im 

1140 

1141 trns = None 

1142 delete_trns = False 

1143 # transparency handling 

1144 if has_transparency: 

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

1146 self.mode == "RGB" and mode in {"La", "LA", "RGBa", "RGBA"} 

1147 ): 

1148 # Use transparent conversion to promote from transparent 

1149 # color to an alpha channel. 

1150 new_im = self._new( 

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

1152 ) 

1153 del new_im.info["transparency"] 

1154 return new_im 

1155 elif self.mode in {"1", "L", "I", "I;16", "RGB", "P"} and ( 

1156 mode in {"L", "RGB", "P"} 

1157 ): 

1158 t = self.info["transparency"] 

1159 if isinstance(t, bytes): 

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

1161 warnings.warn( 

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

1163 "converted to RGBA images" 

1164 ) 

1165 delete_trns = True 

1166 else: 

1167 # get the new transparency color. 

1168 # use existing conversions 

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

1170 if self.mode == "P": 

1171 assert self.palette is not None 

1172 trns_im.putpalette(self.palette) 

1173 if isinstance(t, tuple): 

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

1175 assert trns_im.palette is not None 

1176 try: 

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

1178 except ValueError as e: 

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

1180 # If all 256 colors are in use, 

1181 # then there is no need for transparency 

1182 t = None 

1183 else: 

1184 raise ValueError(err) from e 

1185 if t is None: 

1186 trns = None 

1187 else: 

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

1189 

1190 if mode in {"L", "RGB"}: 

1191 trns_im = trns_im.convert(mode) 

1192 else: 

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

1194 # after quantization. 

1195 trns_im = trns_im.convert("RGB") 

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

1197 

1198 elif self.mode == "P" and mode in {"LA", "PA", "RGBA"}: 

1199 t = self.info["transparency"] 

1200 delete_trns = True 

1201 

1202 if isinstance(t, bytes): 

1203 im = im.copy() 

1204 im.putpalettealphas(t) 

1205 elif isinstance(t, int): 

1206 im = im.copy() 

1207 im.putpalettealpha(t, 0) 

1208 else: 

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

1210 raise ValueError(msg) 

1211 elif self.mode in {"1", "L", "I", "I;16", "RGB"} and mode == "PA": 

1212 im_without_trns = self.copy() 

1213 del im_without_trns.info["transparency"] 

1214 new_im = im_without_trns.convert(mode, dither=dither) 

1215 new_im.putalpha(self.convert("RGBA").getchannel("A")) 

1216 return new_im 

1217 

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

1219 im = self.im.quantize(colors) 

1220 new_im = self._new(im) 

1221 from . import ImagePalette 

1222 

1223 new_im.palette = ImagePalette.ImagePalette( 

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

1225 ) 

1226 if delete_trns: 

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

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

1229 del new_im.info["transparency"] 

1230 if trns is not None: 

1231 try: 

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

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

1234 new_im, 

1235 ) 

1236 except Exception: 

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

1238 # transparency hanging around to mess us up. 

1239 del new_im.info["transparency"] 

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

1241 return new_im 

1242 

1243 # colorspace conversion 

1244 if dither is None: 

1245 dither = Dither.FLOYDSTEINBERG 

1246 

1247 try: 

1248 im = im.convert(mode, dither) 

1249 except ValueError: 

1250 try: 

1251 # normalize source image and try again 

1252 modebase = getmodebase(self.mode) 

1253 if modebase == self.mode: 

1254 raise 

1255 im = im.convert(modebase) 

1256 im = im.convert(mode, dither) 

1257 except KeyError as e: 

1258 msg = "illegal conversion" 

1259 raise ValueError(msg) from e 

1260 

1261 new_im = self._new(im) 

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

1263 from . import ImagePalette 

1264 

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

1266 if delete_trns: 

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

1268 del new_im.info["transparency"] 

1269 if trns is not None: 

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

1271 try: 

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

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

1274 new_im, 

1275 ) 

1276 except ValueError as e: 

1277 del new_im.info["transparency"] 

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

1279 # If all 256 colors are in use, 

1280 # then there is no need for transparency 

1281 warnings.warn( 

1282 "Couldn't allocate palette entry for transparency" 

1283 ) 

1284 else: 

1285 new_im.info["transparency"] = trns 

1286 return new_im 

1287 

1288 def quantize( 

1289 self, 

1290 colors: int = 256, 

1291 method: int | None = None, 

1292 kmeans: int = 0, 

1293 palette: Image | None = None, 

1294 dither: Dither = Dither.FLOYDSTEINBERG, 

1295 ) -> Image: 

1296 """ 

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

1298 of colors. 

1299 

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

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

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

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

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

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

1306 ``feature="libimagequant"``). 

1307 

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

1309 

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

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

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

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

1314 :param palette: Quantize to the palette of given 

1315 :py:class:`PIL.Image.Image`. 

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

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

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

1319 (default). 

1320 :returns: A new image 

1321 """ 

1322 

1323 self.load() 

1324 

1325 if method is None: 

1326 # defaults: 

1327 method = Quantize.MEDIANCUT 

1328 if self.mode == "RGBA": 

1329 method = Quantize.FASTOCTREE 

1330 

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

1332 Quantize.FASTOCTREE, 

1333 Quantize.LIBIMAGEQUANT, 

1334 ): 

1335 # Caller specified an invalid mode. 

1336 msg = ( 

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

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

1339 ) 

1340 raise ValueError(msg) 

1341 

1342 if palette: 

1343 # use palette from reference image 

1344 palette.load() 

1345 if palette.mode != "P": 

1346 msg = "bad mode for palette image" 

1347 raise ValueError(msg) 

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

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

1350 raise ValueError(msg) 

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

1352 new_im = self._new(im) 

1353 assert palette.palette is not None 

1354 new_im.palette = palette.palette.copy() 

1355 return new_im 

1356 

1357 if kmeans < 0: 

1358 msg = "kmeans must not be negative" 

1359 raise ValueError(msg) 

1360 

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

1362 

1363 from . import ImagePalette 

1364 

1365 mode = im.im.getpalettemode() 

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

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

1368 

1369 return im 

1370 

1371 def copy(self) -> Image: 

1372 """ 

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

1374 into an image, but still retain the original. 

1375 

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

1377 """ 

1378 self.load() 

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

1380 

1381 __copy__ = copy 

1382 

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

1384 """ 

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

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

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

1388 

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

1390 

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

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

1393 """ 

1394 

1395 if box is None: 

1396 box = (0, 0, *self.size) 

1397 if box[2] - box[0] == 0 or box[3] - box[1] == 0: 

1398 return self._new(core.new(self.mode, (box[2] - box[0], box[3] - box[1]))) 

1399 if box == (0, 0, *self.size): 

1400 return self.copy() 

1401 

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

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

1404 raise ValueError(msg) 

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

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

1407 raise ValueError(msg) 

1408 

1409 self.load() 

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

1411 

1412 def _crop( 

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

1414 ) -> core.ImagingCore: 

1415 """ 

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

1417 

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

1419 includes additional sanity checks. 

1420 

1421 :param im: a core image object 

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

1423 :returns: A core image object. 

1424 """ 

1425 

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

1427 

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

1429 

1430 _decompression_bomb_check(absolute_values) 

1431 

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

1433 

1434 def draft( 

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

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

1437 """ 

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

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

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

1441 JPEG to grayscale while loading it. 

1442 

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

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

1445 

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

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

1448 effect. 

1449 

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

1451 currently implemented only for JPEG and MPO images. 

1452 

1453 :param mode: The requested mode. 

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

1455 (width, height). 

1456 """ 

1457 pass 

1458 

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

1460 """ 

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

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

1463 

1464 :param filter: Filter kernel. 

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

1466 

1467 from . import ImageFilter 

1468 

1469 self.load() 

1470 

1471 if callable(filter): 

1472 filter = filter() 

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

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

1475 raise TypeError(msg) 

1476 

1477 multiband = isinstance(filter, ImageFilter.MultibandFilter) 

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

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

1480 

1481 ims = [ 

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

1483 ] 

1484 return merge(self.mode, ims) 

1485 

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

1487 """ 

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

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

1490 

1491 :returns: A tuple containing band names. 

1492 """ 

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

1494 

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

1496 """ 

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

1498 image. 

1499 

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

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

1502 Otherwise, trim pixels when all channels are zero. 

1503 Keyword-only argument. 

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

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

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

1507 method returns None. 

1508 

1509 """ 

1510 

1511 self.load() 

1512 return self.im.getbbox(alpha_only) 

1513 

1514 def getcolors( 

1515 self, maxcolors: int = 256 

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

1517 """ 

1518 Returns a list of colors used in this image. 

1519 

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

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

1522 return the index of the color in the palette. 

1523 

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

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

1526 256 colors. 

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

1528 """ 

1529 if maxcolors < 0: 

1530 return None 

1531 

1532 self.load() 

1533 if self.mode in {"1", "L", "P"}: 

1534 h = self.im.histogram() 

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

1536 if len(out) > maxcolors: 

1537 return None 

1538 return out 

1539 return self.im.getcolors(maxcolors) 

1540 

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

1542 """ 

1543 Returns the contents of this image as a sequence object 

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

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

1546 line zero, and so on. 

1547 

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

1549 internal PIL data type, which only supports certain sequence 

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

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

1552 

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

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

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

1556 :returns: A sequence-like object. 

1557 """ 

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

1559 

1560 self.load() 

1561 if band is not None: 

1562 return self.im.getband(band) 

1563 return self.im # could be abused 

1564 

1565 def get_flattened_data( 

1566 self, band: int | None = None 

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

1568 """ 

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

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

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

1572 

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

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

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

1576 :returns: A tuple containing pixel values. 

1577 """ 

1578 self.load() 

1579 if band is not None: 

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

1581 return tuple(self.im) 

1582 

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

1584 """ 

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

1586 the image. 

1587 

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

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

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

1591 """ 

1592 

1593 self.load() 

1594 return self.im.getextrema() 

1595 

1596 def getxmp(self, *, strip_namespaces: bool = True) -> dict[str, Any]: 

1597 """ 

1598 Returns a dictionary containing the XMP tags. 

1599 Requires defusedxml to be installed. 

1600 

1601 :param strip_namespaces: If ``False``, keep each tag's full 

1602 ``{namespace-uri}local-name`` form instead of stripping the namespace 

1603 prefix. 

1604 

1605 .. versionadded:: 13.0.0 

1606 

1607 :returns: XMP tags in a dictionary. 

1608 """ 

1609 try: 

1610 from defusedxml import ElementTree 

1611 except ImportError: 

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

1613 return {} 

1614 

1615 if strip_namespaces: 

1616 

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

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

1619 

1620 else: 

1621 

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

1623 return tag 

1624 

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

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

1627 children = list(element) 

1628 if children: 

1629 for child in children: 

1630 name = get_name(child.tag) 

1631 child_value = get_value(child) 

1632 if name in value: 

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

1634 value[name] = [value[name]] 

1635 value[name].append(child_value) 

1636 else: 

1637 value[name] = child_value 

1638 elif value: 

1639 if element.text: 

1640 value["text"] = element.text 

1641 else: 

1642 return element.text 

1643 return value 

1644 

1645 if "xmp" not in self.info: 

1646 return {} 

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

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

1649 

1650 def getexif(self) -> Exif: 

1651 """ 

1652 Gets EXIF data from the image. 

1653 

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

1655 """ 

1656 if self._exif is None: 

1657 self._exif = Exif() 

1658 elif self._exif._loaded: 

1659 return self._exif 

1660 self._exif._loaded = True 

1661 

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

1663 if exif_info is None: 

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

1665 exif_info = bytes.fromhex( 

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

1667 ) 

1668 elif hasattr(self, "tag_v2"): 

1669 from . import TiffImagePlugin 

1670 

1671 assert isinstance(self, TiffImagePlugin.TiffImageFile) 

1672 self._exif.bigtiff = self.tag_v2._bigtiff 

1673 self._exif.endian = self.tag_v2._endian 

1674 

1675 assert self.fp is not None 

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

1677 if exif_info is not None: 

1678 self._exif.load(exif_info) 

1679 

1680 # XMP tags 

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

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

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

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

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

1686 if xmp_tags: 

1687 match = re.search(pattern, xmp_tags) 

1688 if match: 

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

1690 

1691 return self._exif 

1692 

1693 def _reload_exif(self) -> None: 

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

1695 return 

1696 self._exif._loaded = False 

1697 self.getexif() 

1698 

1699 def getim(self) -> CapsuleType: 

1700 """ 

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

1702 

1703 :returns: A capsule object. 

1704 """ 

1705 

1706 self.load() 

1707 return self.im.ptr 

1708 

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

1710 """ 

1711 Returns the image palette as a list. 

1712 

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

1714 return the palette in its current mode. 

1715 

1716 .. versionadded:: 9.1.0 

1717 

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

1719 image has no palette. 

1720 """ 

1721 

1722 self.load() 

1723 try: 

1724 palette = ( 

1725 self.im.getpalette(rawmode) 

1726 if rawmode is not None 

1727 else self.im.getpalette() 

1728 ) 

1729 except ValueError: 

1730 return None # no palette 

1731 return list(palette) 

1732 

1733 @property 

1734 def has_transparency_data(self) -> bool: 

1735 """ 

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

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

1738 in the info dictionary. 

1739 

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

1741 within are opaque. 

1742 

1743 :returns: A boolean. 

1744 """ 

1745 if ( 

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

1747 or "transparency" in self.info 

1748 ): 

1749 return True 

1750 if self.mode == "P": 

1751 assert self.palette is not None 

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

1753 return False 

1754 

1755 def apply_transparency(self) -> None: 

1756 """ 

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

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

1759 Otherwise, the image is unchanged. 

1760 """ 

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

1762 return 

1763 

1764 from . import ImagePalette 

1765 

1766 palette = self.getpalette("RGBA") 

1767 assert palette is not None 

1768 transparency = self.info["transparency"] 

1769 if isinstance(transparency, bytes): 

1770 for i, alpha in enumerate(transparency): 

1771 palette[i * 4 + 3] = alpha 

1772 else: 

1773 palette[transparency * 4 + 3] = 0 

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

1775 self.palette.dirty = 1 

1776 

1777 del self.info["transparency"] 

1778 

1779 def getpixel( 

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

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

1782 """ 

1783 Returns the pixel value at a given position. 

1784 

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

1786 :ref:`coordinate-system`. 

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

1788 this method returns a tuple. 

1789 """ 

1790 

1791 self.load() 

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

1793 

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

1795 """ 

1796 Get projection to x and y axes 

1797 

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

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

1800 """ 

1801 

1802 self.load() 

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

1804 return list(x), list(y) 

1805 

1806 def histogram( 

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

1808 ) -> list[int]: 

1809 """ 

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

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

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

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

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

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

1816 

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

1818 by this method. 

1819 

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

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

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

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

1824 

1825 :param mask: An optional mask. 

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

1827 :returns: A list containing pixel counts. 

1828 """ 

1829 if min(self.size) == 0: 

1830 return [0] * 256 * getmodebands(self.mode) 

1831 

1832 self.load() 

1833 if mask: 

1834 mask.load() 

1835 return self.im.histogram(None, mask.im) 

1836 if self.mode in ("I", "I;16", "I;16L", "I;16B", "I;16N", "F"): 

1837 return self.im.histogram( 

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

1839 ) 

1840 return self.im.histogram() 

1841 

1842 def entropy( 

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

1844 ) -> float: 

1845 """ 

1846 Calculates and returns the entropy for the image. 

1847 

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

1849 image by this method. 

1850 

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

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

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

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

1855 

1856 :param mask: An optional mask. 

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

1858 :returns: A float value representing the image entropy 

1859 """ 

1860 if min(self.size) == 0: 

1861 return 0.0 

1862 

1863 self.load() 

1864 if mask: 

1865 mask.load() 

1866 return self.im.entropy(None, mask.im) 

1867 if self.mode in ("I", "I;16", "I;16L", "I;16B", "I;16N", "F"): 

1868 return self.im.entropy( 

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

1870 ) 

1871 return self.im.entropy() 

1872 

1873 def paste( 

1874 self, 

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

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

1877 mask: Image | None = None, 

1878 ) -> None: 

1879 """ 

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

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

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

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

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

1885 

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

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

1888 details). 

1889 

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

1891 containing pixel values. The method then fills the region 

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

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

1894 :ref:`colors` for more information. 

1895 

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

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

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

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

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

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

1902 channels if they have them. 

1903 

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

1905 combine images with respect to their alpha channels. 

1906 

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

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

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

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

1911 upper left corner. 

1912 

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

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

1915 is interpreted as a mask image. 

1916 :param mask: An optional mask image. 

1917 """ 

1918 

1919 if isinstance(box, Image): 

1920 if mask is not None: 

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

1922 raise ValueError(msg) 

1923 # abbreviated paste(im, mask) syntax 

1924 mask = box 

1925 box = None 

1926 

1927 if box is None: 

1928 box = (0, 0) 

1929 

1930 if len(box) == 2: 

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

1932 if isinstance(im, Image): 

1933 size = im.size 

1934 elif isinstance(mask, Image): 

1935 size = mask.size 

1936 else: 

1937 # FIXME: use self.size here? 

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

1939 raise ValueError(msg) 

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

1941 

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

1943 if isinstance(im, str): 

1944 from . import ImageColor 

1945 

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

1947 elif isinstance(im, Image): 

1948 if self.mode != im.mode and ( 

1949 self.mode != "RGB" or im.mode not in {"LA", "RGBA", "RGBa"} 

1950 ): 

1951 # should use an adapter for this! 

1952 im = im.convert(self.mode) 

1953 else: 

1954 im.load() 

1955 source = im.im 

1956 else: 

1957 source = im 

1958 

1959 self._ensure_mutable() 

1960 

1961 if mask: 

1962 mask.load() 

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

1964 else: 

1965 self.im.paste(source, box) 

1966 

1967 def alpha_composite( 

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

1969 ) -> None: 

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

1971 onto this image. 

1972 

1973 :param im: image to composite over this one 

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

1975 left corner in this (destination) image. 

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

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

1978 bottom) for the bounds of the source rectangle 

1979 

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

1981 """ 

1982 

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

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

1985 raise ValueError(msg) 

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

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

1988 raise ValueError(msg) 

1989 

1990 if len(source) == 4: 

1991 overlay_crop_box = tuple(source) 

1992 elif len(source) == 2: 

1993 overlay_crop_box = tuple(source) + im.size 

1994 else: 

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

1996 raise ValueError(msg) 

1997 

1998 if not len(dest) == 2: 

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

2000 raise ValueError(msg) 

2001 if min(source) < 0: 

2002 msg = "Source must be non-negative" 

2003 raise ValueError(msg) 

2004 

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

2006 if overlay_crop_box == (0, 0, *im.size): 

2007 overlay = im 

2008 else: 

2009 overlay = im.crop(overlay_crop_box) 

2010 

2011 # target for the paste 

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

2013 

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

2015 if box == (0, 0, *self.size): 

2016 background = self 

2017 else: 

2018 background = self.crop(box) 

2019 

2020 result = alpha_composite(background, overlay) 

2021 self.paste(result, box) 

2022 

2023 def point( 

2024 self, 

2025 lut: ( 

2026 Sequence[float] 

2027 | NumpyArray 

2028 | Callable[[int], float] 

2029 | Callable[[ImagePointTransform], ImagePointTransform | float] 

2030 | ImagePointHandler 

2031 ), 

2032 mode: str | None = None, 

2033 ) -> Image: 

2034 """ 

2035 Maps this image through a lookup table or function. 

2036 

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

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

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

2040 single argument. The function is called once for each 

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

2042 all bands of the image. 

2043 

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

2045 object:: 

2046 

2047 class Example(Image.ImagePointHandler): 

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

2049 # Return result 

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

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

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

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

2054 """ 

2055 

2056 self.load() 

2057 

2058 if isinstance(lut, ImagePointHandler): 

2059 return lut.point(self) 

2060 

2061 if callable(lut): 

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

2063 if self.mode in ("I", "I;16", "I;16L", "I;16B", "I;16N", "F"): 

2064 # check if the function can be used with point_transform 

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

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

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

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

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

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

2071 else: 

2072 flatLut = lut 

2073 

2074 if self.mode == "F": 

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

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

2077 raise ValueError(msg) 

2078 

2079 if mode != "F": 

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

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

2082 

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

2084 """ 

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

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

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

2088 

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

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

2091 """ 

2092 

2093 self._ensure_mutable() 

2094 

2095 if self.mode in ("RGB", "RGBX"): 

2096 # promote self to RGBA 

2097 self.im.setalpha() 

2098 self._mode = "RGBA" 

2099 elif self.mode not in ("LA", "PA", "RGBA"): 

2100 try: 

2101 # do things the hard way 

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

2103 im = self.im.convert(mode) 

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

2105 msg = "alpha channel could not be added" 

2106 raise ValueError(msg) # sanity check 

2107 self.im = im 

2108 self._mode = self.im.mode 

2109 except KeyError as e: 

2110 msg = "illegal image mode" 

2111 raise ValueError(msg) from e 

2112 

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

2114 band = 1 

2115 else: 

2116 band = 3 

2117 

2118 if isinstance(alpha, Image): 

2119 # alpha layer 

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

2121 msg = "illegal image mode" 

2122 raise ValueError(msg) 

2123 alpha.load() 

2124 if alpha.mode == "1": 

2125 alpha = alpha.convert("L") 

2126 else: 

2127 # constant alpha 

2128 try: 

2129 self.im.fillband(band, alpha) 

2130 except (AttributeError, ValueError): 

2131 # do things the hard way 

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

2133 else: 

2134 return 

2135 

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

2137 

2138 def putdata( 

2139 self, 

2140 data: Sequence[float] | Sequence[Sequence[int]] | NumpyArray, 

2141 scale: float = 1.0, 

2142 offset: float = 0.0, 

2143 ) -> None: 

2144 """ 

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

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

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

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

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

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

2151 

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

2153 information about values. 

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

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

2156 """ 

2157 

2158 self._ensure_mutable() 

2159 

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

2161 

2162 def putpalette( 

2163 self, 

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

2165 rawmode: str = "RGB", 

2166 ) -> None: 

2167 """ 

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

2169 or "LA" image. 

2170 

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

2172 integer value for each channel in the raw mode. 

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

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

2175 index in the 256 colors. 

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

2177 containing red, green, blue and alpha values. 

2178 

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

2180 

2181 :param data: A palette sequence (either a list or a string) or an ImagePalette. 

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

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

2184 Ignored if ``data`` is an ImagePalette. 

2185 """ 

2186 from . import ImagePalette 

2187 

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

2189 msg = "illegal image mode" 

2190 raise ValueError(msg) 

2191 if isinstance(data, ImagePalette.ImagePalette): 

2192 palette = data.copy() 

2193 palette.dirty = 1 

2194 else: 

2195 palette = ImagePalette.raw(rawmode, data) 

2196 if rawmode.startswith("CMYK"): 

2197 palette.mode = "CMYK" 

2198 elif "A" in rawmode: 

2199 palette.mode = "RGBA" 

2200 if palette.mode == palette.rawmode: 

2201 palette.rawmode = None 

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

2203 self.palette = palette 

2204 if self.palette.rawmode or ( 

2205 self._im is not None and self._im.mode != self.mode 

2206 ): 

2207 # either raw palette data needs to be decoded, 

2208 # or the core image needs its mode updated 

2209 self.load() 

2210 

2211 def _get_palette_color(self, value: tuple[int, ...]) -> tuple[int, ...] | int: 

2212 if len(value) in {3, 4}: 

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

2214 if self.mode == "PA": 

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

2216 value = value[:3] 

2217 assert self.palette is not None 

2218 palette_index = self.palette.getcolor(value, self) 

2219 return (palette_index, alpha) if self.mode == "PA" else palette_index 

2220 return value 

2221 

2222 def putpixel( 

2223 self, 

2224 xy: tuple[int, int] | list[int], 

2225 value: float | tuple[int, ...], 

2226 ) -> None: 

2227 """ 

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

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

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

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

2232 

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

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

2235 module instead. 

2236 

2237 See: 

2238 

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

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

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

2242 

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

2244 :ref:`coordinate-system`. 

2245 :param value: The pixel value. 

2246 """ 

2247 

2248 self._ensure_mutable() 

2249 

2250 if self.mode in {"P", "PA"}: 

2251 if isinstance(value, list) and len(value) in {3, 4}: # type: ignore[unreachable] 

2252 deprecate("'value' lists", 15, "tuples", plural=True) # type: ignore[unreachable] 

2253 

2254 value = tuple(value) 

2255 if isinstance(value, tuple): 

2256 value = self._get_palette_color(value) 

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

2258 

2259 def remap_palette( 

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

2261 ) -> Image: 

2262 """ 

2263 Rewrites the image to reorder the palette. 

2264 

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

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

2267 is the identity transform. 

2268 :param source_palette: Bytes or None. 

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

2270 

2271 """ 

2272 from . import ImagePalette 

2273 

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

2275 msg = "illegal image mode" 

2276 raise ValueError(msg) 

2277 

2278 bands = 3 

2279 palette_mode = "RGB" 

2280 if source_palette is None: 

2281 if self.mode == "P": 

2282 self.load() 

2283 palette_mode = self.im.getpalettemode() 

2284 if palette_mode == "RGBA": 

2285 bands = 4 

2286 source_palette = self.im.getpalette() 

2287 else: # L-mode 

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

2289 elif len(source_palette) > 768: 

2290 bands = 4 

2291 palette_mode = "RGBA" 

2292 

2293 palette_bytes = b"" 

2294 new_positions = [0] * 256 

2295 

2296 # pick only the used colors from the palette 

2297 for i, oldPosition in enumerate(dest_map): 

2298 palette_bytes += source_palette[ 

2299 oldPosition * bands : oldPosition * bands + bands 

2300 ] 

2301 new_positions[oldPosition] = i 

2302 

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

2304 

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

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

2307 # from palette 1 to palette 2. New_positions is 

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

2309 # palette 1 with any holes removed. 

2310 

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

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

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

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

2315 # sans palette thus converting the image bytes, then 

2316 # assigning the optimized RGB palette. 

2317 

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

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

2320 

2321 mapping_palette = bytearray(new_positions) 

2322 

2323 m_im = self.copy() 

2324 m_im._mode = "P" 

2325 

2326 m_im.palette = ImagePalette.ImagePalette( 

2327 palette_mode, palette=mapping_palette * bands 

2328 ) 

2329 # possibly set palette dirty, then 

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

2331 # or just force it. 

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

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

2334 

2335 m_im = m_im.convert("L") 

2336 

2337 m_im.putpalette(palette_bytes, palette_mode) 

2338 

2339 if "transparency" in self.info: 

2340 try: 

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

2342 except ValueError: 

2343 if "transparency" in m_im.info: 

2344 del m_im.info["transparency"] 

2345 

2346 return m_im 

2347 

2348 def _get_safe_box( 

2349 self, 

2350 size: tuple[int, int], 

2351 resample: Resampling, 

2352 box: tuple[float, float, float, float], 

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

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

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

2356 """ 

2357 filter_support = _filters_support[resample] - 0.5 

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

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

2360 support_x = filter_support * scale_x 

2361 support_y = filter_support * scale_y 

2362 

2363 return ( 

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

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

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

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

2368 ) 

2369 

2370 def resize( 

2371 self, 

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

2373 resample: int | None = None, 

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

2375 reducing_gap: float | None = None, 

2376 ) -> Image: 

2377 """ 

2378 Returns a resized copy of this image. 

2379 

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

2381 (width, height). 

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

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

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

2385 :py:data:`Resampling.BICUBIC`, :py:data:`Resampling.LANCZOS`, 

2386 :py:data:`Resampling.MKS2013`, or :py:data:`Resampling.MKS2021`. 

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

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

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

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

2391 the source image region to be scaled. 

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

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

2394 :param reducing_gap: Apply optimization by resizing the image 

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

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

2397 Second, resizing using regular resampling. The last step 

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

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

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

2401 the closer the result to the fair resampling. 

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

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

2404 indistinguishable from fair resampling in most cases. 

2405 The default value is None (no optimization). 

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

2407 """ 

2408 

2409 if resample is None: 

2410 resample = Resampling.BICUBIC 

2411 elif resample not in ( 

2412 Resampling.NEAREST, 

2413 Resampling.BILINEAR, 

2414 Resampling.BICUBIC, 

2415 Resampling.LANCZOS, 

2416 Resampling.BOX, 

2417 Resampling.HAMMING, 

2418 Resampling.MKS2013, 

2419 Resampling.MKS2021, 

2420 ): 

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

2422 

2423 filters = [ 

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

2425 for filter in ( 

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

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

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

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

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

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

2432 (Resampling.MKS2013, "Image.Resampling.MKS2013"), 

2433 (Resampling.MKS2021, "Image.Resampling.MKS2021"), 

2434 ) 

2435 ] 

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

2437 raise ValueError(msg) 

2438 

2439 if reducing_gap is not None and reducing_gap < 1.0: 

2440 msg = "reducing_gap must be 1.0 or greater" 

2441 raise ValueError(msg) 

2442 

2443 if box is None: 

2444 box = (0, 0, *self.size) 

2445 

2446 size = tuple(size) 

2447 if self.size == size and box == (0, 0, *self.size): 

2448 return self.copy() 

2449 

2450 if self.mode in {"1", "P", "PA"}: 

2451 resample = Resampling.NEAREST 

2452 

2453 if self.mode in {"LA", "RGBA"} and resample != Resampling.NEAREST: 

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

2455 im = im.resize(size, resample, box, reducing_gap) 

2456 return im.convert(self.mode) 

2457 

2458 self.load() 

2459 

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

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

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

2463 if factor_x > 1 or factor_y > 1: 

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

2465 factor = (factor_x, factor_y) 

2466 self = ( 

2467 self.reduce(factor, box=reduce_box) 

2468 if callable(self.reduce) 

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

2470 ) 

2471 box = ( 

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

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

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

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

2476 ) 

2477 

2478 return self._new(self.im.resize(size, resample, box)) 

2479 

2480 def reduce( 

2481 self, 

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

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

2484 ) -> Image: 

2485 """ 

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

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

2488 the resulting size will be rounded up. 

2489 

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

2491 for width and height separately. 

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

2493 the source image region to be reduced. 

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

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

2496 """ 

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

2498 factor = (factor, factor) 

2499 

2500 if factor == (1, 1): 

2501 return self.crop(box) 

2502 

2503 if box is None: 

2504 box = (0, 0, *self.size) 

2505 

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

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

2508 im = im.reduce(factor, box) 

2509 return im.convert(self.mode) 

2510 

2511 self.load() 

2512 

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

2514 

2515 def rotate( 

2516 self, 

2517 angle: float, 

2518 resample: Resampling = Resampling.NEAREST, 

2519 expand: int | bool = False, 

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

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

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

2523 ) -> Image: 

2524 """ 

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

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

2527 clockwise around its centre. 

2528 

2529 :param angle: In degrees counterclockwise. 

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

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

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

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

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

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

2536 See :ref:`concept-filters`. 

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

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

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

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

2541 the center and no translation. 

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

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

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

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

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

2547 """ 

2548 

2549 angle = angle % 360.0 

2550 if math.isnan(angle): 

2551 msg = "invalid angle" 

2552 raise ValueError(msg) 

2553 

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

2555 # translating or changing the center. 

2556 if not (center or translate): 

2557 if angle == 0: 

2558 return self.copy() 

2559 if angle == 180: 

2560 return self.transpose(Transpose.ROTATE_180) 

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

2562 return self.transpose( 

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

2564 ) 

2565 

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

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

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

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

2570 

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

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

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

2574 # (0, 0, 1) (0, 0, 1) ( 0, 0, 1) (0, 0, 1) 

2575 

2576 # The reverse matrix is thus: 

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

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

2579 # (0, 0, 1) ( 0, 0, 1) (0, 0, 1) (0, 0, 1) 

2580 

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

2582 # compensate for the expand flag. 

2583 

2584 w, h = self.size 

2585 

2586 if translate is None: 

2587 post_trans = (0, 0) 

2588 else: 

2589 post_trans = translate 

2590 if center is None: 

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

2592 

2593 angle = -math.radians(angle) 

2594 matrix = [ 

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

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

2597 0.0, 

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

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

2600 0.0, 

2601 ] 

2602 

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

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

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

2606 

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

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

2609 ) 

2610 matrix[2] += center[0] 

2611 matrix[5] += center[1] 

2612 

2613 if expand: 

2614 # calculate output size 

2615 xx = [] 

2616 yy = [] 

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

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

2619 xx.append(transformed_x) 

2620 yy.append(transformed_y) 

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

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

2623 

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

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

2626 # translation vector as new translation vector. 

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

2628 w, h = nw, nh 

2629 

2630 return self.transform( 

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

2632 ) 

2633 

2634 def save( 

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

2636 ) -> None: 

2637 """ 

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

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

2640 extension, if possible. 

2641 

2642 Keyword options can be used to provide additional instructions 

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

2644 silently ignored. The available options are described in the 

2645 :doc:`image format documentation 

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

2647 

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

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

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

2651 methods, and be opened in binary mode. 

2652 

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

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

2655 format to use is determined from the filename extension. 

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

2657 parameter should always be used. 

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

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

2660 saving multiple images:: 

2661 

2662 # Saving XMP data to a single image 

2663 from PIL import Image 

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

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

2666 

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

2668 from PIL import Image 

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

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

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

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

2673 :returns: None 

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

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

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

2677 may have been created, and may contain partial data. 

2678 """ 

2679 

2680 filename: str | bytes = "" 

2681 open_fp = False 

2682 if is_path(fp): 

2683 filename = os.fspath(fp) 

2684 open_fp = True 

2685 elif fp == sys.stdout and isinstance(sys.stdout, io.TextIOWrapper): 

2686 fp = sys.stdout.buffer 

2687 if not filename and hasattr(fp, "name") and is_path(fp.name): 

2688 # only set the name for metadata purposes 

2689 filename = os.fspath(fp.name) 

2690 

2691 if format: 

2692 preinit() 

2693 else: 

2694 filename_ext = os.path.splitext(filename)[1].lower() 

2695 ext = ( 

2696 filename_ext.decode() 

2697 if isinstance(filename_ext, bytes) 

2698 else filename_ext 

2699 ) 

2700 

2701 # Try importing only the plugin for this extension first 

2702 if not _import_plugin_for_extension(ext): 

2703 preinit() 

2704 

2705 if ext not in EXTENSION: 

2706 init() 

2707 try: 

2708 format = EXTENSION[ext] 

2709 except KeyError as e: 

2710 msg = f"unknown file extension: {ext}" 

2711 raise ValueError(msg) from e 

2712 

2713 from . import ImageFile 

2714 

2715 # may mutate self! 

2716 if isinstance(self, ImageFile.ImageFile) and os.path.abspath( 

2717 filename 

2718 ) == os.path.abspath(self.filename): 

2719 self._ensure_mutable() 

2720 else: 

2721 self.load() 

2722 

2723 save_all = params.pop("save_all", None) 

2724 self._default_encoderinfo = params 

2725 encoderinfo = getattr(self, "encoderinfo", {}) 

2726 self._attach_default_encoderinfo(self) 

2727 self.encoderconfig: tuple[Any, ...] = () 

2728 

2729 if format.upper() not in SAVE: 

2730 init() 

2731 if save_all or ( 

2732 save_all is None 

2733 and params.get("append_images") 

2734 and format.upper() in SAVE_ALL 

2735 ): 

2736 save_handler = SAVE_ALL[format.upper()] 

2737 else: 

2738 save_handler = SAVE[format.upper()] 

2739 

2740 created = False 

2741 if open_fp: 

2742 created = not os.path.exists(filename) 

2743 if params.get("append", False): 

2744 # Open also for reading ("+"), because TIFF save_all 

2745 # writer needs to go back and edit the written data. 

2746 fp = builtins.open(filename, "r+b") 

2747 else: 

2748 fp = builtins.open(filename, "w+b") 

2749 else: 

2750 fp = cast("IO[bytes]", fp) 

2751 

2752 try: 

2753 save_handler(self, fp, filename) 

2754 except Exception: 

2755 if open_fp: 

2756 fp.close() 

2757 if created: 

2758 try: 

2759 os.remove(filename) 

2760 except PermissionError: 

2761 pass 

2762 raise 

2763 finally: 

2764 self.encoderinfo = encoderinfo 

2765 if open_fp: 

2766 fp.close() 

2767 

2768 def _attach_default_encoderinfo(self, im: Image) -> dict[str, Any]: 

2769 encoderinfo = getattr(self, "encoderinfo", {}) 

2770 self.encoderinfo = {**im._default_encoderinfo, **encoderinfo} 

2771 return encoderinfo 

2772 

2773 def seek(self, frame: int) -> None: 

2774 """ 

2775 Seeks to the given frame in this sequence file. If you seek 

2776 beyond the end of the sequence, the method raises an 

2777 ``EOFError`` exception. When a sequence file is opened, the 

2778 library automatically seeks to frame 0. 

2779 

2780 See :py:meth:`~PIL.Image.Image.tell`. 

2781 

2782 If defined, :attr:`~PIL.Image.Image.n_frames` refers to the 

2783 number of available frames. 

2784 

2785 :param frame: Frame number, starting at 0. 

2786 :exception EOFError: If the call attempts to seek beyond the end 

2787 of the sequence. 

2788 """ 

2789 

2790 # overridden by file handlers 

2791 if frame != self.tell(): 

2792 # The file handler likely did not override this method 

2793 msg = "no more images in file" 

2794 raise EOFError(msg) 

2795 

2796 if self._im is not None and ( 

2797 self.im.size != self.size or self.im.mode != self.mode 

2798 ): 

2799 self._im = None 

2800 

2801 def show(self, title: str | None = None) -> None: 

2802 """ 

2803 Displays this image. This method is mainly intended for debugging purposes. 

2804 

2805 This method calls :py:func:`PIL.ImageShow.show` internally. You can use 

2806 :py:func:`PIL.ImageShow.register` to override its default behaviour. 

2807 

2808 The image is first saved to a temporary file. By default, it will be in 

2809 PNG format. 

2810 

2811 On Unix, the image is then opened using the **xdg-open**, **display**, 

2812 **gm**, **eog** or **xv** utility, depending on which one can be found. 

2813 

2814 On macOS, the image is opened with the native Preview application. 

2815 

2816 On Windows, the image is opened with the standard PNG display utility. 

2817 

2818 :param title: Optional title to use for the image window, where possible. 

2819 """ 

2820 

2821 from . import ImageShow 

2822 

2823 ImageShow.show(self, title) 

2824 

2825 def split(self) -> tuple[Image, ...]: 

2826 """ 

2827 Split this image into individual bands. This method returns a 

2828 tuple of individual image bands from an image. For example, 

2829 splitting an "RGB" image creates three new images each 

2830 containing a copy of one of the original bands (red, green, 

2831 blue). 

2832 

2833 If you need only one band, :py:meth:`~PIL.Image.Image.getchannel` 

2834 method can be more convenient and faster. 

2835 

2836 :returns: A tuple containing bands. 

2837 """ 

2838 

2839 self.load() 

2840 if self.im.bands == 1: 

2841 return (self.copy(),) 

2842 return tuple(map(self._new, self.im.split())) 

2843 

2844 def getchannel(self, channel: int | str) -> Image: 

2845 """ 

2846 Returns an image containing a single channel of the source image. 

2847 

2848 :param channel: What channel to return. Could be index 

2849 (0 for "R" channel of "RGB") or channel name 

2850 ("A" for alpha channel of "RGBA"). 

2851 :returns: An image in "L" mode. 

2852 

2853 .. versionadded:: 4.3.0 

2854 """ 

2855 self.load() 

2856 

2857 if isinstance(channel, str): 

2858 try: 

2859 channel = self.getbands().index(channel) 

2860 except ValueError as e: 

2861 msg = f'The image has no channel "{channel}"' 

2862 raise ValueError(msg) from e 

2863 

2864 return self._new(self.im.getband(channel)) 

2865 

2866 def tell(self) -> int: 

2867 """ 

2868 Returns the current frame number. See :py:meth:`~PIL.Image.Image.seek`. 

2869 

2870 If defined, :attr:`~PIL.Image.Image.n_frames` refers to the 

2871 number of available frames. 

2872 

2873 :returns: Frame number, starting with 0. 

2874 """ 

2875 return 0 

2876 

2877 def thumbnail( 

2878 self, 

2879 size: tuple[float, float], 

2880 resample: Resampling = Resampling.BICUBIC, 

2881 reducing_gap: float | None = 2.0, 

2882 ) -> None: 

2883 """ 

2884 Make this image into a thumbnail. This method modifies the 

2885 image to contain a thumbnail version of itself, no larger than 

2886 the given size. This method calculates an appropriate thumbnail 

2887 size to preserve the aspect of the image, calls the 

2888 :py:meth:`~PIL.Image.Image.draft` method to configure the file reader 

2889 (where applicable), and finally resizes the image. 

2890 

2891 Note that this function modifies the :py:class:`~PIL.Image.Image` 

2892 object in place. If you need to use the full resolution image as well, 

2893 apply this method to a :py:meth:`~PIL.Image.Image.copy` of the original 

2894 image. 

2895 

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

2897 (width, height). 

2898 :param resample: Optional resampling filter. This can be one 

2899 of :py:data:`Resampling.NEAREST`, :py:data:`Resampling.BOX`, 

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

2901 :py:data:`Resampling.BICUBIC`, :py:data:`Resampling.LANCZOS`, 

2902 :py:data:`Resampling.MKS2013`, or :py:data:`Resampling.MKS2021`. 

2903 If omitted, it defaults to :py:data:`Resampling.BICUBIC`. 

2904 (was :py:data:`Resampling.NEAREST` prior to version 2.5.0). 

2905 See: :ref:`concept-filters`. 

2906 :param reducing_gap: Apply optimization by resizing the image 

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

2908 using :py:meth:`~PIL.Image.Image.reduce` or 

2909 :py:meth:`~PIL.Image.Image.draft` for JPEG images. 

2910 Second, resizing using regular resampling. The last step 

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

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

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

2914 the closer the result to the fair resampling. 

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

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

2917 indistinguishable from fair resampling in most cases. 

2918 The default value is 2.0 (very close to fair resampling 

2919 while still being faster in many cases). 

2920 :returns: None 

2921 """ 

2922 

2923 provided_size = tuple(map(math.floor, size)) 

2924 

2925 def preserve_aspect_ratio() -> tuple[int, int] | None: 

2926 def round_aspect(number: float, key: Callable[[int], float]) -> int: 

2927 return min(math.floor(number), math.ceil(number), key=key) 

2928 

2929 x, y = provided_size 

2930 if x >= self.width and y >= self.height: 

2931 return None 

2932 if self.height == 0: 

2933 return x, self.height 

2934 

2935 aspect = self.width / self.height 

2936 if x / y >= aspect: 

2937 x = round_aspect(y * aspect, key=lambda n: abs(aspect - n / y)) 

2938 else: 

2939 y = round_aspect( 

2940 x / aspect, key=lambda n: 0 if n == 0 else abs(aspect - x / n) 

2941 ) 

2942 return x, y 

2943 

2944 preserved_size = preserve_aspect_ratio() 

2945 if preserved_size is None: 

2946 return 

2947 final_size = preserved_size 

2948 

2949 box = None 

2950 if reducing_gap is not None: 

2951 res = self.draft( 

2952 None, (int(size[0] * reducing_gap), int(size[1] * reducing_gap)) 

2953 ) 

2954 if res is not None: 

2955 box = res[1] 

2956 

2957 if self.size != final_size: 

2958 if min(final_size) == 0: 

2959 im = self.crop((0, 0, *final_size)) 

2960 else: 

2961 im = self.resize( 

2962 final_size, resample, box=box, reducing_gap=reducing_gap 

2963 ) 

2964 

2965 self.im = im.im 

2966 self._size = final_size 

2967 self._mode = self.im.mode 

2968 

2969 self.readonly = 0 

2970 

2971 # FIXME: the different transform methods need further explanation 

2972 # instead of bloating the method docs, add a separate chapter. 

2973 def transform( 

2974 self, 

2975 size: tuple[int, int], 

2976 method: Transform | ImageTransformHandler | SupportsGetData, 

2977 data: Sequence[Any] | None = None, 

2978 resample: int = Resampling.NEAREST, 

2979 fill: int = 1, 

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

2981 ) -> Image: 

2982 """ 

2983 Transforms this image. This method creates a new image with the 

2984 given size, and the same mode as the original, and copies data 

2985 to the new image using the given transform. 

2986 

2987 :param size: The output size in pixels, as a 2-tuple: 

2988 (width, height). 

2989 :param method: The transformation method. This is one of 

2990 :py:data:`Transform.EXTENT` (cut out a rectangular subregion), 

2991 :py:data:`Transform.AFFINE` (affine transform), 

2992 :py:data:`Transform.PERSPECTIVE` (perspective transform), 

2993 :py:data:`Transform.QUAD` (map a quadrilateral to a rectangle), or 

2994 :py:data:`Transform.MESH` (map a number of source quadrilaterals 

2995 in one operation). 

2996 

2997 It may also be an :py:class:`~PIL.Image.ImageTransformHandler` 

2998 object:: 

2999 

3000 class Example(Image.ImageTransformHandler): 

3001 def transform(self, size, data, resample, fill=1): 

3002 # Return result 

3003 

3004 Implementations of :py:class:`~PIL.Image.ImageTransformHandler` 

3005 for some of the :py:class:`Transform` methods are provided 

3006 in :py:mod:`~PIL.ImageTransform`. 

3007 

3008 It may also be an object with a ``method.getdata`` method 

3009 that returns a tuple supplying new ``method`` and ``data`` values:: 

3010 

3011 class Example: 

3012 def getdata(self): 

3013 method = Image.Transform.EXTENT 

3014 data = (0, 0, 100, 100) 

3015 return method, data 

3016 :param data: Extra data to the transformation method. 

3017 :param resample: Optional resampling filter. It can be one of 

3018 :py:data:`Resampling.NEAREST` (use nearest neighbour), 

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

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

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

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

3023 See: :ref:`concept-filters`. 

3024 :param fill: If ``method`` is an 

3025 :py:class:`~PIL.Image.ImageTransformHandler` object, this is one of 

3026 the arguments passed to it. Otherwise, it is unused. 

3027 :param fillcolor: Optional fill color for the area outside the 

3028 transform in the output image. 

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

3030 """ 

3031 

3032 if self.mode in ("LA", "RGBA") and resample != Resampling.NEAREST: 

3033 return ( 

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

3035 .transform(size, method, data, resample, fill, fillcolor) 

3036 .convert(self.mode) 

3037 ) 

3038 

3039 if isinstance(method, ImageTransformHandler): 

3040 return method.transform(size, self, resample=resample, fill=fill) 

3041 

3042 if hasattr(method, "getdata"): 

3043 # compatibility w. old-style transform objects 

3044 method, data = method.getdata() 

3045 

3046 if data is None: 

3047 msg = "missing method data" 

3048 raise ValueError(msg) 

3049 

3050 palette = None 

3051 if self.mode in {"P", "PA"} and self.palette: 

3052 palette = self.palette.copy() 

3053 if isinstance(fillcolor, str): 

3054 from . import ImageColor 

3055 

3056 fillcolor = ImageColor.getcolor(fillcolor, self.mode) 

3057 if isinstance(fillcolor, tuple) and all( 

3058 isinstance(i, int) for i in fillcolor 

3059 ): 

3060 fillcolor = palette.getcolor(cast("tuple[int, ...]", fillcolor), self) 

3061 

3062 im = new(self.mode, size, fillcolor) 

3063 im.info = self._copy_info() 

3064 if method == Transform.MESH: 

3065 # list of quads 

3066 for box, quad in data: 

3067 im.__transformer( 

3068 box, self, Transform.QUAD, quad, resample, fillcolor is None 

3069 ) 

3070 else: 

3071 im.__transformer( 

3072 (0, 0, *size), self, method, data, resample, fillcolor is None 

3073 ) 

3074 if palette: 

3075 im.palette = palette 

3076 

3077 return im 

3078 

3079 def __transformer( 

3080 self, 

3081 box: tuple[int, int, int, int], 

3082 image: Image, 

3083 method: Transform, 

3084 data: Sequence[float], 

3085 resample: int = Resampling.NEAREST, 

3086 fill: bool = True, 

3087 ) -> None: 

3088 w = box[2] - box[0] 

3089 h = box[3] - box[1] 

3090 

3091 if method == Transform.AFFINE: 

3092 data = data[:6] 

3093 

3094 elif method == Transform.EXTENT: 

3095 # convert extent to an affine transform 

3096 x0, y0, x1, y1 = data 

3097 xs = (x1 - x0) / w 

3098 ys = (y1 - y0) / h 

3099 method = Transform.AFFINE 

3100 data = (xs, 0, x0, 0, ys, y0) 

3101 

3102 elif method == Transform.PERSPECTIVE: 

3103 data = data[:8] 

3104 

3105 elif method == Transform.QUAD: 

3106 # quadrilateral warp. data specifies the four corners 

3107 # given as NW, SW, SE, and NE. 

3108 nw = data[:2] 

3109 sw = data[2:4] 

3110 se = data[4:6] 

3111 ne = data[6:8] 

3112 x0, y0 = nw 

3113 As = 1.0 / w 

3114 At = 1.0 / h 

3115 data = ( 

3116 x0, 

3117 (ne[0] - x0) * As, 

3118 (sw[0] - x0) * At, 

3119 (se[0] - sw[0] - ne[0] + x0) * As * At, 

3120 y0, 

3121 (ne[1] - y0) * As, 

3122 (sw[1] - y0) * At, 

3123 (se[1] - sw[1] - ne[1] + y0) * As * At, 

3124 ) 

3125 

3126 else: 

3127 msg = "unknown transformation method" 

3128 raise ValueError(msg) 

3129 

3130 if resample not in ( 

3131 Resampling.NEAREST, 

3132 Resampling.BILINEAR, 

3133 Resampling.BICUBIC, 

3134 ): 

3135 if resample in ( 

3136 Resampling.BOX, 

3137 Resampling.HAMMING, 

3138 Resampling.LANCZOS, 

3139 Resampling.MKS2013, 

3140 Resampling.MKS2021, 

3141 ): 

3142 unusable: dict[int, str] = { 

3143 Resampling.BOX: "Image.Resampling.BOX", 

3144 Resampling.HAMMING: "Image.Resampling.HAMMING", 

3145 Resampling.LANCZOS: "Image.Resampling.LANCZOS", 

3146 Resampling.MKS2013: "Image.Resampling.MKS2013", 

3147 Resampling.MKS2021: "Image.Resampling.MKS2021", 

3148 } 

3149 msg = unusable[resample] + f" ({resample}) cannot be used." 

3150 else: 

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

3152 

3153 filters = [ 

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

3155 for filter in ( 

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

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

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

3159 ) 

3160 ] 

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

3162 raise ValueError(msg) 

3163 

3164 image.load() 

3165 

3166 self.load() 

3167 

3168 if image.mode in {"1", "P", "PA"}: 

3169 resample = Resampling.NEAREST 

3170 

3171 self.im.transform(box, image.im, method, data, resample, fill) 

3172 

3173 def transpose(self, method: Transpose) -> Image: 

3174 """ 

3175 Transpose image (flip or rotate in 90 degree steps) 

3176 

3177 :param method: One of :py:data:`Transpose.FLIP_LEFT_RIGHT`, 

3178 :py:data:`Transpose.FLIP_TOP_BOTTOM`, :py:data:`Transpose.ROTATE_90`, 

3179 :py:data:`Transpose.ROTATE_180`, :py:data:`Transpose.ROTATE_270`, 

3180 :py:data:`Transpose.TRANSPOSE` or :py:data:`Transpose.TRANSVERSE`. 

3181 :returns: Returns a flipped or rotated copy of this image. 

3182 """ 

3183 

3184 self.load() 

3185 return self._new(self.im.transpose(method)) 

3186 

3187 def effect_spread(self, distance: int) -> Image: 

3188 """ 

3189 Randomly spread pixels in an image. 

3190 

3191 :param distance: Distance to spread pixels. 

3192 """ 

3193 self.load() 

3194 return self._new(self.im.effect_spread(distance)) 

3195 

3196 def toqimage(self) -> ImageQt.ImageQt: 

3197 """Returns a QImage copy of this image""" 

3198 from . import ImageQt 

3199 

3200 if not ImageQt.qt_is_installed: 

3201 msg = "Qt bindings are not installed" 

3202 raise ImportError(msg) 

3203 return ImageQt.toqimage(self) 

3204 

3205 def toqpixmap(self) -> ImageQt.QPixmap: 

3206 """Returns a QPixmap copy of this image""" 

3207 from . import ImageQt 

3208 

3209 if not ImageQt.qt_is_installed: 

3210 msg = "Qt bindings are not installed" 

3211 raise ImportError(msg) 

3212 return ImageQt.toqpixmap(self) 

3213 

3214 

3215# -------------------------------------------------------------------- 

3216# Abstract handlers. 

3217 

3218 

3219class ImagePointHandler(abc.ABC): 

3220 """ 

3221 Used as a mixin by point transforms 

3222 (for use with :py:meth:`~PIL.Image.Image.point`) 

3223 """ 

3224 

3225 @abc.abstractmethod 

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

3227 pass 

3228 

3229 

3230class ImageTransformHandler(abc.ABC): 

3231 """ 

3232 Used as a mixin by geometry transforms 

3233 (for use with :py:meth:`~PIL.Image.Image.transform`) 

3234 """ 

3235 

3236 @abc.abstractmethod 

3237 def transform( 

3238 self, 

3239 size: tuple[int, int], 

3240 image: Image, 

3241 **options: Any, 

3242 ) -> Image: 

3243 pass 

3244 

3245 

3246# -------------------------------------------------------------------- 

3247# Factories 

3248 

3249 

3250def _check_size(size: Any) -> None: 

3251 """ 

3252 Common check to enforce type and sanity check on size tuples 

3253 

3254 :param size: Should be a 2 tuple of (width, height) 

3255 :returns: None, or raises a ValueError 

3256 """ 

3257 

3258 if not isinstance(size, (list, tuple)): 

3259 msg = "Size must be a list or tuple" 

3260 raise ValueError(msg) 

3261 if len(size) != 2: 

3262 msg = "Size must be a sequence of length 2" 

3263 raise ValueError(msg) 

3264 if size[0] < 0 or size[1] < 0: 

3265 msg = "Width and height must be >= 0" 

3266 raise ValueError(msg) 

3267 

3268 

3269def new( 

3270 mode: str, 

3271 size: tuple[int, int] | list[int], 

3272 color: float | tuple[float, ...] | str | None = 0, 

3273) -> Image: 

3274 """ 

3275 Creates a new image with the given mode and size. 

3276 

3277 :param mode: The mode to use for the new image. See: :ref:`concept-modes`. 

3278 :param size: A 2-tuple, containing (width, height) in pixels. 

3279 :param color: What color to use for the image. If given, this should be a single 

3280 integer or floating point value for single-band modes, and a tuple for 

3281 multi-band modes (one value per band). When creating RGB or HSV images, you can 

3282 also use color strings as supported by the ImageColor module. See :ref:`colors` 

3283 for more information. The default color is zero, which appears as black in 

3284 single band or RGB-based images. ``None`` is also treated as zero. 

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

3286 """ 

3287 

3288 _check_size(size) 

3289 

3290 if color is None: 

3291 # core.new() returns zeroed memory, so there is nothing to fill 

3292 return Image()._new(core.new(mode, size)) 

3293 

3294 if isinstance(color, str): 

3295 # css3-style specifier 

3296 

3297 from . import ImageColor 

3298 

3299 color = ImageColor.getcolor(color, mode) 

3300 

3301 im = Image() 

3302 if ( 

3303 mode in {"P", "PA"} 

3304 and isinstance(color, tuple) 

3305 and all(isinstance(i, int) for i in color) 

3306 ): 

3307 from . import ImagePalette 

3308 

3309 im._mode = mode 

3310 im.palette = ImagePalette.ImagePalette() 

3311 color = im._get_palette_color(cast("tuple[int, ...]", color)) 

3312 return im._new(core.fill(mode, size, color)) 

3313 

3314 

3315def frombytes( 

3316 mode: str, 

3317 size: tuple[int, int], 

3318 data: DecoderInput, 

3319 decoder_name: str = "raw", 

3320 *args: Any, 

3321) -> Image: 

3322 """ 

3323 Creates a copy of an image memory from pixel data in a buffer. 

3324 

3325 In its simplest form, this function takes three arguments 

3326 (mode, size, and unpacked pixel data). 

3327 

3328 You can also use any pixel decoder supported by PIL. For more 

3329 information on available decoders, see the section 

3330 :ref:`Writing Your Own File Codec <file-codecs>`. 

3331 

3332 Note that this function decodes pixel data only, not entire images. 

3333 If you have an entire image in a string, wrap it in a 

3334 :py:class:`~io.BytesIO` object, and use :py:func:`~PIL.Image.open` to load 

3335 it. 

3336 

3337 :param mode: The image mode. See: :ref:`concept-modes`. 

3338 :param size: The image size. 

3339 :param data: A byte buffer containing raw data for the given mode. 

3340 :param decoder_name: What decoder to use. 

3341 :param args: Additional parameters for the given decoder. 

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

3343 """ 

3344 

3345 _check_size(size) 

3346 

3347 im = new(mode, size) 

3348 if im.width != 0 and im.height != 0: 

3349 decoder_args: Any = args 

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

3351 # may pass tuple instead of argument list 

3352 decoder_args = decoder_args[0] 

3353 

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

3355 decoder_args = mode 

3356 

3357 im.frombytes(data, decoder_name, decoder_args) 

3358 return im 

3359 

3360 

3361def frombuffer( 

3362 mode: str, 

3363 size: tuple[int, int], 

3364 data: bytes | bytearray | SupportsArrayInterface, 

3365 decoder_name: str = "raw", 

3366 *args: Any, 

3367) -> Image: 

3368 """ 

3369 Creates an image memory referencing pixel data in a byte buffer. 

3370 

3371 This function is similar to :py:func:`~PIL.Image.frombytes`, but uses data 

3372 in the byte buffer, where possible. This means that changes to the 

3373 original buffer object are reflected in this image). Not all modes can 

3374 share memory; supported modes include "L", "RGBX", "RGBA", and "CMYK". 

3375 

3376 Note that this function decodes pixel data only, not entire images. 

3377 If you have an entire image file in a string, wrap it in a 

3378 :py:class:`~io.BytesIO` object, and use :py:func:`~PIL.Image.open` to load it. 

3379 

3380 The default parameters used for the "raw" decoder differs from that used for 

3381 :py:func:`~PIL.Image.frombytes`. This is a bug, and will probably be fixed in a 

3382 future release. The current release issues a warning if you do this; to disable 

3383 the warning, you should provide the full set of parameters. See below for details. 

3384 

3385 :param mode: The image mode. See: :ref:`concept-modes`. 

3386 :param size: The image size. 

3387 :param data: A bytes or other buffer object containing raw 

3388 data for the given mode. 

3389 :param decoder_name: What decoder to use. 

3390 :param args: Additional parameters for the given decoder. For the 

3391 default encoder ("raw"), it's recommended that you provide the 

3392 full set of parameters:: 

3393 

3394 frombuffer(mode, size, data, "raw", mode, 0, 1) 

3395 

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

3397 

3398 .. versionadded:: 1.1.4 

3399 """ 

3400 

3401 _check_size(size) 

3402 

3403 # may pass tuple instead of argument list 

3404 if len(args) == 1 and isinstance(args[0], tuple): 

3405 args = args[0] 

3406 

3407 if decoder_name == "raw" and min(size) != 0: 

3408 if args == (): 

3409 args = mode, 0, 1 

3410 if args[0] == mode and args[0] in _MAPMODES: 

3411 im = Image()._new(core.map_buffer(data, size, decoder_name, 0, args)) 

3412 if mode == "P": 

3413 from . import ImagePalette 

3414 

3415 im.palette = ImagePalette.ImagePalette("RGB", im.im.getpalette("RGB")) 

3416 return im 

3417 

3418 return frombytes(mode, size, data, decoder_name, args) 

3419 

3420 

3421class SupportsArrayInterface(Protocol): 

3422 """ 

3423 An object that has an ``__array_interface__`` dictionary. 

3424 """ 

3425 

3426 @property 

3427 def __array_interface__(self) -> dict[str, Any]: 

3428 raise NotImplementedError() 

3429 

3430 

3431DecoderInput = bytes | bytearray | memoryview | SupportsArrayInterface 

3432 

3433 

3434class SupportsArrowArrayInterface(Protocol): 

3435 """ 

3436 An object that has an ``__arrow_c_array__`` method corresponding to the arrow c 

3437 data interface. 

3438 """ 

3439 

3440 def __arrow_c_array__( 

3441 self, requested_schema: PyCapsule = None # type: ignore[name-defined] # noqa: F821 

3442 ) -> tuple[PyCapsule, PyCapsule]: # type: ignore[name-defined] # noqa: F821 

3443 raise NotImplementedError() 

3444 

3445 

3446def fromarray(obj: SupportsArrayInterface, mode: str | None = None) -> Image: 

3447 """ 

3448 Creates an image memory from an object exporting the array interface 

3449 (using the buffer protocol):: 

3450 

3451 from PIL import Image 

3452 import numpy as np 

3453 a = np.zeros((5, 5)) 

3454 im = Image.fromarray(a) 

3455 

3456 If ``obj`` is not contiguous, then the ``tobytes`` method is called 

3457 and :py:func:`~PIL.Image.frombuffer` is used. 

3458 

3459 In the case of NumPy, be aware that Pillow modes do not always correspond 

3460 to NumPy dtypes. Pillow modes only offer 1-bit pixels, 8-bit pixels, 

3461 32-bit signed integer pixels, and 32-bit floating point pixels. 

3462 

3463 Pillow images can also be converted to arrays:: 

3464 

3465 from PIL import Image 

3466 import numpy as np 

3467 im = Image.open("hopper.jpg") 

3468 a = np.asarray(im) 

3469 

3470 When converting Pillow images to arrays however, only pixel values are 

3471 transferred. This means that P and PA mode images will lose their palette. 

3472 

3473 :param obj: Object with array interface 

3474 :param mode: Optional mode to use when reading ``obj``. Since pixel values do not 

3475 contain information about palettes or color spaces, this can be used to place 

3476 grayscale L mode data within a P mode image, or read RGB data as YCbCr for 

3477 example. 

3478 

3479 See: :ref:`concept-modes` for general information about modes. 

3480 :returns: An image object. 

3481 

3482 .. versionadded:: 1.1.6 

3483 """ 

3484 arr = obj.__array_interface__ 

3485 shape = arr["shape"] 

3486 ndim = len(shape) 

3487 strides = arr.get("strides", None) 

3488 try: 

3489 typekey = (1, 1) + shape[2:], arr["typestr"] 

3490 except KeyError as e: 

3491 if mode is not None: 

3492 typekey = None 

3493 color_modes: list[str] = [] 

3494 else: 

3495 msg = "Cannot handle this data type" 

3496 raise TypeError(msg) from e 

3497 if typekey is not None: 

3498 try: 

3499 typemode, rawmode, color_modes = _fromarray_typemap[typekey] 

3500 except KeyError as e: 

3501 typekey_shape, typestr = typekey 

3502 msg = f"Cannot handle this data type: {typekey_shape}, {typestr}" 

3503 raise TypeError(msg) from e 

3504 if mode is not None: 

3505 if mode != typemode and mode not in color_modes: 

3506 msg = "Invalid mode for data type" 

3507 raise ValueError(msg) 

3508 rawmode = mode 

3509 else: 

3510 mode = typemode 

3511 if mode in ["1", "L", "I", "P", "F"]: 

3512 ndmax = 2 

3513 elif mode == "RGB": 

3514 ndmax = 3 

3515 else: 

3516 ndmax = 4 

3517 if ndim > ndmax: 

3518 msg = f"Too many dimensions: {ndim} > {ndmax}." 

3519 raise ValueError(msg) 

3520 

3521 size = 1 if ndim == 1 else shape[1], shape[0] 

3522 if strides is not None: 

3523 if hasattr(obj, "tobytes"): 

3524 obj = obj.tobytes() 

3525 elif hasattr(obj, "tostring"): 

3526 obj = obj.tostring() 

3527 else: 

3528 msg = "'strides' requires either tobytes() or tostring()" 

3529 raise ValueError(msg) 

3530 

3531 return frombuffer(mode, size, obj, "raw", rawmode, 0, 1) 

3532 

3533 

3534def fromarrow( 

3535 obj: SupportsArrowArrayInterface, mode: str, size: tuple[int, int] 

3536) -> Image: 

3537 """Creates an image with zero-copy shared memory from an object exporting 

3538 the arrow_c_array interface protocol:: 

3539 

3540 from PIL import Image 

3541 import pyarrow as pa 

3542 arr = pa.array([0]*(5*5*4), type=pa.uint8()) 

3543 im = Image.fromarrow(arr, 'RGBA', (5, 5)) 

3544 

3545 If the data representation of the ``obj`` is not compatible with 

3546 Pillow internal storage, a ValueError is raised. 

3547 

3548 Pillow images can also be converted to Arrow objects:: 

3549 

3550 from PIL import Image 

3551 import pyarrow as pa 

3552 im = Image.open('hopper.jpg') 

3553 arr = pa.array(im) 

3554 

3555 As with array support, when converting Pillow images to arrays, 

3556 only pixel values are transferred. This means that P and PA mode 

3557 images will lose their palette. 

3558 

3559 :param obj: Object with an arrow_c_array interface 

3560 :param mode: Image mode. 

3561 :param size: Image size. This must match the storage of the arrow object. 

3562 :returns: An Image object 

3563 

3564 Note that according to the Arrow spec, both the producer and the 

3565 consumer should consider the exported array to be immutable, as 

3566 unsynchronized updates will potentially cause inconsistent data. 

3567 

3568 See: :ref:`arrow-support` for more detailed information 

3569 

3570 .. versionadded:: 11.2.1 

3571 

3572 """ 

3573 if not hasattr(obj, "__arrow_c_array__"): 

3574 msg = "arrow_c_array interface not found" 

3575 raise ValueError(msg) 

3576 

3577 schema_capsule, array_capsule = obj.__arrow_c_array__() 

3578 _im = core.new_arrow(mode, size, schema_capsule, array_capsule) 

3579 if _im is not None: 

3580 return Image()._new(_im) 

3581 

3582 msg = "new_arrow returned None without an exception" 

3583 raise ValueError(msg) 

3584 

3585 

3586def fromqimage(im: ImageQt.QImage) -> ImageFile.ImageFile: 

3587 """Creates an image instance from a QImage image""" 

3588 from . import ImageQt 

3589 

3590 if not ImageQt.qt_is_installed: 

3591 msg = "Qt bindings are not installed" 

3592 raise ImportError(msg) 

3593 return ImageQt.fromqimage(im) 

3594 

3595 

3596def fromqpixmap(im: ImageQt.QPixmap) -> ImageFile.ImageFile: 

3597 """Creates an image instance from a QPixmap image""" 

3598 from . import ImageQt 

3599 

3600 if not ImageQt.qt_is_installed: 

3601 msg = "Qt bindings are not installed" 

3602 raise ImportError(msg) 

3603 return ImageQt.fromqpixmap(im) 

3604 

3605 

3606_fromarray_typemap = { 

3607 # (shape, typestr) => mode, rawmode, color modes 

3608 # first two members of shape are set to one 

3609 ((1, 1), "|b1"): ("1", "1;8", []), 

3610 ((1, 1), "|u1"): ("L", "L", ["P"]), 

3611 ((1, 1), "|i1"): ("I", "I;8", []), 

3612 ((1, 1), "<u2"): ("I;16", "I;16", []), 

3613 ((1, 1), ">u2"): ("I;16B", "I;16B", []), 

3614 ((1, 1), "<i2"): ("I", "I;16S", []), 

3615 ((1, 1), ">i2"): ("I", "I;16BS", []), 

3616 ((1, 1), "<u4"): ("I", "I;32", []), 

3617 ((1, 1), ">u4"): ("I", "I;32B", []), 

3618 ((1, 1), "<i4"): ("I", "I;32S", []), 

3619 ((1, 1), ">i4"): ("I", "I;32BS", []), 

3620 ((1, 1), "<f4"): ("F", "F;32F", []), 

3621 ((1, 1), ">f4"): ("F", "F;32BF", []), 

3622 ((1, 1), "<f8"): ("F", "F;64F", []), 

3623 ((1, 1), ">f8"): ("F", "F;64BF", []), 

3624 ((1, 1, 2), "|u1"): ("LA", "LA", ["La", "PA"]), 

3625 ((1, 1, 3), "|u1"): ("RGB", "RGB", ["YCbCr", "LAB", "HSV"]), 

3626 ((1, 1, 4), "|u1"): ("RGBA", "RGBA", ["RGBa", "RGBX", "CMYK"]), 

3627 # shortcuts: 

3628 ((1, 1), f"{_ENDIAN}i4"): ("I", "I", []), 

3629 ((1, 1), f"{_ENDIAN}f4"): ("F", "F", []), 

3630} 

3631 

3632 

3633def _decompression_bomb_check( 

3634 size: tuple[int, int], *, error_only: bool = False 

3635) -> None: 

3636 if MAX_IMAGE_PIXELS is None: 

3637 return 

3638 

3639 pixels = max(1, size[0]) * max(1, size[1]) 

3640 

3641 if pixels > 2 * MAX_IMAGE_PIXELS: 

3642 msg = ( 

3643 f"Image size ({pixels} pixels) exceeds limit of {2 * MAX_IMAGE_PIXELS} " 

3644 "pixels, could be decompression bomb DOS attack." 

3645 ) 

3646 raise DecompressionBombError(msg) 

3647 

3648 if not error_only and pixels > MAX_IMAGE_PIXELS: 

3649 warnings.warn( 

3650 f"Image size ({pixels} pixels) exceeds limit of {MAX_IMAGE_PIXELS} pixels, " 

3651 "could be decompression bomb DOS attack.", 

3652 DecompressionBombWarning, 

3653 ) 

3654 

3655 

3656def open( 

3657 fp: StrOrBytesPath | IO[bytes], 

3658 mode: Literal["r"] = "r", 

3659 formats: list[str] | tuple[str, ...] | None = None, 

3660) -> ImageFile.ImageFile: 

3661 """ 

3662 Opens and identifies the given image file. 

3663 

3664 This is a lazy operation; this function identifies the file, but 

3665 the file remains open and the actual image data is not read from 

3666 the file until you try to process the data (or call the 

3667 :py:meth:`~PIL.Image.Image.load` method). See 

3668 :py:func:`~PIL.Image.new`. See :ref:`file-handling`. 

3669 

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

3671 The file object must implement ``file.read``, 

3672 ``file.seek``, and ``file.tell`` methods, 

3673 and be opened in binary mode. The file object will also seek to zero 

3674 before reading. 

3675 :param mode: The mode. If given, this argument must be "r". 

3676 :param formats: A list or tuple of formats to attempt to load the file in. 

3677 This can be used to restrict the set of formats checked. 

3678 Pass ``None`` to try all supported formats. You can print the set of 

3679 available formats by running ``python3 -m PIL`` or using 

3680 the :py:func:`PIL.features.pilinfo` function. 

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

3682 :exception FileNotFoundError: If the file cannot be found. 

3683 :exception PIL.UnidentifiedImageError: If the image cannot be opened and 

3684 identified. 

3685 :exception ValueError: If the ``mode`` is not "r", or if a ``StringIO`` 

3686 instance is used for ``fp``. 

3687 :exception TypeError: If ``formats`` is not ``None``, a list or a tuple. 

3688 """ 

3689 

3690 if mode != "r": 

3691 msg = f"bad mode {repr(mode)}" # type: ignore[unreachable] 

3692 raise ValueError(msg) 

3693 elif isinstance(fp, io.StringIO): 

3694 msg = ( # type: ignore[unreachable] 

3695 "StringIO cannot be used to open an image. " 

3696 "Binary data must be used instead." 

3697 ) 

3698 raise ValueError(msg) 

3699 

3700 if formats is None: 

3701 formats = ID 

3702 elif not isinstance(formats, (list, tuple)): 

3703 msg = "formats must be a list or tuple" # type: ignore[unreachable] 

3704 raise TypeError(msg) 

3705 

3706 exclusive_fp = False 

3707 filename: str | bytes = "" 

3708 if is_path(fp): 

3709 filename = os.fspath(fp) 

3710 fp = builtins.open(filename, "rb") 

3711 exclusive_fp = True 

3712 else: 

3713 fp = cast("IO[bytes]", fp) 

3714 

3715 try: 

3716 fp.seek(0) 

3717 except (AttributeError, io.UnsupportedOperation): 

3718 fp = io.BytesIO(fp.read()) 

3719 exclusive_fp = True 

3720 

3721 prefix = fp.read(16) 

3722 

3723 # Try to import just the plugin needed for this file extension 

3724 # before falling back to preinit() which imports common plugins 

3725 ext = os.path.splitext(filename)[1] if filename else "" 

3726 if not _import_plugin_for_extension(ext): 

3727 preinit() 

3728 

3729 warning_messages: list[str] = [] 

3730 

3731 def _open_core( 

3732 fp: IO[bytes], 

3733 filename: str | bytes, 

3734 prefix: bytes, 

3735 formats: list[str] | tuple[str, ...], 

3736 ) -> ImageFile.ImageFile | None: 

3737 for i in formats: 

3738 i = i.upper() 

3739 if i not in OPEN: 

3740 init() 

3741 try: 

3742 factory, accept = OPEN[i] 

3743 result = not accept or accept(prefix) 

3744 if isinstance(result, str): 

3745 warning_messages.append(result) 

3746 elif result: 

3747 fp.seek(0) 

3748 im = factory(fp, filename) 

3749 _decompression_bomb_check(im.size) 

3750 return im 

3751 except (SyntaxError, IndexError, TypeError, struct.error) as e: 

3752 if WARN_POSSIBLE_FORMATS: 

3753 warning_messages.append(i + " opening failed. " + str(e)) 

3754 except BaseException: 

3755 if exclusive_fp: 

3756 fp.close() 

3757 raise 

3758 return None 

3759 

3760 im = _open_core(fp, filename, prefix, formats) 

3761 

3762 if im is None and formats is ID: 

3763 # Try preinit (few common plugins) then init (all plugins) 

3764 for loader in (preinit, init): 

3765 checked_formats = ID.copy() 

3766 loader() 

3767 if formats != checked_formats: 

3768 im = _open_core( 

3769 fp, 

3770 filename, 

3771 prefix, 

3772 tuple(f for f in formats if f not in checked_formats), 

3773 ) 

3774 if im is not None: 

3775 break 

3776 

3777 if im: 

3778 im._exclusive_fp = exclusive_fp 

3779 return im 

3780 

3781 if exclusive_fp: 

3782 fp.close() 

3783 for message in warning_messages: 

3784 warnings.warn(message) 

3785 msg = "cannot identify image file %r" % (filename if filename else fp) 

3786 raise UnidentifiedImageError(msg) 

3787 

3788 

3789# 

3790# Image processing. 

3791 

3792 

3793def alpha_composite(im1: Image, im2: Image) -> Image: 

3794 """ 

3795 Alpha composite im2 over im1. 

3796 

3797 :param im1: The first image. Must have mode RGBA or LA. 

3798 :param im2: The second image. Must have the same mode and size as the first image. 

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

3800 """ 

3801 

3802 im1.load() 

3803 im2.load() 

3804 return im1._new(core.alpha_composite(im1.im, im2.im)) 

3805 

3806 

3807def blend(im1: Image, im2: Image, alpha: float) -> Image: 

3808 """ 

3809 Creates a new image by interpolating between two input images, using 

3810 a constant alpha:: 

3811 

3812 out = image1 * (1.0 - alpha) + image2 * alpha 

3813 

3814 :param im1: The first image. 

3815 :param im2: The second image. Must have the same mode and size as 

3816 the first image. 

3817 :param alpha: The interpolation alpha factor. If alpha is 0.0, a 

3818 copy of the first image is returned. If alpha is 1.0, a copy of 

3819 the second image is returned. There are no restrictions on the 

3820 alpha value. If necessary, the result is clipped to fit into 

3821 the allowed output range. 

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

3823 """ 

3824 

3825 im1.load() 

3826 im2.load() 

3827 return im1._new(core.blend(im1.im, im2.im, alpha)) 

3828 

3829 

3830def composite(image1: Image, image2: Image, mask: Image) -> Image: 

3831 """ 

3832 Create composite image by blending images using a transparency mask. 

3833 

3834 :param image1: The first image. 

3835 :param image2: The second image. Must have the same mode and 

3836 size as the first image. 

3837 :param mask: A mask image. This image can have mode 

3838 "1", "L", or "RGBA", and must have the same size as the 

3839 other two images. 

3840 """ 

3841 

3842 image = image2.copy() 

3843 image.paste(image1, None, mask) 

3844 return image 

3845 

3846 

3847def eval(image: Image, *args: Callable[[int], float]) -> Image: 

3848 r""" 

3849 Applies the function (which should take one argument) to each pixel 

3850 in the given image. If the image has more than one band, the same 

3851 function is applied to each band. Note that the function is 

3852 evaluated once for each possible pixel value, so you cannot use 

3853 random components or other generators. 

3854 

3855 :param image: The input image. 

3856 :param \*args: A function object, taking one integer argument. 

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

3858 """ 

3859 

3860 return image.point(args[0]) 

3861 

3862 

3863def merge(mode: str, bands: Sequence[Image]) -> Image: 

3864 """ 

3865 Merge a set of single band images into a new multiband image. 

3866 

3867 :param mode: The mode to use for the output image. See: 

3868 :ref:`concept-modes`. 

3869 :param bands: A sequence containing one single-band image for 

3870 each band in the output image. All bands must have the 

3871 same size. 

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

3873 """ 

3874 

3875 if getmodebands(mode) != len(bands): 

3876 msg = "wrong number of bands" 

3877 raise ValueError(msg) 

3878 for band in bands[1:]: 

3879 if band.mode != getmodetype(mode): 

3880 msg = "mode mismatch" 

3881 raise ValueError(msg) 

3882 if band.size != bands[0].size: 

3883 msg = "size mismatch" 

3884 raise ValueError(msg) 

3885 for band in bands: 

3886 band.load() 

3887 return bands[0]._new(core.merge(mode, *[b.im for b in bands])) 

3888 

3889 

3890# -------------------------------------------------------------------- 

3891# Plugin registry 

3892 

3893 

3894def register_open( 

3895 id: str, 

3896 factory: ( 

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

3898 | type[ImageFile.ImageFile] 

3899 ), 

3900 accept: Callable[[bytes], bool | str] | None = None, 

3901) -> None: 

3902 """ 

3903 Register an image file plugin. This function should not be used 

3904 in application code. 

3905 

3906 :param id: An image format identifier. 

3907 :param factory: An image file factory method. 

3908 :param accept: An optional function that can be used to quickly 

3909 reject images having another format. 

3910 """ 

3911 id = id.upper() 

3912 if id not in ID: 

3913 ID.append(id) 

3914 OPEN[id] = factory, accept 

3915 

3916 

3917def register_mime(id: str, mimetype: str) -> None: 

3918 """ 

3919 Registers an image MIME type by populating ``Image.MIME``. This function 

3920 should not be used in application code. 

3921 

3922 ``Image.MIME`` provides a mapping from image format identifiers to mime 

3923 formats, but :py:meth:`~PIL.ImageFile.ImageFile.get_format_mimetype` can 

3924 provide a different result for specific images. 

3925 

3926 :param id: An image format identifier. 

3927 :param mimetype: The image MIME type for this format. 

3928 """ 

3929 MIME[id.upper()] = mimetype 

3930 

3931 

3932def register_save( 

3933 id: str, driver: Callable[[Image, IO[bytes], str | bytes], None] 

3934) -> None: 

3935 """ 

3936 Registers an image save function. This function should not be 

3937 used in application code. 

3938 

3939 :param id: An image format identifier. 

3940 :param driver: A function to save images in this format. 

3941 """ 

3942 SAVE[id.upper()] = driver 

3943 

3944 

3945def register_save_all( 

3946 id: str, driver: Callable[[Image, IO[bytes], str | bytes], None] 

3947) -> None: 

3948 """ 

3949 Registers an image function to save all the frames 

3950 of a multiframe format. This function should not be 

3951 used in application code. 

3952 

3953 :param id: An image format identifier. 

3954 :param driver: A function to save images in this format. 

3955 """ 

3956 SAVE_ALL[id.upper()] = driver 

3957 

3958 

3959def register_extension(id: str, extension: str) -> None: 

3960 """ 

3961 Registers an image extension. This function should not be 

3962 used in application code. 

3963 

3964 :param id: An image format identifier. 

3965 :param extension: An extension used for this format. 

3966 """ 

3967 EXTENSION[extension.lower()] = id.upper() 

3968 

3969 

3970def register_extensions(id: str, extensions: list[str]) -> None: 

3971 """ 

3972 Registers image extensions. This function should not be 

3973 used in application code. 

3974 

3975 :param id: An image format identifier. 

3976 :param extensions: A list of extensions used for this format. 

3977 """ 

3978 for extension in extensions: 

3979 register_extension(id, extension) 

3980 

3981 

3982def registered_extensions() -> dict[str, str]: 

3983 """ 

3984 Returns a dictionary containing all file extensions belonging 

3985 to registered plugins 

3986 """ 

3987 init() 

3988 return EXTENSION 

3989 

3990 

3991def register_decoder(name: str, decoder: type[ImageFile.PyDecoder]) -> None: 

3992 """ 

3993 Registers an image decoder. This function should not be 

3994 used in application code. 

3995 

3996 :param name: The name of the decoder 

3997 :param decoder: An ImageFile.PyDecoder object 

3998 

3999 .. versionadded:: 4.1.0 

4000 """ 

4001 DECODERS[name] = decoder 

4002 

4003 

4004def register_encoder(name: str, encoder: type[ImageFile.PyEncoder]) -> None: 

4005 """ 

4006 Registers an image encoder. This function should not be 

4007 used in application code. 

4008 

4009 :param name: The name of the encoder 

4010 :param encoder: An ImageFile.PyEncoder object 

4011 

4012 .. versionadded:: 4.1.0 

4013 """ 

4014 ENCODERS[name] = encoder 

4015 

4016 

4017# -------------------------------------------------------------------- 

4018# Effects 

4019 

4020 

4021def effect_mandelbrot( 

4022 size: tuple[int, int], extent: tuple[float, float, float, float], quality: int 

4023) -> Image: 

4024 """ 

4025 Generate a Mandelbrot set covering the given extent. 

4026 

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

4028 (width, height). 

4029 :param extent: The extent to cover, as a 4-tuple: 

4030 (x0, y0, x1, y1). 

4031 :param quality: Quality. 

4032 """ 

4033 return Image()._new(core.effect_mandelbrot(size, extent, quality)) 

4034 

4035 

4036def effect_noise(size: tuple[int, int], sigma: float) -> Image: 

4037 """ 

4038 Generate Gaussian noise centered around 128. 

4039 

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

4041 (width, height). 

4042 :param sigma: Standard deviation of noise. 

4043 """ 

4044 return Image()._new(core.effect_noise(size, sigma)) 

4045 

4046 

4047def linear_gradient(mode: str) -> Image: 

4048 """ 

4049 Generate 256x256 linear gradient from black to white, top to bottom. 

4050 

4051 :param mode: Input mode. 

4052 """ 

4053 return Image()._new(core.linear_gradient(mode)) 

4054 

4055 

4056def radial_gradient(mode: str) -> Image: 

4057 """ 

4058 Generate 256x256 radial gradient from black to white, centre to edge. 

4059 

4060 :param mode: Input mode. 

4061 """ 

4062 return Image()._new(core.radial_gradient(mode)) 

4063 

4064 

4065# -------------------------------------------------------------------- 

4066# Resources 

4067 

4068 

4069def _apply_env_variables(env: dict[str, str] | None = None) -> None: 

4070 env_dict = env if env is not None else os.environ 

4071 

4072 for var_name, setter in [ 

4073 ("PILLOW_ALIGNMENT", core.set_alignment), 

4074 ("PILLOW_BLOCK_SIZE", core.set_block_size), 

4075 ("PILLOW_BLOCKS_MAX", core.set_blocks_max), 

4076 ]: 

4077 if var_name not in env_dict: 

4078 continue 

4079 

4080 var = env_dict[var_name].lower() 

4081 

4082 units = 1 

4083 for postfix, mul in [("k", 1024), ("m", 1024 * 1024)]: 

4084 if var.endswith(postfix): 

4085 units = mul 

4086 var = var[: -len(postfix)] 

4087 

4088 try: 

4089 var_int = int(var) * units 

4090 except ValueError: 

4091 warnings.warn(f"{var_name} is not int") 

4092 continue 

4093 

4094 try: 

4095 setter(var_int) 

4096 except ValueError as e: 

4097 warnings.warn(f"{var_name}: {e}") 

4098 

4099 

4100_apply_env_variables() 

4101atexit.register(core.clear_cache) 

4102 

4103 

4104if TYPE_CHECKING: 

4105 _ExifBase = MutableMapping[int, Any] 

4106else: 

4107 _ExifBase = MutableMapping 

4108 

4109 

4110class Exif(_ExifBase): 

4111 """ 

4112 This class provides read and write access to EXIF image data:: 

4113 

4114 from PIL import Image 

4115 im = Image.open("exif.png") 

4116 exif = im.getexif() # Returns an instance of this class 

4117 

4118 Information can be read and written, iterated over or deleted:: 

4119 

4120 print(exif[274]) # 1 

4121 exif[274] = 2 

4122 for k, v in exif.items(): 

4123 print("Tag", k, "Value", v) # Tag 274 Value 2 

4124 del exif[274] 

4125 

4126 To access information beyond IFD0, :py:meth:`~PIL.Image.Exif.get_ifd` 

4127 returns a dictionary:: 

4128 

4129 from PIL import ExifTags 

4130 im = Image.open("exif_gps.jpg") 

4131 exif = im.getexif() 

4132 gps_ifd = exif.get_ifd(ExifTags.IFD.GPSInfo) 

4133 print(gps_ifd) 

4134 

4135 Other IFDs include ``ExifTags.IFD.Exif``, ``ExifTags.IFD.MakerNote``, 

4136 ``ExifTags.IFD.Interop`` and ``ExifTags.IFD.IFD1``. 

4137 

4138 :py:mod:`~PIL.ExifTags` also has enum classes to provide names for data:: 

4139 

4140 print(exif[ExifTags.Base.Software]) # PIL 

4141 print(gps_ifd[ExifTags.GPS.GPSDateStamp]) # 1999:99:99 99:99:99 

4142 """ 

4143 

4144 endian: str | None = None 

4145 bigtiff = False 

4146 _loaded = False 

4147 

4148 def __init__(self) -> None: 

4149 self._data: dict[int, Any] = {} 

4150 self._hidden_data: dict[int, Any] = {} 

4151 self._ifds: dict[int, dict[int, Any]] = {} 

4152 self._info: TiffImagePlugin.ImageFileDirectory_v2 | None = None 

4153 self._loaded_exif: bytes | None = None 

4154 

4155 def _fixup(self, value: Any) -> Any: 

4156 try: 

4157 if len(value) == 1 and isinstance(value, tuple): 

4158 return value[0] 

4159 except Exception: 

4160 pass 

4161 return value 

4162 

4163 def _fixup_dict(self, src_dict: dict[int, Any]) -> dict[int, Any]: 

4164 # Helper function 

4165 # returns a dict with any single item tuples/lists as individual values 

4166 return {k: self._fixup(v) for k, v in src_dict.items()} 

4167 

4168 def _get_ifd_dict( 

4169 self, offset: int, group: int | None = None 

4170 ) -> dict[int, Any] | None: 

4171 try: 

4172 # an offset pointer to the location of the nested embedded IFD. 

4173 # It should be a long, but may be corrupted. 

4174 self.fp.seek(offset) 

4175 except (KeyError, TypeError): 

4176 return None 

4177 else: 

4178 from . import TiffImagePlugin 

4179 

4180 info = TiffImagePlugin.ImageFileDirectory_v2(self.head, group=group) 

4181 info.load(self.fp) 

4182 return self._fixup_dict(dict(info)) 

4183 

4184 def _get_head(self) -> bytes: 

4185 version = b"\x2b" if self.bigtiff else b"\x2a" 

4186 if self.endian == "<": 

4187 head = b"II" + version + b"\x00" + o32le(8) 

4188 else: 

4189 head = b"MM\x00" + version + o32be(8) 

4190 if self.bigtiff: 

4191 head += o32le(8) if self.endian == "<" else o32be(8) 

4192 head += b"\x00\x00\x00\x00" 

4193 return head 

4194 

4195 def load(self, data: bytes) -> None: 

4196 # Extract EXIF information. This is highly experimental, 

4197 # and is likely to be replaced with something better in a future 

4198 # version. 

4199 

4200 # The EXIF record consists of a TIFF file embedded in a JPEG 

4201 # application marker (!). 

4202 if data == self._loaded_exif: 

4203 return 

4204 self._loaded_exif = data 

4205 self._data.clear() 

4206 self._hidden_data.clear() 

4207 self._ifds.clear() 

4208 data = re.sub(b"^(Exif\x00\x00){1,2}", b"", data) 

4209 if not data: 

4210 self._info = None 

4211 return 

4212 

4213 self.fp: IO[bytes] = io.BytesIO(data) 

4214 self.head = self.fp.read(8) 

4215 # process dictionary 

4216 from . import TiffImagePlugin 

4217 

4218 self._info = TiffImagePlugin.ImageFileDirectory_v2(self.head) 

4219 self.endian = self._info._endian 

4220 self.fp.seek(self._info.next) 

4221 self._info.load(self.fp) 

4222 

4223 def load_from_fp(self, fp: IO[bytes], offset: int | None = None) -> None: 

4224 self._loaded_exif = None 

4225 self._data.clear() 

4226 self._hidden_data.clear() 

4227 self._ifds.clear() 

4228 

4229 # process dictionary 

4230 from . import TiffImagePlugin 

4231 

4232 self.fp = fp 

4233 if offset is not None: 

4234 self.head = self._get_head() 

4235 else: 

4236 self.head = self.fp.read(8) 

4237 self._info = TiffImagePlugin.ImageFileDirectory_v2(self.head) 

4238 if self.endian is None: 

4239 self.endian = self._info._endian 

4240 if offset is None: 

4241 offset = self._info.next 

4242 self.fp.tell() 

4243 self.fp.seek(offset) 

4244 self._info.load(self.fp) 

4245 

4246 def _get_merged_dict(self) -> dict[int, Any]: 

4247 merged_dict = dict(self) 

4248 

4249 # get EXIF extension 

4250 if ExifTags.IFD.Exif in self: 

4251 ifd = self._get_ifd_dict(self[ExifTags.IFD.Exif], ExifTags.IFD.Exif) 

4252 if ifd: 

4253 merged_dict.update(ifd) 

4254 

4255 # GPS 

4256 if ExifTags.IFD.GPSInfo in self: 

4257 merged_dict[ExifTags.IFD.GPSInfo] = self._get_ifd_dict( 

4258 self[ExifTags.IFD.GPSInfo], ExifTags.IFD.GPSInfo 

4259 ) 

4260 

4261 return merged_dict 

4262 

4263 def tobytes(self, offset: int = 8) -> bytes: 

4264 from . import TiffImagePlugin 

4265 

4266 head = self._get_head() 

4267 ifd = TiffImagePlugin.ImageFileDirectory_v2(ifh=head) 

4268 for tag, ifd_dict in self._ifds.items(): 

4269 if tag in {ExifTags.IFD.Exif, ExifTags.IFD.GPSInfo} and tag not in self: 

4270 ifd[tag] = ifd_dict 

4271 for tag, value in self.items(): 

4272 if tag in [ 

4273 ExifTags.IFD.Exif, 

4274 ExifTags.IFD.GPSInfo, 

4275 ] and not isinstance(value, dict): 

4276 value = self.get_ifd(tag) 

4277 if ( 

4278 tag == ExifTags.IFD.Exif 

4279 and ExifTags.IFD.Interop in value 

4280 and not isinstance(value[ExifTags.IFD.Interop], dict) 

4281 ): 

4282 value = value.copy() 

4283 value[ExifTags.IFD.Interop] = self.get_ifd(ExifTags.IFD.Interop) 

4284 ifd[tag] = value 

4285 return b"Exif\x00\x00" + head + ifd.tobytes(offset) 

4286 

4287 def get_ifd(self, tag: int) -> dict[int, Any]: 

4288 if tag not in self._ifds: 

4289 if tag == ExifTags.IFD.IFD1: 

4290 if self._info is not None and self._info.next != 0: 

4291 ifd = self._get_ifd_dict(self._info.next) 

4292 if ifd is not None: 

4293 self._ifds[tag] = ifd 

4294 elif tag in [ExifTags.IFD.Exif, ExifTags.IFD.GPSInfo]: 

4295 offset = self._hidden_data.get(tag, self.get(tag)) 

4296 if offset is not None: 

4297 ifd = self._get_ifd_dict(offset, tag) 

4298 if ifd is not None: 

4299 self._ifds[tag] = ifd 

4300 elif tag in [ExifTags.IFD.Interop, ExifTags.IFD.MakerNote]: 

4301 if ExifTags.IFD.Exif not in self._ifds: 

4302 self.get_ifd(ExifTags.IFD.Exif) 

4303 tag_data = self._ifds[ExifTags.IFD.Exif].get(tag) 

4304 if tag_data is None: 

4305 pass 

4306 elif tag == ExifTags.IFD.MakerNote: 

4307 from .TiffImagePlugin import ImageFileDirectory_v2 

4308 

4309 try: 

4310 if tag_data.startswith(b"FUJIFILM"): 

4311 ifd_offset = i32le(tag_data, 8) 

4312 ifd_data = tag_data[ifd_offset:] 

4313 

4314 makernote = {} 

4315 for i in range(struct.unpack("<H", ifd_data[:2])[0]): 

4316 ifd_tag, typ, count, data = struct.unpack( 

4317 "<HHL4s", ifd_data[i * 12 + 2 : (i + 1) * 12 + 2] 

4318 ) 

4319 try: 

4320 ( 

4321 unit_size, 

4322 handler, 

4323 ) = ImageFileDirectory_v2._load_dispatch[typ] 

4324 except KeyError: 

4325 continue 

4326 size = count * unit_size 

4327 if size > 4: 

4328 (offset,) = struct.unpack("<L", data) 

4329 data = ifd_data[offset - 12 : offset + size - 12] 

4330 else: 

4331 data = data[:size] 

4332 

4333 if len(data) != size: 

4334 warnings.warn( 

4335 "Possibly corrupt EXIF MakerNote data. " 

4336 f"Expecting to read {size} bytes but only got " 

4337 f"{len(data)}. Skipping tag {ifd_tag}" 

4338 ) 

4339 continue 

4340 

4341 if not data: 

4342 continue 

4343 

4344 makernote[ifd_tag] = handler( 

4345 ImageFileDirectory_v2(), data, False 

4346 ) 

4347 self._ifds[tag] = dict(self._fixup_dict(makernote)) 

4348 elif self.get(0x010F) == "Nintendo": 

4349 makernote = {} 

4350 for i in range(struct.unpack(">H", tag_data[:2])[0]): 

4351 ifd_tag, typ, count, data = struct.unpack( 

4352 ">HHL4s", tag_data[i * 12 + 2 : (i + 1) * 12 + 2] 

4353 ) 

4354 if ifd_tag == 0x1101: 

4355 # CameraInfo 

4356 (offset,) = struct.unpack(">L", data) 

4357 self.fp.seek(offset) 

4358 

4359 camerainfo: dict[str, int | bytes] = { 

4360 "ModelID": self.fp.read(4) 

4361 } 

4362 

4363 self.fp.read(4) 

4364 # Seconds since 2000 

4365 camerainfo["TimeStamp"] = i32le(self.fp.read(12)) 

4366 

4367 self.fp.read(4) 

4368 camerainfo["InternalSerialNumber"] = self.fp.read(4) 

4369 

4370 self.fp.read(12) 

4371 parallax = self.fp.read(4) 

4372 handler = ImageFileDirectory_v2._load_dispatch[ 

4373 TiffTags.FLOAT 

4374 ][1] 

4375 camerainfo["Parallax"] = handler( 

4376 ImageFileDirectory_v2(), parallax, False 

4377 )[0] 

4378 

4379 self.fp.read(4) 

4380 camerainfo["Category"] = self.fp.read(2) 

4381 

4382 makernote = {0x1101: camerainfo} 

4383 self._ifds[tag] = makernote 

4384 except struct.error: 

4385 pass 

4386 else: 

4387 # Interop 

4388 ifd = self._get_ifd_dict(tag_data, tag) 

4389 if ifd is not None: 

4390 self._ifds[tag] = ifd 

4391 ifd = self._ifds.setdefault(tag, {}) 

4392 if tag == ExifTags.IFD.Exif and self._hidden_data: 

4393 ifd = { 

4394 k: v 

4395 for (k, v) in ifd.items() 

4396 if k not in (ExifTags.IFD.Interop, ExifTags.IFD.MakerNote) 

4397 } 

4398 return ifd 

4399 

4400 def hide_offsets(self) -> None: 

4401 for tag in (ExifTags.IFD.Exif, ExifTags.IFD.GPSInfo): 

4402 if tag in self: 

4403 self._hidden_data[tag] = self[tag] 

4404 del self[tag] 

4405 

4406 def __str__(self) -> str: 

4407 if self._info is not None: 

4408 # Load all keys into self._data 

4409 for tag in self._info: 

4410 self[tag] 

4411 

4412 return str(self._data) 

4413 

4414 def __len__(self) -> int: 

4415 keys = set(self._data) 

4416 if self._info is not None: 

4417 keys.update(self._info) 

4418 return len(keys) 

4419 

4420 def __getitem__(self, tag: int) -> Any: 

4421 if self._info is not None and tag not in self._data and tag in self._info: 

4422 self._data[tag] = self._fixup(self._info[tag]) 

4423 del self._info[tag] 

4424 return self._data[tag] 

4425 

4426 def __contains__(self, tag: object) -> bool: 

4427 return tag in self._data or (self._info is not None and tag in self._info) 

4428 

4429 def __setitem__(self, tag: int, value: Any) -> None: 

4430 if self._info is not None and tag in self._info: 

4431 del self._info[tag] 

4432 self._data[tag] = value 

4433 

4434 def __delitem__(self, tag: int) -> None: 

4435 if self._info is not None and tag in self._info: 

4436 del self._info[tag] 

4437 else: 

4438 del self._data[tag] 

4439 if tag in self._ifds: 

4440 del self._ifds[tag] 

4441 

4442 def __iter__(self) -> Iterator[int]: 

4443 keys = set(self._data) 

4444 if self._info is not None: 

4445 keys.update(self._info) 

4446 return iter(keys)