Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/PIL/Image.py: 17%

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

1728 statements  

1# 

2# The Python Imaging Library. 

3# $Id$ 

4# 

5# the Image class wrapper 

6# 

7# partial release history: 

8# 1995-09-09 fl Created 

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

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

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

12# 2000-06-07 fl PIL release 1.1 

13# 2000-10-20 fl PIL release 1.1.1 

14# 2001-05-07 fl PIL release 1.1.2 

15# 2002-03-15 fl PIL release 1.1.3 

16# 2003-05-10 fl PIL release 1.1.4 

17# 2005-03-28 fl PIL release 1.1.5 

18# 2006-12-02 fl PIL release 1.1.6 

19# 2009-11-15 fl PIL release 1.1.7 

20# 

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

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

23# 

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

25# 

26 

27from __future__ import annotations 

28 

29import abc 

30import atexit 

31import builtins 

32import io 

33import logging 

34import math 

35import os 

36import re 

37import struct 

38import sys 

39import tempfile 

40import warnings 

41from collections.abc import Callable, Iterator, MutableMapping, Sequence 

42from enum import IntEnum 

43from types import ModuleType 

44from typing import ( 

45 IO, 

46 TYPE_CHECKING, 

47 Any, 

48 Literal, 

49 Protocol, 

50 cast, 

51) 

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 

68ElementTree: ModuleType | None 

69try: 

70 from defusedxml import ElementTree 

71except ImportError: 

72 ElementTree = None 

73 

74logger = logging.getLogger(__name__) 

75 

76 

77class DecompressionBombWarning(RuntimeWarning): 

78 pass 

79 

80 

81class DecompressionBombError(Exception): 

82 pass 

83 

84 

85WARN_POSSIBLE_FORMATS: bool = False 

86 

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

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

89 

90 

91try: 

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

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

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

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

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

97 from . import _imaging as core 

98 

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

100 msg = ( 

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

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

103 f"Pillow version: {__version__}" 

104 ) 

105 raise ImportError(msg) 

106 

107except ImportError as v: 

108 core = DeferredError.new(ImportError("The _imaging C module is not installed.")) 

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

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

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

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

113 # possible. 

114 warnings.warn( 

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

116 RuntimeWarning, 

117 ) 

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

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

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

121 # see docs/porting.rst 

122 raise 

123 

124 

125def isImageType(t: Any) -> TypeGuard[Image]: 

126 """ 

127 Checks if an object is an image object. 

128 

129 .. warning:: 

130 

131 This function is for internal use only. 

132 

133 :param t: object to check if it's an image 

134 :returns: True if the object is an image 

135 """ 

136 deprecate("Image.isImageType(im)", 12, "isinstance(im, Image.Image)") 

137 return hasattr(t, "im") 

138 

139 

140# 

141# Constants 

142 

143 

144# transpose 

145class Transpose(IntEnum): 

146 FLIP_LEFT_RIGHT = 0 

147 FLIP_TOP_BOTTOM = 1 

148 ROTATE_90 = 2 

149 ROTATE_180 = 3 

150 ROTATE_270 = 4 

151 TRANSPOSE = 5 

152 TRANSVERSE = 6 

153 

154 

155# transforms (also defined in Imaging.h) 

156class Transform(IntEnum): 

157 AFFINE = 0 

158 EXTENT = 1 

159 PERSPECTIVE = 2 

160 QUAD = 3 

161 MESH = 4 

162 

163 

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

165class Resampling(IntEnum): 

166 NEAREST = 0 

167 BOX = 4 

168 BILINEAR = 2 

169 HAMMING = 5 

170 BICUBIC = 3 

171 LANCZOS = 1 

172 

173 

174_filters_support = { 

175 Resampling.BOX: 0.5, 

176 Resampling.BILINEAR: 1.0, 

177 Resampling.HAMMING: 1.0, 

178 Resampling.BICUBIC: 2.0, 

179 Resampling.LANCZOS: 3.0, 

180} 

181 

182 

183# dithers 

184class Dither(IntEnum): 

185 NONE = 0 

186 ORDERED = 1 # Not yet implemented 

187 RASTERIZE = 2 # Not yet implemented 

188 FLOYDSTEINBERG = 3 # default 

189 

190 

191# palettes/quantizers 

192class Palette(IntEnum): 

193 WEB = 0 

194 ADAPTIVE = 1 

195 

196 

197class Quantize(IntEnum): 

198 MEDIANCUT = 0 

199 MAXCOVERAGE = 1 

200 FASTOCTREE = 2 

201 LIBIMAGEQUANT = 3 

202 

203 

204module = sys.modules[__name__] 

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

206 for item in enum: 

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

208 

209 

210if hasattr(core, "DEFAULT_STRATEGY"): 

211 DEFAULT_STRATEGY = core.DEFAULT_STRATEGY 

212 FILTERED = core.FILTERED 

213 HUFFMAN_ONLY = core.HUFFMAN_ONLY 

214 RLE = core.RLE 

215 FIXED = core.FIXED 

216 

217 

218# -------------------------------------------------------------------- 

219# Registries 

220 

221if TYPE_CHECKING: 

222 import mmap 

223 from xml.etree.ElementTree import Element 

224 

225 from IPython.lib.pretty import PrettyPrinter 

226 

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

228 from ._typing import CapsuleType, NumpyArray, StrOrBytesPath, TypeGuard 

229ID: list[str] = [] 

230OPEN: dict[ 

231 str, 

232 tuple[ 

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

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

235 ], 

236] = {} 

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

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

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

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

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

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

243 

244# -------------------------------------------------------------------- 

245# Modes 

246 

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

248 

249 

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

251 m = ImageMode.getmode(im.mode) 

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

253 extra = len(m.bands) 

254 if extra != 1: 

255 shape += (extra,) 

256 return shape, m.typestr 

257 

258 

259MODES = [ 

260 "1", 

261 "CMYK", 

262 "F", 

263 "HSV", 

264 "I", 

265 "I;16", 

266 "I;16B", 

267 "I;16L", 

268 "I;16N", 

269 "L", 

270 "LA", 

271 "La", 

272 "LAB", 

273 "P", 

274 "PA", 

275 "RGB", 

276 "RGBA", 

277 "RGBa", 

278 "RGBX", 

279 "YCbCr", 

280] 

281 

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

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

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

285 

286 

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

288 """ 

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

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

291 contain color data. 

292 

293 :param mode: Input mode. 

294 :returns: "L" or "RGB". 

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

296 """ 

297 return ImageMode.getmode(mode).basemode 

298 

299 

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

301 """ 

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

303 single-layer mode suitable for storing individual bands. 

304 

305 :param mode: Input mode. 

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

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

308 """ 

309 return ImageMode.getmode(mode).basetype 

310 

311 

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

313 """ 

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

315 a tuple containing the names of individual bands (use 

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

317 individual band. 

318 

319 :param mode: Input mode. 

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

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

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

323 """ 

324 return ImageMode.getmode(mode).bands 

325 

326 

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

328 """ 

329 Gets the number of individual bands for this mode. 

330 

331 :param mode: Input mode. 

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

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

334 """ 

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

336 

337 

338# -------------------------------------------------------------------- 

339# Helpers 

340 

341_initialized = 0 

342 

343 

344def preinit() -> None: 

345 """ 

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

347 

348 It is called when opening or saving images. 

349 """ 

350 

351 global _initialized 

352 if _initialized >= 1: 

353 return 

354 

355 try: 

356 from . import BmpImagePlugin 

357 

358 assert BmpImagePlugin 

359 except ImportError: 

360 pass 

361 try: 

362 from . import GifImagePlugin 

363 

364 assert GifImagePlugin 

365 except ImportError: 

366 pass 

367 try: 

368 from . import JpegImagePlugin 

369 

370 assert JpegImagePlugin 

371 except ImportError: 

372 pass 

373 try: 

374 from . import PpmImagePlugin 

375 

376 assert PpmImagePlugin 

377 except ImportError: 

378 pass 

379 try: 

380 from . import PngImagePlugin 

381 

382 assert PngImagePlugin 

383 except ImportError: 

384 pass 

385 

386 _initialized = 1 

387 

388 

389def init() -> bool: 

390 """ 

391 Explicitly initializes the Python Imaging Library. This function 

392 loads all available file format drivers. 

393 

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

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

396 """ 

397 

398 global _initialized 

399 if _initialized >= 2: 

400 return False 

401 

402 parent_name = __name__.rpartition(".")[0] 

403 for plugin in _plugins: 

404 try: 

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

406 __import__(f"{parent_name}.{plugin}", globals(), locals(), []) 

407 except ImportError as e: 

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

409 

410 if OPEN or SAVE: 

411 _initialized = 2 

412 return True 

413 return False 

414 

415 

416# -------------------------------------------------------------------- 

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

418 

419 

420def _getdecoder( 

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

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

423 # tweak arguments 

424 if args is None: 

425 args = () 

426 elif not isinstance(args, tuple): 

427 args = (args,) 

428 

429 try: 

430 decoder = DECODERS[decoder_name] 

431 except KeyError: 

432 pass 

433 else: 

434 return decoder(mode, *args + extra) 

435 

436 try: 

437 # get decoder 

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

439 except AttributeError as e: 

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

441 raise OSError(msg) from e 

442 return decoder(mode, *args + extra) 

443 

444 

445def _getencoder( 

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

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

448 # tweak arguments 

449 if args is None: 

450 args = () 

451 elif not isinstance(args, tuple): 

452 args = (args,) 

453 

454 try: 

455 encoder = ENCODERS[encoder_name] 

456 except KeyError: 

457 pass 

458 else: 

459 return encoder(mode, *args + extra) 

460 

461 try: 

462 # get encoder 

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

464 except AttributeError as e: 

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

466 raise OSError(msg) from e 

467 return encoder(mode, *args + extra) 

468 

469 

470# -------------------------------------------------------------------- 

471# Simple expression analyzer 

472 

473 

474class ImagePointTransform: 

475 """ 

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

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

478 ``scale`` and ``offset`` is added. 

479 """ 

480 

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

482 self.scale = scale 

483 self.offset = offset 

484 

485 def __neg__(self) -> ImagePointTransform: 

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

487 

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

489 if isinstance(other, ImagePointTransform): 

490 return ImagePointTransform( 

491 self.scale + other.scale, self.offset + other.offset 

492 ) 

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

494 

495 __radd__ = __add__ 

496 

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

498 return self + -other 

499 

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

501 return other + -self 

502 

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

504 if isinstance(other, ImagePointTransform): 

505 return NotImplemented 

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

507 

508 __rmul__ = __mul__ 

509 

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

511 if isinstance(other, ImagePointTransform): 

512 return NotImplemented 

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

514 

515 

516def _getscaleoffset( 

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

518) -> tuple[float, float]: 

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

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

521 

522 

523# -------------------------------------------------------------------- 

524# Implementation wrapper 

525 

526 

527class SupportsGetData(Protocol): 

528 def getdata( 

529 self, 

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

531 

532 

533class Image: 

534 """ 

535 This class represents an image object. To create 

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

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

538 directly. 

539 

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

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

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

543 """ 

544 

545 format: str | None = None 

546 format_description: str | None = None 

547 _close_exclusive_fp_after_loading = True 

548 

549 def __init__(self) -> None: 

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

551 # FIXME: turn mode and size into delegating properties? 

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

553 self._mode = "" 

554 self._size = (0, 0) 

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

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

557 self.readonly = 0 

558 self._exif: Exif | None = None 

559 

560 @property 

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

562 if isinstance(self._im, DeferredError): 

563 raise self._im.ex 

564 assert self._im is not None 

565 return self._im 

566 

567 @im.setter 

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

569 self._im = im 

570 

571 @property 

572 def width(self) -> int: 

573 return self.size[0] 

574 

575 @property 

576 def height(self) -> int: 

577 return self.size[1] 

578 

579 @property 

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

581 return self._size 

582 

583 @property 

584 def mode(self) -> str: 

585 return self._mode 

586 

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

588 new = Image() 

589 new.im = im 

590 new._mode = im.mode 

591 new._size = im.size 

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

593 if self.palette: 

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

595 else: 

596 from . import ImagePalette 

597 

598 new.palette = ImagePalette.ImagePalette() 

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

600 return new 

601 

602 # Context manager support 

603 def __enter__(self): 

604 return self 

605 

606 def _close_fp(self): 

607 if getattr(self, "_fp", False): 

608 if self._fp != self.fp: 

609 self._fp.close() 

610 self._fp = DeferredError(ValueError("Operation on closed image")) 

611 if self.fp: 

612 self.fp.close() 

613 

614 def __exit__(self, *args): 

615 if hasattr(self, "fp"): 

616 if getattr(self, "_exclusive_fp", False): 

617 self._close_fp() 

618 self.fp = None 

619 

620 def close(self) -> None: 

621 """ 

622 Closes the file pointer, if possible. 

623 

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

625 The image data will be unusable afterward. 

626 

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

628 have not had their file read and closed by the 

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

630 more information. 

631 """ 

632 if hasattr(self, "fp"): 

633 try: 

634 self._close_fp() 

635 self.fp = None 

636 except Exception as msg: 

637 logger.debug("Error closing: %s", msg) 

638 

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

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

641 

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

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

644 # object is gone. 

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

646 

647 def _copy(self) -> None: 

648 self.load() 

649 self.im = self.im.copy() 

650 self.readonly = 0 

651 

652 def _ensure_mutable(self) -> None: 

653 if self.readonly: 

654 self._copy() 

655 else: 

656 self.load() 

657 

658 def _dump( 

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

660 ) -> str: 

661 suffix = "" 

662 if format: 

663 suffix = f".{format}" 

664 

665 if not file: 

666 f, filename = tempfile.mkstemp(suffix) 

667 os.close(f) 

668 else: 

669 filename = file 

670 if not filename.endswith(suffix): 

671 filename = filename + suffix 

672 

673 self.load() 

674 

675 if not format or format == "PPM": 

676 self.im.save_ppm(filename) 

677 else: 

678 self.save(filename, format, **options) 

679 

680 return filename 

681 

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

683 if self.__class__ is not other.__class__: 

684 return False 

685 assert isinstance(other, Image) 

686 return ( 

687 self.mode == other.mode 

688 and self.size == other.size 

689 and self.info == other.info 

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

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

692 ) 

693 

694 def __repr__(self) -> str: 

695 return ( 

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

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

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

699 ) 

700 

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

702 """IPython plain text display support""" 

703 

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

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

706 p.text( 

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

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

709 ) 

710 

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

712 """Helper function for iPython display hook. 

713 

714 :param image_format: Image format. 

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

716 """ 

717 b = io.BytesIO() 

718 try: 

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

720 except Exception: 

721 return None 

722 return b.getvalue() 

723 

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

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

726 

727 :returns: PNG version of the image as bytes 

728 """ 

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

730 

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

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

733 

734 :returns: JPEG version of the image as bytes 

735 """ 

736 return self._repr_image("JPEG") 

737 

738 @property 

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

740 # numpy array interface support 

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

742 if self.mode == "1": 

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

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

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

746 else: 

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

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

749 return new 

750 

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

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

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

754 

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

756 Image.__init__(self) 

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

758 self.info = info 

759 self._mode = mode 

760 self._size = size 

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

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

763 self.putpalette(palette) 

764 self.frombytes(data) 

765 

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

767 """ 

768 Return image as a bytes object. 

769 

770 .. warning:: 

771 

772 This method returns the raw image data from the internal 

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

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

775 data. 

776 

777 :param encoder_name: What encoder to use. The default is to 

778 use the standard "raw" encoder. 

779 

780 A list of C encoders can be seen under 

781 codecs section of the function array in 

782 :file:`_imaging.c`. Python encoders are 

783 registered within the relevant plugins. 

784 :param args: Extra arguments to the encoder. 

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

786 """ 

787 

788 encoder_args: Any = args 

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

790 # may pass tuple instead of argument list 

791 encoder_args = encoder_args[0] 

792 

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

794 encoder_args = self.mode 

795 

796 self.load() 

797 

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

799 return b"" 

800 

801 # unpack data 

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

803 e.setimage(self.im) 

804 

805 bufsize = max(65536, self.size[0] * 4) # see RawEncode.c 

806 

807 output = [] 

808 while True: 

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

810 output.append(data) 

811 if errcode: 

812 break 

813 if errcode < 0: 

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

815 raise RuntimeError(msg) 

816 

817 return b"".join(output) 

818 

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

820 """ 

821 Returns the image converted to an X11 bitmap. 

822 

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

824 

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

826 :returns: A string containing an X11 bitmap. 

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

828 """ 

829 

830 self.load() 

831 if self.mode != "1": 

832 msg = "not a bitmap" 

833 raise ValueError(msg) 

834 data = self.tobytes("xbm") 

835 return b"".join( 

836 [ 

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

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

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

840 data, 

841 b"};", 

842 ] 

843 ) 

844 

845 def frombytes( 

846 self, 

847 data: bytes | bytearray | SupportsArrayInterface, 

848 decoder_name: str = "raw", 

849 *args: Any, 

850 ) -> None: 

851 """ 

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

853 

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

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

856 """ 

857 

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

859 return 

860 

861 decoder_args: Any = args 

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

863 # may pass tuple instead of argument list 

864 decoder_args = decoder_args[0] 

865 

866 # default format 

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

868 decoder_args = self.mode 

869 

870 # unpack data 

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

872 d.setimage(self.im) 

873 s = d.decode(data) 

874 

875 if s[0] >= 0: 

876 msg = "not enough image data" 

877 raise ValueError(msg) 

878 if s[1] != 0: 

879 msg = "cannot decode image data" 

880 raise ValueError(msg) 

881 

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

883 """ 

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

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

886 Image class automatically loads an opened image when it is 

887 accessed for the first time. 

888 

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

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

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

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

893 

894 :returns: An image access object. 

895 :rtype: :py:class:`.PixelAccess` 

896 """ 

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

898 # realize palette 

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

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

901 self.palette.dirty = 0 

902 self.palette.rawmode = None 

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

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

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

906 else: 

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

908 self.palette.mode = "RGBA" 

909 else: 

910 self.palette.palette = self.im.getpalette( 

911 self.palette.mode, self.palette.mode 

912 ) 

913 

914 if self._im is not None: 

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

916 return None 

917 

918 def verify(self) -> None: 

919 """ 

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

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

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

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

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

925 file. 

926 """ 

927 pass 

928 

929 def convert( 

930 self, 

931 mode: str | None = None, 

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

933 dither: Dither | None = None, 

934 palette: Palette = Palette.WEB, 

935 colors: int = 256, 

936 ) -> Image: 

937 """ 

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

939 method translates pixels through the palette. If mode is 

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

941 and the palette can be represented without a palette. 

942 

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

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

945 

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

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

948 

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

950 

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

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

953 dither to approximate the original image luminosity levels. If 

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

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

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

957 

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

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

960 and ``dither`` and ``palette`` are ignored. 

961 

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

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

964 

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

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

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

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

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

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

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

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

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

974 :data:`Palette.ADAPTIVE`. 

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

976 palette. Defaults to 256. 

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

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

979 """ 

980 

981 if mode in ("BGR;15", "BGR;16", "BGR;24"): 

982 deprecate(mode, 12) 

983 

984 self.load() 

985 

986 has_transparency = "transparency" in self.info 

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

988 # determine default mode 

989 if self.palette: 

990 mode = self.palette.mode 

991 else: 

992 mode = "RGB" 

993 if mode == "RGB" and has_transparency: 

994 mode = "RGBA" 

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

996 return self.copy() 

997 

998 if matrix: 

999 # matrix conversion 

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

1001 msg = "illegal conversion" 

1002 raise ValueError(msg) 

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

1004 new_im = self._new(im) 

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

1006 transparency = new_im.info["transparency"] 

1007 

1008 def convert_transparency( 

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

1010 ) -> int: 

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

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

1013 

1014 if mode == "L": 

1015 transparency = convert_transparency(matrix, transparency) 

1016 elif len(mode) == 3: 

1017 transparency = tuple( 

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

1019 for i in range(0, len(transparency)) 

1020 ) 

1021 new_im.info["transparency"] = transparency 

1022 return new_im 

1023 

1024 if mode == "P" and self.mode == "RGBA": 

1025 return self.quantize(colors) 

1026 

1027 trns = None 

1028 delete_trns = False 

1029 # transparency handling 

1030 if has_transparency: 

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

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

1033 ): 

1034 # Use transparent conversion to promote from transparent 

1035 # color to an alpha channel. 

1036 new_im = self._new( 

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

1038 ) 

1039 del new_im.info["transparency"] 

1040 return new_im 

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

1042 t = self.info["transparency"] 

1043 if isinstance(t, bytes): 

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

1045 warnings.warn( 

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

1047 "converted to RGBA images" 

1048 ) 

1049 delete_trns = True 

1050 else: 

1051 # get the new transparency color. 

1052 # use existing conversions 

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

1054 if self.mode == "P": 

1055 assert self.palette is not None 

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

1057 if isinstance(t, tuple): 

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

1059 assert trns_im.palette is not None 

1060 try: 

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

1062 except ValueError as e: 

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

1064 # If all 256 colors are in use, 

1065 # then there is no need for transparency 

1066 t = None 

1067 else: 

1068 raise ValueError(err) from e 

1069 if t is None: 

1070 trns = None 

1071 else: 

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

1073 

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

1075 trns_im = trns_im.convert(mode) 

1076 else: 

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

1078 # after quantization. 

1079 trns_im = trns_im.convert("RGB") 

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

1081 

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

1083 t = self.info["transparency"] 

1084 delete_trns = True 

1085 

1086 if isinstance(t, bytes): 

1087 self.im.putpalettealphas(t) 

1088 elif isinstance(t, int): 

1089 self.im.putpalettealpha(t, 0) 

1090 else: 

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

1092 raise ValueError(msg) 

1093 

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

1095 im = self.im.quantize(colors) 

1096 new_im = self._new(im) 

1097 from . import ImagePalette 

1098 

1099 new_im.palette = ImagePalette.ImagePalette( 

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

1101 ) 

1102 if delete_trns: 

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

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

1105 del new_im.info["transparency"] 

1106 if trns is not None: 

1107 try: 

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

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

1110 new_im, 

1111 ) 

1112 except Exception: 

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

1114 # transparency hanging around to mess us up. 

1115 del new_im.info["transparency"] 

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

1117 return new_im 

1118 

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

1120 im = self 

1121 if mode == "LAB": 

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

1123 im = im.convert("RGBA") 

1124 other_mode = im.mode 

1125 else: 

1126 other_mode = mode 

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

1128 from . import ImageCms 

1129 

1130 srgb = ImageCms.createProfile("sRGB") 

1131 lab = ImageCms.createProfile("LAB") 

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

1133 transform = ImageCms.buildTransform( 

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

1135 ) 

1136 return transform.apply(im) 

1137 

1138 # colorspace conversion 

1139 if dither is None: 

1140 dither = Dither.FLOYDSTEINBERG 

1141 

1142 try: 

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

1144 except ValueError: 

1145 try: 

1146 # normalize source image and try again 

1147 modebase = getmodebase(self.mode) 

1148 if modebase == self.mode: 

1149 raise 

1150 im = self.im.convert(modebase) 

1151 im = im.convert(mode, dither) 

1152 except KeyError as e: 

1153 msg = "illegal conversion" 

1154 raise ValueError(msg) from e 

1155 

1156 new_im = self._new(im) 

1157 if mode == "P" and palette != Palette.ADAPTIVE: 

1158 from . import ImagePalette 

1159 

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

1161 if delete_trns: 

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

1163 del new_im.info["transparency"] 

1164 if trns is not None: 

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

1166 try: 

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

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

1169 ) 

1170 except ValueError as e: 

1171 del new_im.info["transparency"] 

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

1173 # If all 256 colors are in use, 

1174 # then there is no need for transparency 

1175 warnings.warn( 

1176 "Couldn't allocate palette entry for transparency" 

1177 ) 

1178 else: 

1179 new_im.info["transparency"] = trns 

1180 return new_im 

1181 

1182 def quantize( 

1183 self, 

1184 colors: int = 256, 

1185 method: int | None = None, 

1186 kmeans: int = 0, 

1187 palette: Image | None = None, 

1188 dither: Dither = Dither.FLOYDSTEINBERG, 

1189 ) -> Image: 

1190 """ 

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

1192 of colors. 

1193 

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

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

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

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

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

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

1200 ``feature="libimagequant"``). 

1201 

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

1203 

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

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

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

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

1208 :param palette: Quantize to the palette of given 

1209 :py:class:`PIL.Image.Image`. 

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

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

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

1213 (default). 

1214 :returns: A new image 

1215 """ 

1216 

1217 self.load() 

1218 

1219 if method is None: 

1220 # defaults: 

1221 method = Quantize.MEDIANCUT 

1222 if self.mode == "RGBA": 

1223 method = Quantize.FASTOCTREE 

1224 

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

1226 Quantize.FASTOCTREE, 

1227 Quantize.LIBIMAGEQUANT, 

1228 ): 

1229 # Caller specified an invalid mode. 

1230 msg = ( 

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

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

1233 ) 

1234 raise ValueError(msg) 

1235 

1236 if palette: 

1237 # use palette from reference image 

1238 palette.load() 

1239 if palette.mode != "P": 

1240 msg = "bad mode for palette image" 

1241 raise ValueError(msg) 

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

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

1244 raise ValueError(msg) 

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

1246 new_im = self._new(im) 

1247 assert palette.palette is not None 

1248 new_im.palette = palette.palette.copy() 

1249 return new_im 

1250 

1251 if kmeans < 0: 

1252 msg = "kmeans must not be negative" 

1253 raise ValueError(msg) 

1254 

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

1256 

1257 from . import ImagePalette 

1258 

1259 mode = im.im.getpalettemode() 

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

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

1262 

1263 return im 

1264 

1265 def copy(self) -> Image: 

1266 """ 

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

1268 into an image, but still retain the original. 

1269 

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

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

1272 """ 

1273 self.load() 

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

1275 

1276 __copy__ = copy 

1277 

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

1279 """ 

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

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

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

1283 

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

1285 

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

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

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

1289 """ 

1290 

1291 if box is None: 

1292 return self.copy() 

1293 

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

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

1296 raise ValueError(msg) 

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

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

1299 raise ValueError(msg) 

1300 

1301 self.load() 

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

1303 

1304 def _crop( 

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

1306 ) -> core.ImagingCore: 

1307 """ 

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

1309 

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

1311 includes additional sanity checks. 

1312 

1313 :param im: a core image object 

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

1315 :returns: A core image object. 

1316 """ 

1317 

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

1319 

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

1321 

1322 _decompression_bomb_check(absolute_values) 

1323 

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

1325 

1326 def draft( 

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

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

1329 """ 

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

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

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

1333 JPEG to grayscale while loading it. 

1334 

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

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

1337 

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

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

1340 effect. 

1341 

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

1343 currently implemented only for JPEG and MPO images. 

1344 

1345 :param mode: The requested mode. 

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

1347 (width, height). 

1348 """ 

1349 pass 

1350 

1351 def _expand(self, xmargin: int, ymargin: int | None = None) -> Image: 

1352 if ymargin is None: 

1353 ymargin = xmargin 

1354 self.load() 

1355 return self._new(self.im.expand(xmargin, ymargin)) 

1356 

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

1358 """ 

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

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

1361 

1362 :param filter: Filter kernel. 

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

1364 

1365 from . import ImageFilter 

1366 

1367 self.load() 

1368 

1369 if callable(filter): 

1370 filter = filter() 

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

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

1373 raise TypeError(msg) 

1374 

1375 multiband = isinstance(filter, ImageFilter.MultibandFilter) 

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

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

1378 

1379 ims = [ 

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

1381 ] 

1382 return merge(self.mode, ims) 

1383 

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

1385 """ 

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

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

1388 

1389 :returns: A tuple containing band names. 

1390 :rtype: tuple 

1391 """ 

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

1393 

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

1395 """ 

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

1397 image. 

1398 

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

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

1401 Otherwise, trim pixels when all channels are zero. 

1402 Keyword-only argument. 

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

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

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

1406 method returns None. 

1407 

1408 """ 

1409 

1410 self.load() 

1411 return self.im.getbbox(alpha_only) 

1412 

1413 def getcolors( 

1414 self, maxcolors: int = 256 

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

1416 """ 

1417 Returns a list of colors used in this image. 

1418 

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

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

1421 return the index of the color in the palette. 

1422 

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

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

1425 256 colors. 

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

1427 """ 

1428 

1429 self.load() 

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

1431 h = self.im.histogram() 

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

1433 if len(out) > maxcolors: 

1434 return None 

1435 return out 

1436 return self.im.getcolors(maxcolors) 

1437 

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

1439 """ 

1440 Returns the contents of this image as a sequence object 

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

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

1443 line zero, and so on. 

1444 

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

1446 internal PIL data type, which only supports certain sequence 

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

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

1449 

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

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

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

1453 :returns: A sequence-like object. 

1454 """ 

1455 

1456 self.load() 

1457 if band is not None: 

1458 return self.im.getband(band) 

1459 return self.im # could be abused 

1460 

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

1462 """ 

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

1464 the image. 

1465 

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

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

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

1469 """ 

1470 

1471 self.load() 

1472 if self.im.bands > 1: 

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

1474 return self.im.getextrema() 

1475 

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

1477 """ 

1478 Returns a dictionary containing the XMP tags. 

1479 Requires defusedxml to be installed. 

1480 

1481 :returns: XMP tags in a dictionary. 

1482 """ 

1483 

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

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

1486 

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

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

1489 children = list(element) 

1490 if children: 

1491 for child in children: 

1492 name = get_name(child.tag) 

1493 child_value = get_value(child) 

1494 if name in value: 

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

1496 value[name] = [value[name]] 

1497 value[name].append(child_value) 

1498 else: 

1499 value[name] = child_value 

1500 elif value: 

1501 if element.text: 

1502 value["text"] = element.text 

1503 else: 

1504 return element.text 

1505 return value 

1506 

1507 if ElementTree is None: 

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

1509 return {} 

1510 if "xmp" not in self.info: 

1511 return {} 

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

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

1514 

1515 def getexif(self) -> Exif: 

1516 """ 

1517 Gets EXIF data from the image. 

1518 

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

1520 """ 

1521 if self._exif is None: 

1522 self._exif = Exif() 

1523 elif self._exif._loaded: 

1524 return self._exif 

1525 self._exif._loaded = True 

1526 

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

1528 if exif_info is None: 

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

1530 exif_info = bytes.fromhex( 

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

1532 ) 

1533 elif hasattr(self, "tag_v2"): 

1534 self._exif.bigtiff = self.tag_v2._bigtiff 

1535 self._exif.endian = self.tag_v2._endian 

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

1537 if exif_info is not None: 

1538 self._exif.load(exif_info) 

1539 

1540 # XMP tags 

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

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

1543 if xmp_tags: 

1544 match = re.search(r'tiff:Orientation(="|>)([0-9])', xmp_tags) 

1545 if match: 

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

1547 

1548 return self._exif 

1549 

1550 def _reload_exif(self) -> None: 

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

1552 return 

1553 self._exif._loaded = False 

1554 self.getexif() 

1555 

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

1557 child_images = [] 

1558 exif = self.getexif() 

1559 ifds = [] 

1560 if ExifTags.Base.SubIFDs in exif: 

1561 subifd_offsets = exif[ExifTags.Base.SubIFDs] 

1562 if subifd_offsets: 

1563 if not isinstance(subifd_offsets, tuple): 

1564 subifd_offsets = (subifd_offsets,) 

1565 for subifd_offset in subifd_offsets: 

1566 ifds.append((exif._get_ifd_dict(subifd_offset), subifd_offset)) 

1567 ifd1 = exif.get_ifd(ExifTags.IFD.IFD1) 

1568 if ifd1 and ifd1.get(ExifTags.Base.JpegIFOffset): 

1569 assert exif._info is not None 

1570 ifds.append((ifd1, exif._info.next)) 

1571 

1572 offset = None 

1573 for ifd, ifd_offset in ifds: 

1574 current_offset = self.fp.tell() 

1575 if offset is None: 

1576 offset = current_offset 

1577 

1578 fp = self.fp 

1579 if ifd is not None: 

1580 thumbnail_offset = ifd.get(ExifTags.Base.JpegIFOffset) 

1581 if thumbnail_offset is not None: 

1582 thumbnail_offset += getattr(self, "_exif_offset", 0) 

1583 self.fp.seek(thumbnail_offset) 

1584 data = self.fp.read(ifd.get(ExifTags.Base.JpegIFByteCount)) 

1585 fp = io.BytesIO(data) 

1586 

1587 with open(fp) as im: 

1588 from . import TiffImagePlugin 

1589 

1590 if thumbnail_offset is None and isinstance( 

1591 im, TiffImagePlugin.TiffImageFile 

1592 ): 

1593 im._frame_pos = [ifd_offset] 

1594 im._seek(0) 

1595 im.load() 

1596 child_images.append(im) 

1597 

1598 if offset is not None: 

1599 self.fp.seek(offset) 

1600 return child_images 

1601 

1602 def getim(self) -> CapsuleType: 

1603 """ 

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

1605 

1606 :returns: A capsule object. 

1607 """ 

1608 

1609 self.load() 

1610 return self.im.ptr 

1611 

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

1613 """ 

1614 Returns the image palette as a list. 

1615 

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

1617 return the palette in its current mode. 

1618 

1619 .. versionadded:: 9.1.0 

1620 

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

1622 image has no palette. 

1623 """ 

1624 

1625 self.load() 

1626 try: 

1627 mode = self.im.getpalettemode() 

1628 except ValueError: 

1629 return None # no palette 

1630 if rawmode is None: 

1631 rawmode = mode 

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

1633 

1634 @property 

1635 def has_transparency_data(self) -> bool: 

1636 """ 

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

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

1639 in the info dictionary. 

1640 

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

1642 within are opaque. 

1643 

1644 :returns: A boolean. 

1645 """ 

1646 if ( 

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

1648 or "transparency" in self.info 

1649 ): 

1650 return True 

1651 if self.mode == "P": 

1652 assert self.palette is not None 

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

1654 return False 

1655 

1656 def apply_transparency(self) -> None: 

1657 """ 

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

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

1660 Otherwise, the image is unchanged. 

1661 """ 

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

1663 return 

1664 

1665 from . import ImagePalette 

1666 

1667 palette = self.getpalette("RGBA") 

1668 assert palette is not None 

1669 transparency = self.info["transparency"] 

1670 if isinstance(transparency, bytes): 

1671 for i, alpha in enumerate(transparency): 

1672 palette[i * 4 + 3] = alpha 

1673 else: 

1674 palette[transparency * 4 + 3] = 0 

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

1676 self.palette.dirty = 1 

1677 

1678 del self.info["transparency"] 

1679 

1680 def getpixel( 

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

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

1683 """ 

1684 Returns the pixel value at a given position. 

1685 

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

1687 :ref:`coordinate-system`. 

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

1689 this method returns a tuple. 

1690 """ 

1691 

1692 self.load() 

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

1694 

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

1696 """ 

1697 Get projection to x and y axes 

1698 

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

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

1701 """ 

1702 

1703 self.load() 

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

1705 return list(x), list(y) 

1706 

1707 def histogram( 

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

1709 ) -> list[int]: 

1710 """ 

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

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

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

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

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

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

1717 

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

1719 by this method. 

1720 

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

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

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

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

1725 

1726 :param mask: An optional mask. 

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

1728 :returns: A list containing pixel counts. 

1729 """ 

1730 self.load() 

1731 if mask: 

1732 mask.load() 

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

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

1735 return self.im.histogram( 

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

1737 ) 

1738 return self.im.histogram() 

1739 

1740 def entropy( 

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

1742 ) -> float: 

1743 """ 

1744 Calculates and returns the entropy for the image. 

1745 

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

1747 image by this method. 

1748 

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

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

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

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

1753 

1754 :param mask: An optional mask. 

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

1756 :returns: A float value representing the image entropy 

1757 """ 

1758 self.load() 

1759 if mask: 

1760 mask.load() 

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

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

1763 return self.im.entropy( 

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

1765 ) 

1766 return self.im.entropy() 

1767 

1768 def paste( 

1769 self, 

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

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

1772 mask: Image | None = None, 

1773 ) -> None: 

1774 """ 

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

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

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

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

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

1780 

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

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

1783 details). 

1784 

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

1786 containing pixel values. The method then fills the region 

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

1788 also use color strings as supported by the ImageColor module. 

1789 

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

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

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

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

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

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

1796 channels if they have them. 

1797 

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

1799 combine images with respect to their alpha channels. 

1800 

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

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

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

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

1805 upper left corner. 

1806 

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

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

1809 is interpreted as a mask image. 

1810 :param mask: An optional mask image. 

1811 """ 

1812 

1813 if isinstance(box, Image): 

1814 if mask is not None: 

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

1816 raise ValueError(msg) 

1817 # abbreviated paste(im, mask) syntax 

1818 mask = box 

1819 box = None 

1820 

1821 if box is None: 

1822 box = (0, 0) 

1823 

1824 if len(box) == 2: 

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

1826 if isinstance(im, Image): 

1827 size = im.size 

1828 elif isinstance(mask, Image): 

1829 size = mask.size 

1830 else: 

1831 # FIXME: use self.size here? 

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

1833 raise ValueError(msg) 

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

1835 

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

1837 if isinstance(im, str): 

1838 from . import ImageColor 

1839 

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

1841 elif isinstance(im, Image): 

1842 im.load() 

1843 if self.mode != im.mode: 

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

1845 # should use an adapter for this! 

1846 im = im.convert(self.mode) 

1847 source = im.im 

1848 else: 

1849 source = im 

1850 

1851 self._ensure_mutable() 

1852 

1853 if mask: 

1854 mask.load() 

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

1856 else: 

1857 self.im.paste(source, box) 

1858 

1859 def alpha_composite( 

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

1861 ) -> None: 

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

1863 onto this image. 

1864 

1865 :param im: image to composite over this one 

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

1867 left corner in this (destination) image. 

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

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

1870 bottom) for the bounds of the source rectangle 

1871 

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

1873 """ 

1874 

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

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

1877 raise ValueError(msg) 

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

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

1880 raise ValueError(msg) 

1881 

1882 if len(source) == 4: 

1883 overlay_crop_box = tuple(source) 

1884 elif len(source) == 2: 

1885 overlay_crop_box = tuple(source) + im.size 

1886 else: 

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

1888 raise ValueError(msg) 

1889 

1890 if not len(dest) == 2: 

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

1892 raise ValueError(msg) 

1893 if min(source) < 0: 

1894 msg = "Source must be non-negative" 

1895 raise ValueError(msg) 

1896 

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

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

1899 overlay = im 

1900 else: 

1901 overlay = im.crop(overlay_crop_box) 

1902 

1903 # target for the paste 

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

1905 

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

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

1908 background = self 

1909 else: 

1910 background = self.crop(box) 

1911 

1912 result = alpha_composite(background, overlay) 

1913 self.paste(result, box) 

1914 

1915 def point( 

1916 self, 

1917 lut: ( 

1918 Sequence[float] 

1919 | NumpyArray 

1920 | Callable[[int], float] 

1921 | Callable[[ImagePointTransform], ImagePointTransform | float] 

1922 | ImagePointHandler 

1923 ), 

1924 mode: str | None = None, 

1925 ) -> Image: 

1926 """ 

1927 Maps this image through a lookup table or function. 

1928 

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

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

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

1932 single argument. The function is called once for each 

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

1934 all bands of the image. 

1935 

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

1937 object:: 

1938 

1939 class Example(Image.ImagePointHandler): 

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

1941 # Return result 

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

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

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

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

1946 """ 

1947 

1948 self.load() 

1949 

1950 if isinstance(lut, ImagePointHandler): 

1951 return lut.point(self) 

1952 

1953 if callable(lut): 

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

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

1956 # check if the function can be used with point_transform 

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

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

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

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

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

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

1963 else: 

1964 flatLut = lut 

1965 

1966 if self.mode == "F": 

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

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

1969 raise ValueError(msg) 

1970 

1971 if mode != "F": 

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

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

1974 

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

1976 """ 

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

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

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

1980 

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

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

1983 """ 

1984 

1985 self._ensure_mutable() 

1986 

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

1988 # attempt to promote self to a matching alpha mode 

1989 try: 

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

1991 try: 

1992 self.im.setmode(mode) 

1993 except (AttributeError, ValueError) as e: 

1994 # do things the hard way 

1995 im = self.im.convert(mode) 

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

1997 msg = "alpha channel could not be added" 

1998 raise ValueError(msg) from e # sanity check 

1999 self.im = im 

2000 self._mode = self.im.mode 

2001 except KeyError as e: 

2002 msg = "illegal image mode" 

2003 raise ValueError(msg) from e 

2004 

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

2006 band = 1 

2007 else: 

2008 band = 3 

2009 

2010 if isinstance(alpha, Image): 

2011 # alpha layer 

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

2013 msg = "illegal image mode" 

2014 raise ValueError(msg) 

2015 alpha.load() 

2016 if alpha.mode == "1": 

2017 alpha = alpha.convert("L") 

2018 else: 

2019 # constant alpha 

2020 try: 

2021 self.im.fillband(band, alpha) 

2022 except (AttributeError, ValueError): 

2023 # do things the hard way 

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

2025 else: 

2026 return 

2027 

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

2029 

2030 def putdata( 

2031 self, 

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

2033 scale: float = 1.0, 

2034 offset: float = 0.0, 

2035 ) -> None: 

2036 """ 

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

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

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

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

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

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

2043 

2044 :param data: A flattened sequence object. 

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

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

2047 """ 

2048 

2049 self._ensure_mutable() 

2050 

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

2052 

2053 def putpalette( 

2054 self, 

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

2056 rawmode: str = "RGB", 

2057 ) -> None: 

2058 """ 

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

2060 or "LA" image. 

2061 

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

2063 integer value for each channel in the raw mode. 

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

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

2066 index in the 256 colors. 

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

2068 containing red, green, blue and alpha values. 

2069 

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

2071 

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

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

2074 that can be transformed to "RGB" or "RGBA" (e.g. "R", "BGR;15", "RGBA;L"). 

2075 """ 

2076 from . import ImagePalette 

2077 

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

2079 msg = "illegal image mode" 

2080 raise ValueError(msg) 

2081 if isinstance(data, ImagePalette.ImagePalette): 

2082 if data.rawmode is not None: 

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

2084 else: 

2085 palette = ImagePalette.ImagePalette(palette=data.palette) 

2086 palette.dirty = 1 

2087 else: 

2088 if not isinstance(data, bytes): 

2089 data = bytes(data) 

2090 palette = ImagePalette.raw(rawmode, data) 

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

2092 self.palette = palette 

2093 self.palette.mode = "RGBA" if "A" in rawmode else "RGB" 

2094 self.load() # install new palette 

2095 

2096 def putpixel( 

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

2098 ) -> None: 

2099 """ 

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

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

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

2103 accepted for P and PA images. 

2104 

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

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

2107 module instead. 

2108 

2109 See: 

2110 

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

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

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

2114 

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

2116 :ref:`coordinate-system`. 

2117 :param value: The pixel value. 

2118 """ 

2119 

2120 if self.readonly: 

2121 self._copy() 

2122 self.load() 

2123 

2124 if ( 

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

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

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

2128 ): 

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

2130 if self.mode == "PA": 

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

2132 value = value[:3] 

2133 assert self.palette is not None 

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

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

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

2137 

2138 def remap_palette( 

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

2140 ) -> Image: 

2141 """ 

2142 Rewrites the image to reorder the palette. 

2143 

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

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

2146 is the identity transform. 

2147 :param source_palette: Bytes or None. 

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

2149 

2150 """ 

2151 from . import ImagePalette 

2152 

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

2154 msg = "illegal image mode" 

2155 raise ValueError(msg) 

2156 

2157 bands = 3 

2158 palette_mode = "RGB" 

2159 if source_palette is None: 

2160 if self.mode == "P": 

2161 self.load() 

2162 palette_mode = self.im.getpalettemode() 

2163 if palette_mode == "RGBA": 

2164 bands = 4 

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

2166 else: # L-mode 

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

2168 elif len(source_palette) > 768: 

2169 bands = 4 

2170 palette_mode = "RGBA" 

2171 

2172 palette_bytes = b"" 

2173 new_positions = [0] * 256 

2174 

2175 # pick only the used colors from the palette 

2176 for i, oldPosition in enumerate(dest_map): 

2177 palette_bytes += source_palette[ 

2178 oldPosition * bands : oldPosition * bands + bands 

2179 ] 

2180 new_positions[oldPosition] = i 

2181 

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

2183 

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

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

2186 # from palette 1 to palette 2. New_positions is 

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

2188 # palette 1 with any holes removed. 

2189 

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

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

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

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

2194 # sans palette thus converting the image bytes, then 

2195 # assigning the optimized RGB palette. 

2196 

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

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

2199 

2200 mapping_palette = bytearray(new_positions) 

2201 

2202 m_im = self.copy() 

2203 m_im._mode = "P" 

2204 

2205 m_im.palette = ImagePalette.ImagePalette( 

2206 palette_mode, palette=mapping_palette * bands 

2207 ) 

2208 # possibly set palette dirty, then 

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

2210 # or just force it. 

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

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

2213 

2214 m_im = m_im.convert("L") 

2215 

2216 m_im.putpalette(palette_bytes, palette_mode) 

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

2218 

2219 if "transparency" in self.info: 

2220 try: 

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

2222 except ValueError: 

2223 if "transparency" in m_im.info: 

2224 del m_im.info["transparency"] 

2225 

2226 return m_im 

2227 

2228 def _get_safe_box( 

2229 self, 

2230 size: tuple[int, int], 

2231 resample: Resampling, 

2232 box: tuple[float, float, float, float], 

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

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

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

2236 """ 

2237 filter_support = _filters_support[resample] - 0.5 

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

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

2240 support_x = filter_support * scale_x 

2241 support_y = filter_support * scale_y 

2242 

2243 return ( 

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

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

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

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

2248 ) 

2249 

2250 def resize( 

2251 self, 

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

2253 resample: int | None = None, 

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

2255 reducing_gap: float | None = None, 

2256 ) -> Image: 

2257 """ 

2258 Returns a resized copy of this image. 

2259 

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

2261 (width, height). 

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

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

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

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

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

2267 :py:data:`Resampling.NEAREST`. If the image mode is "BGR;15", 

2268 "BGR;16" or "BGR;24", then the default filter is 

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

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

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

2272 the source image region to be scaled. 

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

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

2275 :param reducing_gap: Apply optimization by resizing the image 

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

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

2278 Second, resizing using regular resampling. The last step 

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

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

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

2282 the closer the result to the fair resampling. 

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

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

2285 indistinguishable from fair resampling in most cases. 

2286 The default value is None (no optimization). 

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

2288 """ 

2289 

2290 if resample is None: 

2291 bgr = self.mode.startswith("BGR;") 

2292 resample = Resampling.NEAREST if bgr else Resampling.BICUBIC 

2293 elif resample not in ( 

2294 Resampling.NEAREST, 

2295 Resampling.BILINEAR, 

2296 Resampling.BICUBIC, 

2297 Resampling.LANCZOS, 

2298 Resampling.BOX, 

2299 Resampling.HAMMING, 

2300 ): 

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

2302 

2303 filters = [ 

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

2305 for filter in ( 

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

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

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

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

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

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

2312 ) 

2313 ] 

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

2315 raise ValueError(msg) 

2316 

2317 if reducing_gap is not None and reducing_gap < 1.0: 

2318 msg = "reducing_gap must be 1.0 or greater" 

2319 raise ValueError(msg) 

2320 

2321 if box is None: 

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

2323 

2324 size = tuple(size) 

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

2326 return self.copy() 

2327 

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

2329 resample = Resampling.NEAREST 

2330 

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

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

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

2334 return im.convert(self.mode) 

2335 

2336 self.load() 

2337 

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

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

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

2341 if factor_x > 1 or factor_y > 1: 

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

2343 factor = (factor_x, factor_y) 

2344 self = ( 

2345 self.reduce(factor, box=reduce_box) 

2346 if callable(self.reduce) 

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

2348 ) 

2349 box = ( 

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

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

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

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

2354 ) 

2355 

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

2357 

2358 def reduce( 

2359 self, 

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

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

2362 ) -> Image: 

2363 """ 

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

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

2366 the resulting size will be rounded up. 

2367 

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

2369 for width and height separately. 

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

2371 the source image region to be reduced. 

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

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

2374 """ 

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

2376 factor = (factor, factor) 

2377 

2378 if box is None: 

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

2380 

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

2382 return self.copy() 

2383 

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

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

2386 im = im.reduce(factor, box) 

2387 return im.convert(self.mode) 

2388 

2389 self.load() 

2390 

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

2392 

2393 def rotate( 

2394 self, 

2395 angle: float, 

2396 resample: Resampling = Resampling.NEAREST, 

2397 expand: int | bool = False, 

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

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

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

2401 ) -> Image: 

2402 """ 

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

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

2405 clockwise around its centre. 

2406 

2407 :param angle: In degrees counter clockwise. 

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

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

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

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

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

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

2414 See :ref:`concept-filters`. 

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

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

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

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

2419 the center and no translation. 

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

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

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

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

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

2425 """ 

2426 

2427 angle = angle % 360.0 

2428 

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

2430 # translating or changing the center. 

2431 if not (center or translate): 

2432 if angle == 0: 

2433 return self.copy() 

2434 if angle == 180: 

2435 return self.transpose(Transpose.ROTATE_180) 

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

2437 return self.transpose( 

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

2439 ) 

2440 

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

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

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

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

2445 

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

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

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

2449 # (0, 0, 1) (0, 0, 1) ( 0, 0, 1) (0, 0, 1) 

2450 

2451 # The reverse matrix is thus: 

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

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

2454 # (0, 0, 1) ( 0, 0, 1) (0, 0, 1) (0, 0, 1) 

2455 

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

2457 # compensate for the expand flag. 

2458 

2459 w, h = self.size 

2460 

2461 if translate is None: 

2462 post_trans = (0, 0) 

2463 else: 

2464 post_trans = translate 

2465 if center is None: 

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

2467 

2468 angle = -math.radians(angle) 

2469 matrix = [ 

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

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

2472 0.0, 

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

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

2475 0.0, 

2476 ] 

2477 

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

2479 (a, b, c, d, e, f) = matrix 

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

2481 

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

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

2484 ) 

2485 matrix[2] += center[0] 

2486 matrix[5] += center[1] 

2487 

2488 if expand: 

2489 # calculate output size 

2490 xx = [] 

2491 yy = [] 

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

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

2494 xx.append(transformed_x) 

2495 yy.append(transformed_y) 

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

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

2498 

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

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

2501 # translation vector as new translation vector. 

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

2503 w, h = nw, nh 

2504 

2505 return self.transform( 

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

2507 ) 

2508 

2509 def save( 

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

2511 ) -> None: 

2512 """ 

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

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

2515 extension, if possible. 

2516 

2517 Keyword options can be used to provide additional instructions 

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

2519 silently ignored. The available options are described in the 

2520 :doc:`image format documentation 

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

2522 

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

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

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

2526 methods, and be opened in binary mode. 

2527 

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

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

2530 format to use is determined from the filename extension. 

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

2532 parameter should always be used. 

2533 :param params: Extra parameters to the image writer. 

2534 :returns: None 

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

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

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

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

2539 """ 

2540 

2541 filename: str | bytes = "" 

2542 open_fp = False 

2543 if is_path(fp): 

2544 filename = os.fspath(fp) 

2545 open_fp = True 

2546 elif fp == sys.stdout: 

2547 try: 

2548 fp = sys.stdout.buffer 

2549 except AttributeError: 

2550 pass 

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

2552 # only set the name for metadata purposes 

2553 filename = os.fspath(fp.name) 

2554 

2555 # may mutate self! 

2556 self._ensure_mutable() 

2557 

2558 save_all = params.pop("save_all", False) 

2559 self.encoderinfo = {**getattr(self, "encoderinfo", {}), **params} 

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

2561 

2562 preinit() 

2563 

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

2565 ext = filename_ext.decode() if isinstance(filename_ext, bytes) else filename_ext 

2566 

2567 if not format: 

2568 if ext not in EXTENSION: 

2569 init() 

2570 try: 

2571 format = EXTENSION[ext] 

2572 except KeyError as e: 

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

2574 raise ValueError(msg) from e 

2575 

2576 if format.upper() not in SAVE: 

2577 init() 

2578 if save_all: 

2579 save_handler = SAVE_ALL[format.upper()] 

2580 else: 

2581 save_handler = SAVE[format.upper()] 

2582 

2583 created = False 

2584 if open_fp: 

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

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

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

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

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

2590 else: 

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

2592 else: 

2593 fp = cast(IO[bytes], fp) 

2594 

2595 try: 

2596 save_handler(self, fp, filename) 

2597 except Exception: 

2598 if open_fp: 

2599 fp.close() 

2600 if created: 

2601 try: 

2602 os.remove(filename) 

2603 except PermissionError: 

2604 pass 

2605 raise 

2606 finally: 

2607 try: 

2608 del self.encoderinfo 

2609 except AttributeError: 

2610 pass 

2611 if open_fp: 

2612 fp.close() 

2613 

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

2615 """ 

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

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

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

2619 library automatically seeks to frame 0. 

2620 

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

2622 

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

2624 number of available frames. 

2625 

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

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

2628 of the sequence. 

2629 """ 

2630 

2631 # overridden by file handlers 

2632 if frame != 0: 

2633 msg = "no more images in file" 

2634 raise EOFError(msg) 

2635 

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

2637 """ 

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

2639 

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

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

2642 

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

2644 PNG format. 

2645 

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

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

2648 

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

2650 

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

2652 

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

2654 """ 

2655 

2656 _show(self, title=title) 

2657 

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

2659 """ 

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

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

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

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

2664 blue). 

2665 

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

2667 method can be more convenient and faster. 

2668 

2669 :returns: A tuple containing bands. 

2670 """ 

2671 

2672 self.load() 

2673 if self.im.bands == 1: 

2674 return (self.copy(),) 

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

2676 

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

2678 """ 

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

2680 

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

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

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

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

2685 

2686 .. versionadded:: 4.3.0 

2687 """ 

2688 self.load() 

2689 

2690 if isinstance(channel, str): 

2691 try: 

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

2693 except ValueError as e: 

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

2695 raise ValueError(msg) from e 

2696 

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

2698 

2699 def tell(self) -> int: 

2700 """ 

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

2702 

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

2704 number of available frames. 

2705 

2706 :returns: Frame number, starting with 0. 

2707 """ 

2708 return 0 

2709 

2710 def thumbnail( 

2711 self, 

2712 size: tuple[float, float], 

2713 resample: Resampling = Resampling.BICUBIC, 

2714 reducing_gap: float | None = 2.0, 

2715 ) -> None: 

2716 """ 

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

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

2719 the given size. This method calculates an appropriate thumbnail 

2720 size to preserve the aspect of the image, calls the 

2721 :py:meth:`~PIL.Image.Image.draft` method to configure the file reader 

2722 (where applicable), and finally resizes the image. 

2723 

2724 Note that this function modifies the :py:class:`~PIL.Image.Image` 

2725 object in place. If you need to use the full resolution image as well, 

2726 apply this method to a :py:meth:`~PIL.Image.Image.copy` of the original 

2727 image. 

2728 

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

2730 (width, height). 

2731 :param resample: Optional resampling filter. This can be one 

2732 of :py:data:`Resampling.NEAREST`, :py:data:`Resampling.BOX`, 

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

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

2735 If omitted, it defaults to :py:data:`Resampling.BICUBIC`. 

2736 (was :py:data:`Resampling.NEAREST` prior to version 2.5.0). 

2737 See: :ref:`concept-filters`. 

2738 :param reducing_gap: Apply optimization by resizing the image 

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

2740 using :py:meth:`~PIL.Image.Image.reduce` or 

2741 :py:meth:`~PIL.Image.Image.draft` for JPEG images. 

2742 Second, resizing using regular resampling. The last step 

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

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

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

2746 the closer the result to the fair resampling. 

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

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

2749 indistinguishable from fair resampling in most cases. 

2750 The default value is 2.0 (very close to fair resampling 

2751 while still being faster in many cases). 

2752 :returns: None 

2753 """ 

2754 

2755 provided_size = tuple(map(math.floor, size)) 

2756 

2757 def preserve_aspect_ratio() -> tuple[int, int] | None: 

2758 def round_aspect(number: float, key: Callable[[int], float]) -> int: 

2759 return max(min(math.floor(number), math.ceil(number), key=key), 1) 

2760 

2761 x, y = provided_size 

2762 if x >= self.width and y >= self.height: 

2763 return None 

2764 

2765 aspect = self.width / self.height 

2766 if x / y >= aspect: 

2767 x = round_aspect(y * aspect, key=lambda n: abs(aspect - n / y)) 

2768 else: 

2769 y = round_aspect( 

2770 x / aspect, key=lambda n: 0 if n == 0 else abs(aspect - x / n) 

2771 ) 

2772 return x, y 

2773 

2774 preserved_size = preserve_aspect_ratio() 

2775 if preserved_size is None: 

2776 return 

2777 final_size = preserved_size 

2778 

2779 box = None 

2780 if reducing_gap is not None: 

2781 res = self.draft( 

2782 None, (int(size[0] * reducing_gap), int(size[1] * reducing_gap)) 

2783 ) 

2784 if res is not None: 

2785 box = res[1] 

2786 

2787 if self.size != final_size: 

2788 im = self.resize(final_size, resample, box=box, reducing_gap=reducing_gap) 

2789 

2790 self.im = im.im 

2791 self._size = final_size 

2792 self._mode = self.im.mode 

2793 

2794 self.readonly = 0 

2795 

2796 # FIXME: the different transform methods need further explanation 

2797 # instead of bloating the method docs, add a separate chapter. 

2798 def transform( 

2799 self, 

2800 size: tuple[int, int], 

2801 method: Transform | ImageTransformHandler | SupportsGetData, 

2802 data: Sequence[Any] | None = None, 

2803 resample: int = Resampling.NEAREST, 

2804 fill: int = 1, 

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

2806 ) -> Image: 

2807 """ 

2808 Transforms this image. This method creates a new image with the 

2809 given size, and the same mode as the original, and copies data 

2810 to the new image using the given transform. 

2811 

2812 :param size: The output size in pixels, as a 2-tuple: 

2813 (width, height). 

2814 :param method: The transformation method. This is one of 

2815 :py:data:`Transform.EXTENT` (cut out a rectangular subregion), 

2816 :py:data:`Transform.AFFINE` (affine transform), 

2817 :py:data:`Transform.PERSPECTIVE` (perspective transform), 

2818 :py:data:`Transform.QUAD` (map a quadrilateral to a rectangle), or 

2819 :py:data:`Transform.MESH` (map a number of source quadrilaterals 

2820 in one operation). 

2821 

2822 It may also be an :py:class:`~PIL.Image.ImageTransformHandler` 

2823 object:: 

2824 

2825 class Example(Image.ImageTransformHandler): 

2826 def transform(self, size, data, resample, fill=1): 

2827 # Return result 

2828 

2829 Implementations of :py:class:`~PIL.Image.ImageTransformHandler` 

2830 for some of the :py:class:`Transform` methods are provided 

2831 in :py:mod:`~PIL.ImageTransform`. 

2832 

2833 It may also be an object with a ``method.getdata`` method 

2834 that returns a tuple supplying new ``method`` and ``data`` values:: 

2835 

2836 class Example: 

2837 def getdata(self): 

2838 method = Image.Transform.EXTENT 

2839 data = (0, 0, 100, 100) 

2840 return method, data 

2841 :param data: Extra data to the transformation method. 

2842 :param resample: Optional resampling filter. It can be one of 

2843 :py:data:`Resampling.NEAREST` (use nearest neighbour), 

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

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

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

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

2848 See: :ref:`concept-filters`. 

2849 :param fill: If ``method`` is an 

2850 :py:class:`~PIL.Image.ImageTransformHandler` object, this is one of 

2851 the arguments passed to it. Otherwise, it is unused. 

2852 :param fillcolor: Optional fill color for the area outside the 

2853 transform in the output image. 

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

2855 """ 

2856 

2857 if self.mode in ("LA", "RGBA") and resample != Resampling.NEAREST: 

2858 return ( 

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

2860 .transform(size, method, data, resample, fill, fillcolor) 

2861 .convert(self.mode) 

2862 ) 

2863 

2864 if isinstance(method, ImageTransformHandler): 

2865 return method.transform(size, self, resample=resample, fill=fill) 

2866 

2867 if hasattr(method, "getdata"): 

2868 # compatibility w. old-style transform objects 

2869 method, data = method.getdata() 

2870 

2871 if data is None: 

2872 msg = "missing method data" 

2873 raise ValueError(msg) 

2874 

2875 im = new(self.mode, size, fillcolor) 

2876 if self.mode == "P" and self.palette: 

2877 im.palette = self.palette.copy() 

2878 im.info = self.info.copy() 

2879 if method == Transform.MESH: 

2880 # list of quads 

2881 for box, quad in data: 

2882 im.__transformer( 

2883 box, self, Transform.QUAD, quad, resample, fillcolor is None 

2884 ) 

2885 else: 

2886 im.__transformer( 

2887 (0, 0) + size, self, method, data, resample, fillcolor is None 

2888 ) 

2889 

2890 return im 

2891 

2892 def __transformer( 

2893 self, 

2894 box: tuple[int, int, int, int], 

2895 image: Image, 

2896 method: Transform, 

2897 data: Sequence[float], 

2898 resample: int = Resampling.NEAREST, 

2899 fill: bool = True, 

2900 ) -> None: 

2901 w = box[2] - box[0] 

2902 h = box[3] - box[1] 

2903 

2904 if method == Transform.AFFINE: 

2905 data = data[:6] 

2906 

2907 elif method == Transform.EXTENT: 

2908 # convert extent to an affine transform 

2909 x0, y0, x1, y1 = data 

2910 xs = (x1 - x0) / w 

2911 ys = (y1 - y0) / h 

2912 method = Transform.AFFINE 

2913 data = (xs, 0, x0, 0, ys, y0) 

2914 

2915 elif method == Transform.PERSPECTIVE: 

2916 data = data[:8] 

2917 

2918 elif method == Transform.QUAD: 

2919 # quadrilateral warp. data specifies the four corners 

2920 # given as NW, SW, SE, and NE. 

2921 nw = data[:2] 

2922 sw = data[2:4] 

2923 se = data[4:6] 

2924 ne = data[6:8] 

2925 x0, y0 = nw 

2926 As = 1.0 / w 

2927 At = 1.0 / h 

2928 data = ( 

2929 x0, 

2930 (ne[0] - x0) * As, 

2931 (sw[0] - x0) * At, 

2932 (se[0] - sw[0] - ne[0] + x0) * As * At, 

2933 y0, 

2934 (ne[1] - y0) * As, 

2935 (sw[1] - y0) * At, 

2936 (se[1] - sw[1] - ne[1] + y0) * As * At, 

2937 ) 

2938 

2939 else: 

2940 msg = "unknown transformation method" 

2941 raise ValueError(msg) 

2942 

2943 if resample not in ( 

2944 Resampling.NEAREST, 

2945 Resampling.BILINEAR, 

2946 Resampling.BICUBIC, 

2947 ): 

2948 if resample in (Resampling.BOX, Resampling.HAMMING, Resampling.LANCZOS): 

2949 unusable: dict[int, str] = { 

2950 Resampling.BOX: "Image.Resampling.BOX", 

2951 Resampling.HAMMING: "Image.Resampling.HAMMING", 

2952 Resampling.LANCZOS: "Image.Resampling.LANCZOS", 

2953 } 

2954 msg = unusable[resample] + f" ({resample}) cannot be used." 

2955 else: 

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

2957 

2958 filters = [ 

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

2960 for filter in ( 

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

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

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

2964 ) 

2965 ] 

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

2967 raise ValueError(msg) 

2968 

2969 image.load() 

2970 

2971 self.load() 

2972 

2973 if image.mode in ("1", "P"): 

2974 resample = Resampling.NEAREST 

2975 

2976 self.im.transform(box, image.im, method, data, resample, fill) 

2977 

2978 def transpose(self, method: Transpose) -> Image: 

2979 """ 

2980 Transpose image (flip or rotate in 90 degree steps) 

2981 

2982 :param method: One of :py:data:`Transpose.FLIP_LEFT_RIGHT`, 

2983 :py:data:`Transpose.FLIP_TOP_BOTTOM`, :py:data:`Transpose.ROTATE_90`, 

2984 :py:data:`Transpose.ROTATE_180`, :py:data:`Transpose.ROTATE_270`, 

2985 :py:data:`Transpose.TRANSPOSE` or :py:data:`Transpose.TRANSVERSE`. 

2986 :returns: Returns a flipped or rotated copy of this image. 

2987 """ 

2988 

2989 self.load() 

2990 return self._new(self.im.transpose(method)) 

2991 

2992 def effect_spread(self, distance: int) -> Image: 

2993 """ 

2994 Randomly spread pixels in an image. 

2995 

2996 :param distance: Distance to spread pixels. 

2997 """ 

2998 self.load() 

2999 return self._new(self.im.effect_spread(distance)) 

3000 

3001 def toqimage(self) -> ImageQt.ImageQt: 

3002 """Returns a QImage copy of this image""" 

3003 from . import ImageQt 

3004 

3005 if not ImageQt.qt_is_installed: 

3006 msg = "Qt bindings are not installed" 

3007 raise ImportError(msg) 

3008 return ImageQt.toqimage(self) 

3009 

3010 def toqpixmap(self) -> ImageQt.QPixmap: 

3011 """Returns a QPixmap copy of this image""" 

3012 from . import ImageQt 

3013 

3014 if not ImageQt.qt_is_installed: 

3015 msg = "Qt bindings are not installed" 

3016 raise ImportError(msg) 

3017 return ImageQt.toqpixmap(self) 

3018 

3019 

3020# -------------------------------------------------------------------- 

3021# Abstract handlers. 

3022 

3023 

3024class ImagePointHandler: 

3025 """ 

3026 Used as a mixin by point transforms 

3027 (for use with :py:meth:`~PIL.Image.Image.point`) 

3028 """ 

3029 

3030 @abc.abstractmethod 

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

3032 pass 

3033 

3034 

3035class ImageTransformHandler: 

3036 """ 

3037 Used as a mixin by geometry transforms 

3038 (for use with :py:meth:`~PIL.Image.Image.transform`) 

3039 """ 

3040 

3041 @abc.abstractmethod 

3042 def transform( 

3043 self, 

3044 size: tuple[int, int], 

3045 image: Image, 

3046 **options: Any, 

3047 ) -> Image: 

3048 pass 

3049 

3050 

3051# -------------------------------------------------------------------- 

3052# Factories 

3053 

3054# 

3055# Debugging 

3056 

3057 

3058def _wedge() -> Image: 

3059 """Create grayscale wedge (for debugging only)""" 

3060 

3061 return Image()._new(core.wedge("L")) 

3062 

3063 

3064def _check_size(size: Any) -> None: 

3065 """ 

3066 Common check to enforce type and sanity check on size tuples 

3067 

3068 :param size: Should be a 2 tuple of (width, height) 

3069 :returns: None, or raises a ValueError 

3070 """ 

3071 

3072 if not isinstance(size, (list, tuple)): 

3073 msg = "Size must be a list or tuple" 

3074 raise ValueError(msg) 

3075 if len(size) != 2: 

3076 msg = "Size must be a sequence of length 2" 

3077 raise ValueError(msg) 

3078 if size[0] < 0 or size[1] < 0: 

3079 msg = "Width and height must be >= 0" 

3080 raise ValueError(msg) 

3081 

3082 

3083def new( 

3084 mode: str, 

3085 size: tuple[int, int] | list[int], 

3086 color: float | tuple[float, ...] | str | None = 0, 

3087) -> Image: 

3088 """ 

3089 Creates a new image with the given mode and size. 

3090 

3091 :param mode: The mode to use for the new image. See: 

3092 :ref:`concept-modes`. 

3093 :param size: A 2-tuple, containing (width, height) in pixels. 

3094 :param color: What color to use for the image. Default is black. 

3095 If given, this should be a single integer or floating point value 

3096 for single-band modes, and a tuple for multi-band modes (one value 

3097 per band). When creating RGB or HSV images, you can also use color 

3098 strings as supported by the ImageColor module. If the color is 

3099 None, the image is not initialised. 

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

3101 """ 

3102 

3103 if mode in ("BGR;15", "BGR;16", "BGR;24"): 

3104 deprecate(mode, 12) 

3105 

3106 _check_size(size) 

3107 

3108 if color is None: 

3109 # don't initialize 

3110 return Image()._new(core.new(mode, size)) 

3111 

3112 if isinstance(color, str): 

3113 # css3-style specifier 

3114 

3115 from . import ImageColor 

3116 

3117 color = ImageColor.getcolor(color, mode) 

3118 

3119 im = Image() 

3120 if ( 

3121 mode == "P" 

3122 and isinstance(color, (list, tuple)) 

3123 and all(isinstance(i, int) for i in color) 

3124 ): 

3125 color_ints: tuple[int, ...] = cast(tuple[int, ...], tuple(color)) 

3126 if len(color_ints) == 3 or len(color_ints) == 4: 

3127 # RGB or RGBA value for a P image 

3128 from . import ImagePalette 

3129 

3130 im.palette = ImagePalette.ImagePalette() 

3131 color = im.palette.getcolor(color_ints) 

3132 return im._new(core.fill(mode, size, color)) 

3133 

3134 

3135def frombytes( 

3136 mode: str, 

3137 size: tuple[int, int], 

3138 data: bytes | bytearray | SupportsArrayInterface, 

3139 decoder_name: str = "raw", 

3140 *args: Any, 

3141) -> Image: 

3142 """ 

3143 Creates a copy of an image memory from pixel data in a buffer. 

3144 

3145 In its simplest form, this function takes three arguments 

3146 (mode, size, and unpacked pixel data). 

3147 

3148 You can also use any pixel decoder supported by PIL. For more 

3149 information on available decoders, see the section 

3150 :ref:`Writing Your Own File Codec <file-codecs>`. 

3151 

3152 Note that this function decodes pixel data only, not entire images. 

3153 If you have an entire image in a string, wrap it in a 

3154 :py:class:`~io.BytesIO` object, and use :py:func:`~PIL.Image.open` to load 

3155 it. 

3156 

3157 :param mode: The image mode. See: :ref:`concept-modes`. 

3158 :param size: The image size. 

3159 :param data: A byte buffer containing raw data for the given mode. 

3160 :param decoder_name: What decoder to use. 

3161 :param args: Additional parameters for the given decoder. 

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

3163 """ 

3164 

3165 _check_size(size) 

3166 

3167 im = new(mode, size) 

3168 if im.width != 0 and im.height != 0: 

3169 decoder_args: Any = args 

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

3171 # may pass tuple instead of argument list 

3172 decoder_args = decoder_args[0] 

3173 

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

3175 decoder_args = mode 

3176 

3177 im.frombytes(data, decoder_name, decoder_args) 

3178 return im 

3179 

3180 

3181def frombuffer( 

3182 mode: str, 

3183 size: tuple[int, int], 

3184 data: bytes | SupportsArrayInterface, 

3185 decoder_name: str = "raw", 

3186 *args: Any, 

3187) -> Image: 

3188 """ 

3189 Creates an image memory referencing pixel data in a byte buffer. 

3190 

3191 This function is similar to :py:func:`~PIL.Image.frombytes`, but uses data 

3192 in the byte buffer, where possible. This means that changes to the 

3193 original buffer object are reflected in this image). Not all modes can 

3194 share memory; supported modes include "L", "RGBX", "RGBA", and "CMYK". 

3195 

3196 Note that this function decodes pixel data only, not entire images. 

3197 If you have an entire image file in a string, wrap it in a 

3198 :py:class:`~io.BytesIO` object, and use :py:func:`~PIL.Image.open` to load it. 

3199 

3200 The default parameters used for the "raw" decoder differs from that used for 

3201 :py:func:`~PIL.Image.frombytes`. This is a bug, and will probably be fixed in a 

3202 future release. The current release issues a warning if you do this; to disable 

3203 the warning, you should provide the full set of parameters. See below for details. 

3204 

3205 :param mode: The image mode. See: :ref:`concept-modes`. 

3206 :param size: The image size. 

3207 :param data: A bytes or other buffer object containing raw 

3208 data for the given mode. 

3209 :param decoder_name: What decoder to use. 

3210 :param args: Additional parameters for the given decoder. For the 

3211 default encoder ("raw"), it's recommended that you provide the 

3212 full set of parameters:: 

3213 

3214 frombuffer(mode, size, data, "raw", mode, 0, 1) 

3215 

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

3217 

3218 .. versionadded:: 1.1.4 

3219 """ 

3220 

3221 _check_size(size) 

3222 

3223 # may pass tuple instead of argument list 

3224 if len(args) == 1 and isinstance(args[0], tuple): 

3225 args = args[0] 

3226 

3227 if decoder_name == "raw": 

3228 if args == (): 

3229 args = mode, 0, 1 

3230 if args[0] in _MAPMODES: 

3231 im = new(mode, (0, 0)) 

3232 im = im._new(core.map_buffer(data, size, decoder_name, 0, args)) 

3233 if mode == "P": 

3234 from . import ImagePalette 

3235 

3236 im.palette = ImagePalette.ImagePalette("RGB", im.im.getpalette("RGB")) 

3237 im.readonly = 1 

3238 return im 

3239 

3240 return frombytes(mode, size, data, decoder_name, args) 

3241 

3242 

3243class SupportsArrayInterface(Protocol): 

3244 """ 

3245 An object that has an ``__array_interface__`` dictionary. 

3246 """ 

3247 

3248 @property 

3249 def __array_interface__(self) -> dict[str, Any]: 

3250 raise NotImplementedError() 

3251 

3252 

3253def fromarray(obj: SupportsArrayInterface, mode: str | None = None) -> Image: 

3254 """ 

3255 Creates an image memory from an object exporting the array interface 

3256 (using the buffer protocol):: 

3257 

3258 from PIL import Image 

3259 import numpy as np 

3260 a = np.zeros((5, 5)) 

3261 im = Image.fromarray(a) 

3262 

3263 If ``obj`` is not contiguous, then the ``tobytes`` method is called 

3264 and :py:func:`~PIL.Image.frombuffer` is used. 

3265 

3266 In the case of NumPy, be aware that Pillow modes do not always correspond 

3267 to NumPy dtypes. Pillow modes only offer 1-bit pixels, 8-bit pixels, 

3268 32-bit signed integer pixels, and 32-bit floating point pixels. 

3269 

3270 Pillow images can also be converted to arrays:: 

3271 

3272 from PIL import Image 

3273 import numpy as np 

3274 im = Image.open("hopper.jpg") 

3275 a = np.asarray(im) 

3276 

3277 When converting Pillow images to arrays however, only pixel values are 

3278 transferred. This means that P and PA mode images will lose their palette. 

3279 

3280 :param obj: Object with array interface 

3281 :param mode: Optional mode to use when reading ``obj``. Will be determined from 

3282 type if ``None``. 

3283 

3284 This will not be used to convert the data after reading, but will be used to 

3285 change how the data is read:: 

3286 

3287 from PIL import Image 

3288 import numpy as np 

3289 a = np.full((1, 1), 300) 

3290 im = Image.fromarray(a, mode="L") 

3291 im.getpixel((0, 0)) # 44 

3292 im = Image.fromarray(a, mode="RGB") 

3293 im.getpixel((0, 0)) # (44, 1, 0) 

3294 

3295 See: :ref:`concept-modes` for general information about modes. 

3296 :returns: An image object. 

3297 

3298 .. versionadded:: 1.1.6 

3299 """ 

3300 arr = obj.__array_interface__ 

3301 shape = arr["shape"] 

3302 ndim = len(shape) 

3303 strides = arr.get("strides", None) 

3304 if mode is None: 

3305 try: 

3306 typekey = (1, 1) + shape[2:], arr["typestr"] 

3307 except KeyError as e: 

3308 msg = "Cannot handle this data type" 

3309 raise TypeError(msg) from e 

3310 try: 

3311 mode, rawmode = _fromarray_typemap[typekey] 

3312 except KeyError as e: 

3313 typekey_shape, typestr = typekey 

3314 msg = f"Cannot handle this data type: {typekey_shape}, {typestr}" 

3315 raise TypeError(msg) from e 

3316 else: 

3317 rawmode = mode 

3318 if mode in ["1", "L", "I", "P", "F"]: 

3319 ndmax = 2 

3320 elif mode == "RGB": 

3321 ndmax = 3 

3322 else: 

3323 ndmax = 4 

3324 if ndim > ndmax: 

3325 msg = f"Too many dimensions: {ndim} > {ndmax}." 

3326 raise ValueError(msg) 

3327 

3328 size = 1 if ndim == 1 else shape[1], shape[0] 

3329 if strides is not None: 

3330 if hasattr(obj, "tobytes"): 

3331 obj = obj.tobytes() 

3332 elif hasattr(obj, "tostring"): 

3333 obj = obj.tostring() 

3334 else: 

3335 msg = "'strides' requires either tobytes() or tostring()" 

3336 raise ValueError(msg) 

3337 

3338 return frombuffer(mode, size, obj, "raw", rawmode, 0, 1) 

3339 

3340 

3341def fromqimage(im: ImageQt.QImage) -> ImageFile.ImageFile: 

3342 """Creates an image instance from a QImage image""" 

3343 from . import ImageQt 

3344 

3345 if not ImageQt.qt_is_installed: 

3346 msg = "Qt bindings are not installed" 

3347 raise ImportError(msg) 

3348 return ImageQt.fromqimage(im) 

3349 

3350 

3351def fromqpixmap(im: ImageQt.QPixmap) -> ImageFile.ImageFile: 

3352 """Creates an image instance from a QPixmap image""" 

3353 from . import ImageQt 

3354 

3355 if not ImageQt.qt_is_installed: 

3356 msg = "Qt bindings are not installed" 

3357 raise ImportError(msg) 

3358 return ImageQt.fromqpixmap(im) 

3359 

3360 

3361_fromarray_typemap = { 

3362 # (shape, typestr) => mode, rawmode 

3363 # first two members of shape are set to one 

3364 ((1, 1), "|b1"): ("1", "1;8"), 

3365 ((1, 1), "|u1"): ("L", "L"), 

3366 ((1, 1), "|i1"): ("I", "I;8"), 

3367 ((1, 1), "<u2"): ("I", "I;16"), 

3368 ((1, 1), ">u2"): ("I", "I;16B"), 

3369 ((1, 1), "<i2"): ("I", "I;16S"), 

3370 ((1, 1), ">i2"): ("I", "I;16BS"), 

3371 ((1, 1), "<u4"): ("I", "I;32"), 

3372 ((1, 1), ">u4"): ("I", "I;32B"), 

3373 ((1, 1), "<i4"): ("I", "I;32S"), 

3374 ((1, 1), ">i4"): ("I", "I;32BS"), 

3375 ((1, 1), "<f4"): ("F", "F;32F"), 

3376 ((1, 1), ">f4"): ("F", "F;32BF"), 

3377 ((1, 1), "<f8"): ("F", "F;64F"), 

3378 ((1, 1), ">f8"): ("F", "F;64BF"), 

3379 ((1, 1, 2), "|u1"): ("LA", "LA"), 

3380 ((1, 1, 3), "|u1"): ("RGB", "RGB"), 

3381 ((1, 1, 4), "|u1"): ("RGBA", "RGBA"), 

3382 # shortcuts: 

3383 ((1, 1), f"{_ENDIAN}i4"): ("I", "I"), 

3384 ((1, 1), f"{_ENDIAN}f4"): ("F", "F"), 

3385} 

3386 

3387 

3388def _decompression_bomb_check(size: tuple[int, int]) -> None: 

3389 if MAX_IMAGE_PIXELS is None: 

3390 return 

3391 

3392 pixels = max(1, size[0]) * max(1, size[1]) 

3393 

3394 if pixels > 2 * MAX_IMAGE_PIXELS: 

3395 msg = ( 

3396 f"Image size ({pixels} pixels) exceeds limit of {2 * MAX_IMAGE_PIXELS} " 

3397 "pixels, could be decompression bomb DOS attack." 

3398 ) 

3399 raise DecompressionBombError(msg) 

3400 

3401 if pixels > MAX_IMAGE_PIXELS: 

3402 warnings.warn( 

3403 f"Image size ({pixels} pixels) exceeds limit of {MAX_IMAGE_PIXELS} pixels, " 

3404 "could be decompression bomb DOS attack.", 

3405 DecompressionBombWarning, 

3406 ) 

3407 

3408 

3409def open( 

3410 fp: StrOrBytesPath | IO[bytes], 

3411 mode: Literal["r"] = "r", 

3412 formats: list[str] | tuple[str, ...] | None = None, 

3413) -> ImageFile.ImageFile: 

3414 """ 

3415 Opens and identifies the given image file. 

3416 

3417 This is a lazy operation; this function identifies the file, but 

3418 the file remains open and the actual image data is not read from 

3419 the file until you try to process the data (or call the 

3420 :py:meth:`~PIL.Image.Image.load` method). See 

3421 :py:func:`~PIL.Image.new`. See :ref:`file-handling`. 

3422 

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

3424 The file object must implement ``file.read``, 

3425 ``file.seek``, and ``file.tell`` methods, 

3426 and be opened in binary mode. The file object will also seek to zero 

3427 before reading. 

3428 :param mode: The mode. If given, this argument must be "r". 

3429 :param formats: A list or tuple of formats to attempt to load the file in. 

3430 This can be used to restrict the set of formats checked. 

3431 Pass ``None`` to try all supported formats. You can print the set of 

3432 available formats by running ``python3 -m PIL`` or using 

3433 the :py:func:`PIL.features.pilinfo` function. 

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

3435 :exception FileNotFoundError: If the file cannot be found. 

3436 :exception PIL.UnidentifiedImageError: If the image cannot be opened and 

3437 identified. 

3438 :exception ValueError: If the ``mode`` is not "r", or if a ``StringIO`` 

3439 instance is used for ``fp``. 

3440 :exception TypeError: If ``formats`` is not ``None``, a list or a tuple. 

3441 """ 

3442 

3443 if mode != "r": 

3444 msg = f"bad mode {repr(mode)}" # type: ignore[unreachable] 

3445 raise ValueError(msg) 

3446 elif isinstance(fp, io.StringIO): 

3447 msg = ( # type: ignore[unreachable] 

3448 "StringIO cannot be used to open an image. " 

3449 "Binary data must be used instead." 

3450 ) 

3451 raise ValueError(msg) 

3452 

3453 if formats is None: 

3454 formats = ID 

3455 elif not isinstance(formats, (list, tuple)): 

3456 msg = "formats must be a list or tuple" # type: ignore[unreachable] 

3457 raise TypeError(msg) 

3458 

3459 exclusive_fp = False 

3460 filename: str | bytes = "" 

3461 if is_path(fp): 

3462 filename = os.fspath(fp) 

3463 

3464 if filename: 

3465 fp = builtins.open(filename, "rb") 

3466 exclusive_fp = True 

3467 else: 

3468 fp = cast(IO[bytes], fp) 

3469 

3470 try: 

3471 fp.seek(0) 

3472 except (AttributeError, io.UnsupportedOperation): 

3473 fp = io.BytesIO(fp.read()) 

3474 exclusive_fp = True 

3475 

3476 prefix = fp.read(16) 

3477 

3478 preinit() 

3479 

3480 warning_messages: list[str] = [] 

3481 

3482 def _open_core( 

3483 fp: IO[bytes], 

3484 filename: str | bytes, 

3485 prefix: bytes, 

3486 formats: list[str] | tuple[str, ...], 

3487 ) -> ImageFile.ImageFile | None: 

3488 for i in formats: 

3489 i = i.upper() 

3490 if i not in OPEN: 

3491 init() 

3492 try: 

3493 factory, accept = OPEN[i] 

3494 result = not accept or accept(prefix) 

3495 if isinstance(result, str): 

3496 warning_messages.append(result) 

3497 elif result: 

3498 fp.seek(0) 

3499 im = factory(fp, filename) 

3500 _decompression_bomb_check(im.size) 

3501 return im 

3502 except (SyntaxError, IndexError, TypeError, struct.error) as e: 

3503 if WARN_POSSIBLE_FORMATS: 

3504 warning_messages.append(i + " opening failed. " + str(e)) 

3505 except BaseException: 

3506 if exclusive_fp: 

3507 fp.close() 

3508 raise 

3509 return None 

3510 

3511 im = _open_core(fp, filename, prefix, formats) 

3512 

3513 if im is None and formats is ID: 

3514 checked_formats = ID.copy() 

3515 if init(): 

3516 im = _open_core( 

3517 fp, 

3518 filename, 

3519 prefix, 

3520 tuple(format for format in formats if format not in checked_formats), 

3521 ) 

3522 

3523 if im: 

3524 im._exclusive_fp = exclusive_fp 

3525 return im 

3526 

3527 if exclusive_fp: 

3528 fp.close() 

3529 for message in warning_messages: 

3530 warnings.warn(message) 

3531 msg = "cannot identify image file %r" % (filename if filename else fp) 

3532 raise UnidentifiedImageError(msg) 

3533 

3534 

3535# 

3536# Image processing. 

3537 

3538 

3539def alpha_composite(im1: Image, im2: Image) -> Image: 

3540 """ 

3541 Alpha composite im2 over im1. 

3542 

3543 :param im1: The first image. Must have mode RGBA. 

3544 :param im2: The second image. Must have mode RGBA, and the same size as 

3545 the first image. 

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

3547 """ 

3548 

3549 im1.load() 

3550 im2.load() 

3551 return im1._new(core.alpha_composite(im1.im, im2.im)) 

3552 

3553 

3554def blend(im1: Image, im2: Image, alpha: float) -> Image: 

3555 """ 

3556 Creates a new image by interpolating between two input images, using 

3557 a constant alpha:: 

3558 

3559 out = image1 * (1.0 - alpha) + image2 * alpha 

3560 

3561 :param im1: The first image. 

3562 :param im2: The second image. Must have the same mode and size as 

3563 the first image. 

3564 :param alpha: The interpolation alpha factor. If alpha is 0.0, a 

3565 copy of the first image is returned. If alpha is 1.0, a copy of 

3566 the second image is returned. There are no restrictions on the 

3567 alpha value. If necessary, the result is clipped to fit into 

3568 the allowed output range. 

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

3570 """ 

3571 

3572 im1.load() 

3573 im2.load() 

3574 return im1._new(core.blend(im1.im, im2.im, alpha)) 

3575 

3576 

3577def composite(image1: Image, image2: Image, mask: Image) -> Image: 

3578 """ 

3579 Create composite image by blending images using a transparency mask. 

3580 

3581 :param image1: The first image. 

3582 :param image2: The second image. Must have the same mode and 

3583 size as the first image. 

3584 :param mask: A mask image. This image can have mode 

3585 "1", "L", or "RGBA", and must have the same size as the 

3586 other two images. 

3587 """ 

3588 

3589 image = image2.copy() 

3590 image.paste(image1, None, mask) 

3591 return image 

3592 

3593 

3594def eval(image: Image, *args: Callable[[int], float]) -> Image: 

3595 """ 

3596 Applies the function (which should take one argument) to each pixel 

3597 in the given image. If the image has more than one band, the same 

3598 function is applied to each band. Note that the function is 

3599 evaluated once for each possible pixel value, so you cannot use 

3600 random components or other generators. 

3601 

3602 :param image: The input image. 

3603 :param function: A function object, taking one integer argument. 

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

3605 """ 

3606 

3607 return image.point(args[0]) 

3608 

3609 

3610def merge(mode: str, bands: Sequence[Image]) -> Image: 

3611 """ 

3612 Merge a set of single band images into a new multiband image. 

3613 

3614 :param mode: The mode to use for the output image. See: 

3615 :ref:`concept-modes`. 

3616 :param bands: A sequence containing one single-band image for 

3617 each band in the output image. All bands must have the 

3618 same size. 

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

3620 """ 

3621 

3622 if getmodebands(mode) != len(bands) or "*" in mode: 

3623 msg = "wrong number of bands" 

3624 raise ValueError(msg) 

3625 for band in bands[1:]: 

3626 if band.mode != getmodetype(mode): 

3627 msg = "mode mismatch" 

3628 raise ValueError(msg) 

3629 if band.size != bands[0].size: 

3630 msg = "size mismatch" 

3631 raise ValueError(msg) 

3632 for band in bands: 

3633 band.load() 

3634 return bands[0]._new(core.merge(mode, *[b.im for b in bands])) 

3635 

3636 

3637# -------------------------------------------------------------------- 

3638# Plugin registry 

3639 

3640 

3641def register_open( 

3642 id: str, 

3643 factory: ( 

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

3645 | type[ImageFile.ImageFile] 

3646 ), 

3647 accept: Callable[[bytes], bool | str] | None = None, 

3648) -> None: 

3649 """ 

3650 Register an image file plugin. This function should not be used 

3651 in application code. 

3652 

3653 :param id: An image format identifier. 

3654 :param factory: An image file factory method. 

3655 :param accept: An optional function that can be used to quickly 

3656 reject images having another format. 

3657 """ 

3658 id = id.upper() 

3659 if id not in ID: 

3660 ID.append(id) 

3661 OPEN[id] = factory, accept 

3662 

3663 

3664def register_mime(id: str, mimetype: str) -> None: 

3665 """ 

3666 Registers an image MIME type by populating ``Image.MIME``. This function 

3667 should not be used in application code. 

3668 

3669 ``Image.MIME`` provides a mapping from image format identifiers to mime 

3670 formats, but :py:meth:`~PIL.ImageFile.ImageFile.get_format_mimetype` can 

3671 provide a different result for specific images. 

3672 

3673 :param id: An image format identifier. 

3674 :param mimetype: The image MIME type for this format. 

3675 """ 

3676 MIME[id.upper()] = mimetype 

3677 

3678 

3679def register_save( 

3680 id: str, driver: Callable[[Image, IO[bytes], str | bytes], None] 

3681) -> None: 

3682 """ 

3683 Registers an image save function. This function should not be 

3684 used in application code. 

3685 

3686 :param id: An image format identifier. 

3687 :param driver: A function to save images in this format. 

3688 """ 

3689 SAVE[id.upper()] = driver 

3690 

3691 

3692def register_save_all( 

3693 id: str, driver: Callable[[Image, IO[bytes], str | bytes], None] 

3694) -> None: 

3695 """ 

3696 Registers an image function to save all the frames 

3697 of a multiframe format. This function should not be 

3698 used in application code. 

3699 

3700 :param id: An image format identifier. 

3701 :param driver: A function to save images in this format. 

3702 """ 

3703 SAVE_ALL[id.upper()] = driver 

3704 

3705 

3706def register_extension(id: str, extension: str) -> None: 

3707 """ 

3708 Registers an image extension. This function should not be 

3709 used in application code. 

3710 

3711 :param id: An image format identifier. 

3712 :param extension: An extension used for this format. 

3713 """ 

3714 EXTENSION[extension.lower()] = id.upper() 

3715 

3716 

3717def register_extensions(id: str, extensions: list[str]) -> None: 

3718 """ 

3719 Registers image extensions. This function should not be 

3720 used in application code. 

3721 

3722 :param id: An image format identifier. 

3723 :param extensions: A list of extensions used for this format. 

3724 """ 

3725 for extension in extensions: 

3726 register_extension(id, extension) 

3727 

3728 

3729def registered_extensions() -> dict[str, str]: 

3730 """ 

3731 Returns a dictionary containing all file extensions belonging 

3732 to registered plugins 

3733 """ 

3734 init() 

3735 return EXTENSION 

3736 

3737 

3738def register_decoder(name: str, decoder: type[ImageFile.PyDecoder]) -> None: 

3739 """ 

3740 Registers an image decoder. This function should not be 

3741 used in application code. 

3742 

3743 :param name: The name of the decoder 

3744 :param decoder: An ImageFile.PyDecoder object 

3745 

3746 .. versionadded:: 4.1.0 

3747 """ 

3748 DECODERS[name] = decoder 

3749 

3750 

3751def register_encoder(name: str, encoder: type[ImageFile.PyEncoder]) -> None: 

3752 """ 

3753 Registers an image encoder. This function should not be 

3754 used in application code. 

3755 

3756 :param name: The name of the encoder 

3757 :param encoder: An ImageFile.PyEncoder object 

3758 

3759 .. versionadded:: 4.1.0 

3760 """ 

3761 ENCODERS[name] = encoder 

3762 

3763 

3764# -------------------------------------------------------------------- 

3765# Simple display support. 

3766 

3767 

3768def _show(image: Image, **options: Any) -> None: 

3769 from . import ImageShow 

3770 

3771 ImageShow.show(image, **options) 

3772 

3773 

3774# -------------------------------------------------------------------- 

3775# Effects 

3776 

3777 

3778def effect_mandelbrot( 

3779 size: tuple[int, int], extent: tuple[float, float, float, float], quality: int 

3780) -> Image: 

3781 """ 

3782 Generate a Mandelbrot set covering the given extent. 

3783 

3784 :param size: The requested size in pixels, as a 2-tuple: 

3785 (width, height). 

3786 :param extent: The extent to cover, as a 4-tuple: 

3787 (x0, y0, x1, y1). 

3788 :param quality: Quality. 

3789 """ 

3790 return Image()._new(core.effect_mandelbrot(size, extent, quality)) 

3791 

3792 

3793def effect_noise(size: tuple[int, int], sigma: float) -> Image: 

3794 """ 

3795 Generate Gaussian noise centered around 128. 

3796 

3797 :param size: The requested size in pixels, as a 2-tuple: 

3798 (width, height). 

3799 :param sigma: Standard deviation of noise. 

3800 """ 

3801 return Image()._new(core.effect_noise(size, sigma)) 

3802 

3803 

3804def linear_gradient(mode: str) -> Image: 

3805 """ 

3806 Generate 256x256 linear gradient from black to white, top to bottom. 

3807 

3808 :param mode: Input mode. 

3809 """ 

3810 return Image()._new(core.linear_gradient(mode)) 

3811 

3812 

3813def radial_gradient(mode: str) -> Image: 

3814 """ 

3815 Generate 256x256 radial gradient from black to white, centre to edge. 

3816 

3817 :param mode: Input mode. 

3818 """ 

3819 return Image()._new(core.radial_gradient(mode)) 

3820 

3821 

3822# -------------------------------------------------------------------- 

3823# Resources 

3824 

3825 

3826def _apply_env_variables(env: dict[str, str] | None = None) -> None: 

3827 env_dict = env if env is not None else os.environ 

3828 

3829 for var_name, setter in [ 

3830 ("PILLOW_ALIGNMENT", core.set_alignment), 

3831 ("PILLOW_BLOCK_SIZE", core.set_block_size), 

3832 ("PILLOW_BLOCKS_MAX", core.set_blocks_max), 

3833 ]: 

3834 if var_name not in env_dict: 

3835 continue 

3836 

3837 var = env_dict[var_name].lower() 

3838 

3839 units = 1 

3840 for postfix, mul in [("k", 1024), ("m", 1024 * 1024)]: 

3841 if var.endswith(postfix): 

3842 units = mul 

3843 var = var[: -len(postfix)] 

3844 

3845 try: 

3846 var_int = int(var) * units 

3847 except ValueError: 

3848 warnings.warn(f"{var_name} is not int") 

3849 continue 

3850 

3851 try: 

3852 setter(var_int) 

3853 except ValueError as e: 

3854 warnings.warn(f"{var_name}: {e}") 

3855 

3856 

3857_apply_env_variables() 

3858atexit.register(core.clear_cache) 

3859 

3860 

3861if TYPE_CHECKING: 

3862 _ExifBase = MutableMapping[int, Any] 

3863else: 

3864 _ExifBase = MutableMapping 

3865 

3866 

3867class Exif(_ExifBase): 

3868 """ 

3869 This class provides read and write access to EXIF image data:: 

3870 

3871 from PIL import Image 

3872 im = Image.open("exif.png") 

3873 exif = im.getexif() # Returns an instance of this class 

3874 

3875 Information can be read and written, iterated over or deleted:: 

3876 

3877 print(exif[274]) # 1 

3878 exif[274] = 2 

3879 for k, v in exif.items(): 

3880 print("Tag", k, "Value", v) # Tag 274 Value 2 

3881 del exif[274] 

3882 

3883 To access information beyond IFD0, :py:meth:`~PIL.Image.Exif.get_ifd` 

3884 returns a dictionary:: 

3885 

3886 from PIL import ExifTags 

3887 im = Image.open("exif_gps.jpg") 

3888 exif = im.getexif() 

3889 gps_ifd = exif.get_ifd(ExifTags.IFD.GPSInfo) 

3890 print(gps_ifd) 

3891 

3892 Other IFDs include ``ExifTags.IFD.Exif``, ``ExifTags.IFD.MakerNote``, 

3893 ``ExifTags.IFD.Interop`` and ``ExifTags.IFD.IFD1``. 

3894 

3895 :py:mod:`~PIL.ExifTags` also has enum classes to provide names for data:: 

3896 

3897 print(exif[ExifTags.Base.Software]) # PIL 

3898 print(gps_ifd[ExifTags.GPS.GPSDateStamp]) # 1999:99:99 99:99:99 

3899 """ 

3900 

3901 endian: str | None = None 

3902 bigtiff = False 

3903 _loaded = False 

3904 

3905 def __init__(self) -> None: 

3906 self._data: dict[int, Any] = {} 

3907 self._hidden_data: dict[int, Any] = {} 

3908 self._ifds: dict[int, dict[int, Any]] = {} 

3909 self._info: TiffImagePlugin.ImageFileDirectory_v2 | None = None 

3910 self._loaded_exif: bytes | None = None 

3911 

3912 def _fixup(self, value: Any) -> Any: 

3913 try: 

3914 if len(value) == 1 and isinstance(value, tuple): 

3915 return value[0] 

3916 except Exception: 

3917 pass 

3918 return value 

3919 

3920 def _fixup_dict(self, src_dict: dict[int, Any]) -> dict[int, Any]: 

3921 # Helper function 

3922 # returns a dict with any single item tuples/lists as individual values 

3923 return {k: self._fixup(v) for k, v in src_dict.items()} 

3924 

3925 def _get_ifd_dict( 

3926 self, offset: int, group: int | None = None 

3927 ) -> dict[int, Any] | None: 

3928 try: 

3929 # an offset pointer to the location of the nested embedded IFD. 

3930 # It should be a long, but may be corrupted. 

3931 self.fp.seek(offset) 

3932 except (KeyError, TypeError): 

3933 return None 

3934 else: 

3935 from . import TiffImagePlugin 

3936 

3937 info = TiffImagePlugin.ImageFileDirectory_v2(self.head, group=group) 

3938 info.load(self.fp) 

3939 return self._fixup_dict(dict(info)) 

3940 

3941 def _get_head(self) -> bytes: 

3942 version = b"\x2B" if self.bigtiff else b"\x2A" 

3943 if self.endian == "<": 

3944 head = b"II" + version + b"\x00" + o32le(8) 

3945 else: 

3946 head = b"MM\x00" + version + o32be(8) 

3947 if self.bigtiff: 

3948 head += o32le(8) if self.endian == "<" else o32be(8) 

3949 head += b"\x00\x00\x00\x00" 

3950 return head 

3951 

3952 def load(self, data: bytes) -> None: 

3953 # Extract EXIF information. This is highly experimental, 

3954 # and is likely to be replaced with something better in a future 

3955 # version. 

3956 

3957 # The EXIF record consists of a TIFF file embedded in a JPEG 

3958 # application marker (!). 

3959 if data == self._loaded_exif: 

3960 return 

3961 self._loaded_exif = data 

3962 self._data.clear() 

3963 self._hidden_data.clear() 

3964 self._ifds.clear() 

3965 while data and data.startswith(b"Exif\x00\x00"): 

3966 data = data[6:] 

3967 if not data: 

3968 self._info = None 

3969 return 

3970 

3971 self.fp: IO[bytes] = io.BytesIO(data) 

3972 self.head = self.fp.read(8) 

3973 # process dictionary 

3974 from . import TiffImagePlugin 

3975 

3976 self._info = TiffImagePlugin.ImageFileDirectory_v2(self.head) 

3977 self.endian = self._info._endian 

3978 self.fp.seek(self._info.next) 

3979 self._info.load(self.fp) 

3980 

3981 def load_from_fp(self, fp: IO[bytes], offset: int | None = None) -> None: 

3982 self._loaded_exif = None 

3983 self._data.clear() 

3984 self._hidden_data.clear() 

3985 self._ifds.clear() 

3986 

3987 # process dictionary 

3988 from . import TiffImagePlugin 

3989 

3990 self.fp = fp 

3991 if offset is not None: 

3992 self.head = self._get_head() 

3993 else: 

3994 self.head = self.fp.read(8) 

3995 self._info = TiffImagePlugin.ImageFileDirectory_v2(self.head) 

3996 if self.endian is None: 

3997 self.endian = self._info._endian 

3998 if offset is None: 

3999 offset = self._info.next 

4000 self.fp.tell() 

4001 self.fp.seek(offset) 

4002 self._info.load(self.fp) 

4003 

4004 def _get_merged_dict(self) -> dict[int, Any]: 

4005 merged_dict = dict(self) 

4006 

4007 # get EXIF extension 

4008 if ExifTags.IFD.Exif in self: 

4009 ifd = self._get_ifd_dict(self[ExifTags.IFD.Exif], ExifTags.IFD.Exif) 

4010 if ifd: 

4011 merged_dict.update(ifd) 

4012 

4013 # GPS 

4014 if ExifTags.IFD.GPSInfo in self: 

4015 merged_dict[ExifTags.IFD.GPSInfo] = self._get_ifd_dict( 

4016 self[ExifTags.IFD.GPSInfo], ExifTags.IFD.GPSInfo 

4017 ) 

4018 

4019 return merged_dict 

4020 

4021 def tobytes(self, offset: int = 8) -> bytes: 

4022 from . import TiffImagePlugin 

4023 

4024 head = self._get_head() 

4025 ifd = TiffImagePlugin.ImageFileDirectory_v2(ifh=head) 

4026 for tag, ifd_dict in self._ifds.items(): 

4027 if tag not in self: 

4028 ifd[tag] = ifd_dict 

4029 for tag, value in self.items(): 

4030 if tag in [ 

4031 ExifTags.IFD.Exif, 

4032 ExifTags.IFD.GPSInfo, 

4033 ] and not isinstance(value, dict): 

4034 value = self.get_ifd(tag) 

4035 if ( 

4036 tag == ExifTags.IFD.Exif 

4037 and ExifTags.IFD.Interop in value 

4038 and not isinstance(value[ExifTags.IFD.Interop], dict) 

4039 ): 

4040 value = value.copy() 

4041 value[ExifTags.IFD.Interop] = self.get_ifd(ExifTags.IFD.Interop) 

4042 ifd[tag] = value 

4043 return b"Exif\x00\x00" + head + ifd.tobytes(offset) 

4044 

4045 def get_ifd(self, tag: int) -> dict[int, Any]: 

4046 if tag not in self._ifds: 

4047 if tag == ExifTags.IFD.IFD1: 

4048 if self._info is not None and self._info.next != 0: 

4049 ifd = self._get_ifd_dict(self._info.next) 

4050 if ifd is not None: 

4051 self._ifds[tag] = ifd 

4052 elif tag in [ExifTags.IFD.Exif, ExifTags.IFD.GPSInfo]: 

4053 offset = self._hidden_data.get(tag, self.get(tag)) 

4054 if offset is not None: 

4055 ifd = self._get_ifd_dict(offset, tag) 

4056 if ifd is not None: 

4057 self._ifds[tag] = ifd 

4058 elif tag in [ExifTags.IFD.Interop, ExifTags.IFD.MakerNote]: 

4059 if ExifTags.IFD.Exif not in self._ifds: 

4060 self.get_ifd(ExifTags.IFD.Exif) 

4061 tag_data = self._ifds[ExifTags.IFD.Exif][tag] 

4062 if tag == ExifTags.IFD.MakerNote: 

4063 from .TiffImagePlugin import ImageFileDirectory_v2 

4064 

4065 if tag_data[:8] == b"FUJIFILM": 

4066 ifd_offset = i32le(tag_data, 8) 

4067 ifd_data = tag_data[ifd_offset:] 

4068 

4069 makernote = {} 

4070 for i in range(0, struct.unpack("<H", ifd_data[:2])[0]): 

4071 ifd_tag, typ, count, data = struct.unpack( 

4072 "<HHL4s", ifd_data[i * 12 + 2 : (i + 1) * 12 + 2] 

4073 ) 

4074 try: 

4075 ( 

4076 unit_size, 

4077 handler, 

4078 ) = ImageFileDirectory_v2._load_dispatch[typ] 

4079 except KeyError: 

4080 continue 

4081 size = count * unit_size 

4082 if size > 4: 

4083 (offset,) = struct.unpack("<L", data) 

4084 data = ifd_data[offset - 12 : offset + size - 12] 

4085 else: 

4086 data = data[:size] 

4087 

4088 if len(data) != size: 

4089 warnings.warn( 

4090 "Possibly corrupt EXIF MakerNote data. " 

4091 f"Expecting to read {size} bytes but only got " 

4092 f"{len(data)}. Skipping tag {ifd_tag}" 

4093 ) 

4094 continue 

4095 

4096 if not data: 

4097 continue 

4098 

4099 makernote[ifd_tag] = handler( 

4100 ImageFileDirectory_v2(), data, False 

4101 ) 

4102 self._ifds[tag] = dict(self._fixup_dict(makernote)) 

4103 elif self.get(0x010F) == "Nintendo": 

4104 makernote = {} 

4105 for i in range(0, struct.unpack(">H", tag_data[:2])[0]): 

4106 ifd_tag, typ, count, data = struct.unpack( 

4107 ">HHL4s", tag_data[i * 12 + 2 : (i + 1) * 12 + 2] 

4108 ) 

4109 if ifd_tag == 0x1101: 

4110 # CameraInfo 

4111 (offset,) = struct.unpack(">L", data) 

4112 self.fp.seek(offset) 

4113 

4114 camerainfo: dict[str, int | bytes] = { 

4115 "ModelID": self.fp.read(4) 

4116 } 

4117 

4118 self.fp.read(4) 

4119 # Seconds since 2000 

4120 camerainfo["TimeStamp"] = i32le(self.fp.read(12)) 

4121 

4122 self.fp.read(4) 

4123 camerainfo["InternalSerialNumber"] = self.fp.read(4) 

4124 

4125 self.fp.read(12) 

4126 parallax = self.fp.read(4) 

4127 handler = ImageFileDirectory_v2._load_dispatch[ 

4128 TiffTags.FLOAT 

4129 ][1] 

4130 camerainfo["Parallax"] = handler( 

4131 ImageFileDirectory_v2(), parallax, False 

4132 )[0] 

4133 

4134 self.fp.read(4) 

4135 camerainfo["Category"] = self.fp.read(2) 

4136 

4137 makernote = {0x1101: camerainfo} 

4138 self._ifds[tag] = makernote 

4139 else: 

4140 # Interop 

4141 ifd = self._get_ifd_dict(tag_data, tag) 

4142 if ifd is not None: 

4143 self._ifds[tag] = ifd 

4144 ifd = self._ifds.setdefault(tag, {}) 

4145 if tag == ExifTags.IFD.Exif and self._hidden_data: 

4146 ifd = { 

4147 k: v 

4148 for (k, v) in ifd.items() 

4149 if k not in (ExifTags.IFD.Interop, ExifTags.IFD.MakerNote) 

4150 } 

4151 return ifd 

4152 

4153 def hide_offsets(self) -> None: 

4154 for tag in (ExifTags.IFD.Exif, ExifTags.IFD.GPSInfo): 

4155 if tag in self: 

4156 self._hidden_data[tag] = self[tag] 

4157 del self[tag] 

4158 

4159 def __str__(self) -> str: 

4160 if self._info is not None: 

4161 # Load all keys into self._data 

4162 for tag in self._info: 

4163 self[tag] 

4164 

4165 return str(self._data) 

4166 

4167 def __len__(self) -> int: 

4168 keys = set(self._data) 

4169 if self._info is not None: 

4170 keys.update(self._info) 

4171 return len(keys) 

4172 

4173 def __getitem__(self, tag: int) -> Any: 

4174 if self._info is not None and tag not in self._data and tag in self._info: 

4175 self._data[tag] = self._fixup(self._info[tag]) 

4176 del self._info[tag] 

4177 return self._data[tag] 

4178 

4179 def __contains__(self, tag: object) -> bool: 

4180 return tag in self._data or (self._info is not None and tag in self._info) 

4181 

4182 def __setitem__(self, tag: int, value: Any) -> None: 

4183 if self._info is not None and tag in self._info: 

4184 del self._info[tag] 

4185 self._data[tag] = value 

4186 

4187 def __delitem__(self, tag: int) -> None: 

4188 if self._info is not None and tag in self._info: 

4189 del self._info[tag] 

4190 else: 

4191 del self._data[tag] 

4192 

4193 def __iter__(self) -> Iterator[int]: 

4194 keys = set(self._data) 

4195 if self._info is not None: 

4196 keys.update(self._info) 

4197 return iter(keys)