Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pillow-10.4.0-py3.8-linux-x86_64.egg/PIL/Image.py: 24%

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

1723 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, MutableMapping 

42from enum import IntEnum 

43from types import ModuleType 

44from typing import ( 

45 IO, 

46 TYPE_CHECKING, 

47 Any, 

48 Literal, 

49 Protocol, 

50 Sequence, 

51 Tuple, 

52 cast, 

53) 

54 

55# VERSION was removed in Pillow 6.0.0. 

56# PILLOW_VERSION was removed in Pillow 9.0.0. 

57# Use __version__ instead. 

58from . import ( 

59 ExifTags, 

60 ImageMode, 

61 TiffTags, 

62 UnidentifiedImageError, 

63 __version__, 

64 _plugins, 

65) 

66from ._binary import i32le, o32be, o32le 

67from ._deprecate import deprecate 

68from ._typing import StrOrBytesPath, TypeGuard 

69from ._util import DeferredError, is_path 

70 

71ElementTree: ModuleType | None 

72try: 

73 from defusedxml import ElementTree 

74except ImportError: 

75 ElementTree = None 

76 

77logger = logging.getLogger(__name__) 

78 

79 

80class DecompressionBombWarning(RuntimeWarning): 

81 pass 

82 

83 

84class DecompressionBombError(Exception): 

85 pass 

86 

87 

88WARN_POSSIBLE_FORMATS: bool = False 

89 

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

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

92 

93 

94try: 

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

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

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

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

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

100 from . import _imaging as core 

101 

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

103 msg = ( 

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

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

106 f"Pillow version: {__version__}" 

107 ) 

108 raise ImportError(msg) 

109 

110except ImportError as v: 

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

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

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

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

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

116 # possible. 

117 warnings.warn( 

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

119 RuntimeWarning, 

120 ) 

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

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

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

124 # see docs/porting.rst 

125 raise 

126 

127 

128USE_CFFI_ACCESS = False 

129cffi: ModuleType | None 

130try: 

131 import cffi 

132except ImportError: 

133 cffi = None 

134 

135 

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

137 """ 

138 Checks if an object is an image object. 

139 

140 .. warning:: 

141 

142 This function is for internal use only. 

143 

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

145 :returns: True if the object is an image 

146 """ 

147 return hasattr(t, "im") 

148 

149 

150# 

151# Constants 

152 

153 

154# transpose 

155class Transpose(IntEnum): 

156 FLIP_LEFT_RIGHT = 0 

157 FLIP_TOP_BOTTOM = 1 

158 ROTATE_90 = 2 

159 ROTATE_180 = 3 

160 ROTATE_270 = 4 

161 TRANSPOSE = 5 

162 TRANSVERSE = 6 

163 

164 

165# transforms (also defined in Imaging.h) 

166class Transform(IntEnum): 

167 AFFINE = 0 

168 EXTENT = 1 

169 PERSPECTIVE = 2 

170 QUAD = 3 

171 MESH = 4 

172 

173 

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

175class Resampling(IntEnum): 

176 NEAREST = 0 

177 BOX = 4 

178 BILINEAR = 2 

179 HAMMING = 5 

180 BICUBIC = 3 

181 LANCZOS = 1 

182 

183 

184_filters_support = { 

185 Resampling.BOX: 0.5, 

186 Resampling.BILINEAR: 1.0, 

187 Resampling.HAMMING: 1.0, 

188 Resampling.BICUBIC: 2.0, 

189 Resampling.LANCZOS: 3.0, 

190} 

191 

192 

193# dithers 

194class Dither(IntEnum): 

195 NONE = 0 

196 ORDERED = 1 # Not yet implemented 

197 RASTERIZE = 2 # Not yet implemented 

198 FLOYDSTEINBERG = 3 # default 

199 

200 

201# palettes/quantizers 

202class Palette(IntEnum): 

203 WEB = 0 

204 ADAPTIVE = 1 

205 

206 

207class Quantize(IntEnum): 

208 MEDIANCUT = 0 

209 MAXCOVERAGE = 1 

210 FASTOCTREE = 2 

211 LIBIMAGEQUANT = 3 

212 

213 

214module = sys.modules[__name__] 

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

216 for item in enum: 

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

218 

219 

220if hasattr(core, "DEFAULT_STRATEGY"): 

221 DEFAULT_STRATEGY = core.DEFAULT_STRATEGY 

222 FILTERED = core.FILTERED 

223 HUFFMAN_ONLY = core.HUFFMAN_ONLY 

224 RLE = core.RLE 

225 FIXED = core.FIXED 

226 

227 

228# -------------------------------------------------------------------- 

229# Registries 

230 

231if TYPE_CHECKING: 

232 from . import ImageFile, PyAccess 

233ID: list[str] = [] 

234OPEN: dict[ 

235 str, 

236 tuple[ 

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

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

239 ], 

240] = {} 

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

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

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

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

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

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

247 

248# -------------------------------------------------------------------- 

249# Modes 

250 

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

252 

253 

254def _conv_type_shape(im): 

255 m = ImageMode.getmode(im.mode) 

256 shape = (im.height, im.width) 

257 extra = len(m.bands) 

258 if extra != 1: 

259 shape += (extra,) 

260 return shape, m.typestr 

261 

262 

263MODES = [ 

264 "1", 

265 "CMYK", 

266 "F", 

267 "HSV", 

268 "I", 

269 "I;16", 

270 "I;16B", 

271 "I;16L", 

272 "I;16N", 

273 "L", 

274 "LA", 

275 "La", 

276 "LAB", 

277 "P", 

278 "PA", 

279 "RGB", 

280 "RGBA", 

281 "RGBa", 

282 "RGBX", 

283 "YCbCr", 

284] 

285 

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

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

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

289 

290 

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

292 """ 

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

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

295 contain color data. 

296 

297 :param mode: Input mode. 

298 :returns: "L" or "RGB". 

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

300 """ 

301 return ImageMode.getmode(mode).basemode 

302 

303 

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

305 """ 

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

307 single-layer mode suitable for storing individual bands. 

308 

309 :param mode: Input mode. 

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

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

312 """ 

313 return ImageMode.getmode(mode).basetype 

314 

315 

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

317 """ 

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

319 a tuple containing the names of individual bands (use 

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

321 individual band. 

322 

323 :param mode: Input mode. 

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

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

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

327 """ 

328 return ImageMode.getmode(mode).bands 

329 

330 

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

332 """ 

333 Gets the number of individual bands for this mode. 

334 

335 :param mode: Input mode. 

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

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

338 """ 

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

340 

341 

342# -------------------------------------------------------------------- 

343# Helpers 

344 

345_initialized = 0 

346 

347 

348def preinit() -> None: 

349 """ 

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

351 

352 It is called when opening or saving images. 

353 """ 

354 

355 global _initialized 

356 if _initialized >= 1: 

357 return 

358 

359 try: 

360 from . import BmpImagePlugin 

361 

362 assert BmpImagePlugin 

363 except ImportError: 

364 pass 

365 try: 

366 from . import GifImagePlugin 

367 

368 assert GifImagePlugin 

369 except ImportError: 

370 pass 

371 try: 

372 from . import JpegImagePlugin 

373 

374 assert JpegImagePlugin 

375 except ImportError: 

376 pass 

377 try: 

378 from . import PpmImagePlugin 

379 

380 assert PpmImagePlugin 

381 except ImportError: 

382 pass 

383 try: 

384 from . import PngImagePlugin 

385 

386 assert PngImagePlugin 

387 except ImportError: 

388 pass 

389 

390 _initialized = 1 

391 

392 

393def init() -> bool: 

394 """ 

395 Explicitly initializes the Python Imaging Library. This function 

396 loads all available file format drivers. 

397 

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

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

400 """ 

401 

402 global _initialized 

403 if _initialized >= 2: 

404 return False 

405 

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

407 for plugin in _plugins: 

408 try: 

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

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

411 except ImportError as e: 

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

413 

414 if OPEN or SAVE: 

415 _initialized = 2 

416 return True 

417 return False 

418 

419 

420# -------------------------------------------------------------------- 

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

422 

423 

424def _getdecoder( 

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

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

427 # tweak arguments 

428 if args is None: 

429 args = () 

430 elif not isinstance(args, tuple): 

431 args = (args,) 

432 

433 try: 

434 decoder = DECODERS[decoder_name] 

435 except KeyError: 

436 pass 

437 else: 

438 return decoder(mode, *args + extra) 

439 

440 try: 

441 # get decoder 

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

443 except AttributeError as e: 

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

445 raise OSError(msg) from e 

446 return decoder(mode, *args + extra) 

447 

448 

449def _getencoder( 

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

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

452 # tweak arguments 

453 if args is None: 

454 args = () 

455 elif not isinstance(args, tuple): 

456 args = (args,) 

457 

458 try: 

459 encoder = ENCODERS[encoder_name] 

460 except KeyError: 

461 pass 

462 else: 

463 return encoder(mode, *args + extra) 

464 

465 try: 

466 # get encoder 

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

468 except AttributeError as e: 

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

470 raise OSError(msg) from e 

471 return encoder(mode, *args + extra) 

472 

473 

474# -------------------------------------------------------------------- 

475# Simple expression analyzer 

476 

477 

478class _E: 

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

480 self.scale = scale 

481 self.offset = offset 

482 

483 def __neg__(self): 

484 return _E(-self.scale, -self.offset) 

485 

486 def __add__(self, other): 

487 if isinstance(other, _E): 

488 return _E(self.scale + other.scale, self.offset + other.offset) 

489 return _E(self.scale, self.offset + other) 

490 

491 __radd__ = __add__ 

492 

493 def __sub__(self, other): 

494 return self + -other 

495 

496 def __rsub__(self, other): 

497 return other + -self 

498 

499 def __mul__(self, other): 

500 if isinstance(other, _E): 

501 return NotImplemented 

502 return _E(self.scale * other, self.offset * other) 

503 

504 __rmul__ = __mul__ 

505 

506 def __truediv__(self, other): 

507 if isinstance(other, _E): 

508 return NotImplemented 

509 return _E(self.scale / other, self.offset / other) 

510 

511 

512def _getscaleoffset(expr): 

513 a = expr(_E(1, 0)) 

514 return (a.scale, a.offset) if isinstance(a, _E) else (0, a) 

515 

516 

517# -------------------------------------------------------------------- 

518# Implementation wrapper 

519 

520 

521class SupportsGetData(Protocol): 

522 def getdata( 

523 self, 

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

525 

526 

527class Image: 

528 """ 

529 This class represents an image object. To create 

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

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

532 directly. 

533 

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

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

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

537 """ 

538 

539 format: str | None = None 

540 format_description: str | None = None 

541 _close_exclusive_fp_after_loading = True 

542 

543 def __init__(self): 

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

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

546 self.im = None 

547 self._mode = "" 

548 self._size = (0, 0) 

549 self.palette = None 

550 self.info = {} 

551 self.readonly = 0 

552 self.pyaccess = None 

553 self._exif = None 

554 

555 @property 

556 def width(self) -> int: 

557 return self.size[0] 

558 

559 @property 

560 def height(self) -> int: 

561 return self.size[1] 

562 

563 @property 

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

565 return self._size 

566 

567 @property 

568 def mode(self) -> str: 

569 return self._mode 

570 

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

572 new = Image() 

573 new.im = im 

574 new._mode = im.mode 

575 new._size = im.size 

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

577 if self.palette: 

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

579 else: 

580 from . import ImagePalette 

581 

582 new.palette = ImagePalette.ImagePalette() 

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

584 return new 

585 

586 # Context manager support 

587 def __enter__(self): 

588 return self 

589 

590 def _close_fp(self): 

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

592 if self._fp != self.fp: 

593 self._fp.close() 

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

595 if self.fp: 

596 self.fp.close() 

597 

598 def __exit__(self, *args): 

599 if hasattr(self, "fp"): 

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

601 self._close_fp() 

602 self.fp = None 

603 

604 def close(self) -> None: 

605 """ 

606 Closes the file pointer, if possible. 

607 

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

609 The image data will be unusable afterward. 

610 

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

612 have not had their file read and closed by the 

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

614 more information. 

615 """ 

616 if hasattr(self, "fp"): 

617 try: 

618 self._close_fp() 

619 self.fp = None 

620 except Exception as msg: 

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

622 

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

624 self.map = None 

625 

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

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

628 # object is gone. 

629 self.im = DeferredError(ValueError("Operation on closed image")) 

630 

631 def _copy(self) -> None: 

632 self.load() 

633 self.im = self.im.copy() 

634 self.pyaccess = None 

635 self.readonly = 0 

636 

637 def _ensure_mutable(self) -> None: 

638 if self.readonly: 

639 self._copy() 

640 else: 

641 self.load() 

642 

643 def _dump( 

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

645 ) -> str: 

646 suffix = "" 

647 if format: 

648 suffix = f".{format}" 

649 

650 if not file: 

651 f, filename = tempfile.mkstemp(suffix) 

652 os.close(f) 

653 else: 

654 filename = file 

655 if not filename.endswith(suffix): 

656 filename = filename + suffix 

657 

658 self.load() 

659 

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

661 self.im.save_ppm(filename) 

662 else: 

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

664 

665 return filename 

666 

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

668 if self.__class__ is not other.__class__: 

669 return False 

670 assert isinstance(other, Image) 

671 return ( 

672 self.mode == other.mode 

673 and self.size == other.size 

674 and self.info == other.info 

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

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

677 ) 

678 

679 def __repr__(self) -> str: 

680 return "<%s.%s image mode=%s size=%dx%d at 0x%X>" % ( 

681 self.__class__.__module__, 

682 self.__class__.__name__, 

683 self.mode, 

684 self.size[0], 

685 self.size[1], 

686 id(self), 

687 ) 

688 

689 def _repr_pretty_(self, p, cycle) -> None: 

690 """IPython plain text display support""" 

691 

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

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

694 p.text( 

695 "<%s.%s image mode=%s size=%dx%d>" 

696 % ( 

697 self.__class__.__module__, 

698 self.__class__.__name__, 

699 self.mode, 

700 self.size[0], 

701 self.size[1], 

702 ) 

703 ) 

704 

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

706 """Helper function for iPython display hook. 

707 

708 :param image_format: Image format. 

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

710 """ 

711 b = io.BytesIO() 

712 try: 

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

714 except Exception: 

715 return None 

716 return b.getvalue() 

717 

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

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

720 

721 :returns: PNG version of the image as bytes 

722 """ 

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

724 

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

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

727 

728 :returns: JPEG version of the image as bytes 

729 """ 

730 return self._repr_image("JPEG") 

731 

732 @property 

733 def __array_interface__(self): 

734 # numpy array interface support 

735 new = {"version": 3} 

736 try: 

737 if self.mode == "1": 

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

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

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

741 else: 

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

743 except Exception as e: 

744 if not isinstance(e, (MemoryError, RecursionError)): 

745 try: 

746 import numpy 

747 from packaging.version import parse as parse_version 

748 except ImportError: 

749 pass 

750 else: 

751 if parse_version(numpy.__version__) < parse_version("1.23"): 

752 warnings.warn(str(e)) 

753 raise 

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

755 return new 

756 

757 def __getstate__(self): 

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

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

760 

761 def __setstate__(self, state) -> None: 

762 Image.__init__(self) 

763 info, mode, size, palette, data = state 

764 self.info = info 

765 self._mode = mode 

766 self._size = size 

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

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

769 self.putpalette(palette) 

770 self.frombytes(data) 

771 

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

773 """ 

774 Return image as a bytes object. 

775 

776 .. warning:: 

777 

778 This method returns the raw image data from the internal 

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

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

781 data. 

782 

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

784 use the standard "raw" encoder. 

785 

786 A list of C encoders can be seen under 

787 codecs section of the function array in 

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

789 registered within the relevant plugins. 

790 :param args: Extra arguments to the encoder. 

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

792 """ 

793 

794 encoder_args: Any = args 

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

796 # may pass tuple instead of argument list 

797 encoder_args = encoder_args[0] 

798 

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

800 encoder_args = self.mode 

801 

802 self.load() 

803 

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

805 return b"" 

806 

807 # unpack data 

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

809 e.setimage(self.im) 

810 

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

812 

813 output = [] 

814 while True: 

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

816 output.append(data) 

817 if errcode: 

818 break 

819 if errcode < 0: 

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

821 raise RuntimeError(msg) 

822 

823 return b"".join(output) 

824 

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

826 """ 

827 Returns the image converted to an X11 bitmap. 

828 

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

830 

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

832 :returns: A string containing an X11 bitmap. 

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

834 """ 

835 

836 self.load() 

837 if self.mode != "1": 

838 msg = "not a bitmap" 

839 raise ValueError(msg) 

840 data = self.tobytes("xbm") 

841 return b"".join( 

842 [ 

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

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

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

846 data, 

847 b"};", 

848 ] 

849 ) 

850 

851 def frombytes( 

852 self, data: bytes | bytearray, decoder_name: str = "raw", *args: Any 

853 ) -> None: 

854 """ 

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

856 

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

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

859 """ 

860 

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

862 return 

863 

864 decoder_args: Any = args 

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

866 # may pass tuple instead of argument list 

867 decoder_args = decoder_args[0] 

868 

869 # default format 

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

871 decoder_args = self.mode 

872 

873 # unpack data 

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

875 d.setimage(self.im) 

876 s = d.decode(data) 

877 

878 if s[0] >= 0: 

879 msg = "not enough image data" 

880 raise ValueError(msg) 

881 if s[1] != 0: 

882 msg = "cannot decode image data" 

883 raise ValueError(msg) 

884 

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

886 """ 

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

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

889 Image class automatically loads an opened image when it is 

890 accessed for the first time. 

891 

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

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

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

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

896 

897 :returns: An image access object. 

898 :rtype: :py:class:`.PixelAccess` or :py:class:`.PyAccess` 

899 """ 

900 if self.im is not None and self.palette and self.palette.dirty: 

901 # realize palette 

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

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

904 self.palette.dirty = 0 

905 self.palette.rawmode = None 

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

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

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

909 else: 

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

911 self.palette.mode = "RGBA" 

912 else: 

913 self.palette.palette = self.im.getpalette( 

914 self.palette.mode, self.palette.mode 

915 ) 

916 

917 if self.im is not None: 

918 if cffi and USE_CFFI_ACCESS: 

919 if self.pyaccess: 

920 return self.pyaccess 

921 from . import PyAccess 

922 

923 self.pyaccess = PyAccess.new(self, self.readonly) 

924 if self.pyaccess: 

925 return self.pyaccess 

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

927 return None 

928 

929 def verify(self) -> None: 

930 """ 

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

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

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

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

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

936 file. 

937 """ 

938 pass 

939 

940 def convert( 

941 self, 

942 mode: str | None = None, 

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

944 dither: Dither | None = None, 

945 palette: Palette = Palette.WEB, 

946 colors: int = 256, 

947 ) -> Image: 

948 """ 

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

950 method translates pixels through the palette. If mode is 

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

952 and the palette can be represented without a palette. 

953 

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

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

956 

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

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

959 

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

961 

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

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

964 dither to approximate the original image luminosity levels. If 

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

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

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

968 

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

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

971 and ``dither`` and ``palette`` are ignored. 

972 

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

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

975 

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

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

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

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

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

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

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

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

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

985 :data:`Palette.ADAPTIVE`. 

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

987 palette. Defaults to 256. 

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

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

990 """ 

991 

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

993 deprecate(mode, 12) 

994 

995 self.load() 

996 

997 has_transparency = "transparency" in self.info 

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

999 # determine default mode 

1000 if self.palette: 

1001 mode = self.palette.mode 

1002 else: 

1003 mode = "RGB" 

1004 if mode == "RGB" and has_transparency: 

1005 mode = "RGBA" 

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

1007 return self.copy() 

1008 

1009 if matrix: 

1010 # matrix conversion 

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

1012 msg = "illegal conversion" 

1013 raise ValueError(msg) 

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

1015 new_im = self._new(im) 

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

1017 transparency = new_im.info["transparency"] 

1018 

1019 def convert_transparency( 

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

1021 ) -> int: 

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

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

1024 

1025 if mode == "L": 

1026 transparency = convert_transparency(matrix, transparency) 

1027 elif len(mode) == 3: 

1028 transparency = tuple( 

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

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

1031 ) 

1032 new_im.info["transparency"] = transparency 

1033 return new_im 

1034 

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

1036 return self.quantize(colors) 

1037 

1038 trns = None 

1039 delete_trns = False 

1040 # transparency handling 

1041 if has_transparency: 

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

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

1044 ): 

1045 # Use transparent conversion to promote from transparent 

1046 # color to an alpha channel. 

1047 new_im = self._new( 

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

1049 ) 

1050 del new_im.info["transparency"] 

1051 return new_im 

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

1053 t = self.info["transparency"] 

1054 if isinstance(t, bytes): 

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

1056 warnings.warn( 

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

1058 "converted to RGBA images" 

1059 ) 

1060 delete_trns = True 

1061 else: 

1062 # get the new transparency color. 

1063 # use existing conversions 

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

1065 if self.mode == "P": 

1066 trns_im.putpalette(self.palette) 

1067 if isinstance(t, tuple): 

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

1069 try: 

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

1071 except ValueError as e: 

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

1073 # If all 256 colors are in use, 

1074 # then there is no need for transparency 

1075 t = None 

1076 else: 

1077 raise ValueError(err) from e 

1078 if t is None: 

1079 trns = None 

1080 else: 

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

1082 

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

1084 trns_im = trns_im.convert(mode) 

1085 else: 

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

1087 # after quantization. 

1088 trns_im = trns_im.convert("RGB") 

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

1090 

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

1092 t = self.info["transparency"] 

1093 delete_trns = True 

1094 

1095 if isinstance(t, bytes): 

1096 self.im.putpalettealphas(t) 

1097 elif isinstance(t, int): 

1098 self.im.putpalettealpha(t, 0) 

1099 else: 

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

1101 raise ValueError(msg) 

1102 

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

1104 im = self.im.quantize(colors) 

1105 new_im = self._new(im) 

1106 from . import ImagePalette 

1107 

1108 new_im.palette = ImagePalette.ImagePalette( 

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

1110 ) 

1111 if delete_trns: 

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

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

1114 del new_im.info["transparency"] 

1115 if trns is not None: 

1116 try: 

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

1118 cast(Tuple[int, ...], trns), # trns was converted to RGB 

1119 new_im, 

1120 ) 

1121 except Exception: 

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

1123 # transparency hanging around to mess us up. 

1124 del new_im.info["transparency"] 

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

1126 return new_im 

1127 

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

1129 other_mode = mode if self.mode == "LAB" else self.mode 

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

1131 from . import ImageCms 

1132 

1133 srgb = ImageCms.createProfile("sRGB") 

1134 lab = ImageCms.createProfile("LAB") 

1135 profiles = [lab, srgb] if self.mode == "LAB" else [srgb, lab] 

1136 transform = ImageCms.buildTransform( 

1137 profiles[0], profiles[1], self.mode, mode 

1138 ) 

1139 return transform.apply(self) 

1140 

1141 # colorspace conversion 

1142 if dither is None: 

1143 dither = Dither.FLOYDSTEINBERG 

1144 

1145 try: 

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

1147 except ValueError: 

1148 try: 

1149 # normalize source image and try again 

1150 modebase = getmodebase(self.mode) 

1151 if modebase == self.mode: 

1152 raise 

1153 im = self.im.convert(modebase) 

1154 im = im.convert(mode, dither) 

1155 except KeyError as e: 

1156 msg = "illegal conversion" 

1157 raise ValueError(msg) from e 

1158 

1159 new_im = self._new(im) 

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

1161 from . import ImagePalette 

1162 

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

1164 if delete_trns: 

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

1166 del new_im.info["transparency"] 

1167 if trns is not None: 

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

1169 try: 

1170 new_im.info["transparency"] = new_im.palette.getcolor(trns, new_im) 

1171 except ValueError as e: 

1172 del new_im.info["transparency"] 

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

1174 # If all 256 colors are in use, 

1175 # then there is no need for transparency 

1176 warnings.warn( 

1177 "Couldn't allocate palette entry for transparency" 

1178 ) 

1179 else: 

1180 new_im.info["transparency"] = trns 

1181 return new_im 

1182 

1183 def quantize( 

1184 self, 

1185 colors: int = 256, 

1186 method: int | None = None, 

1187 kmeans: int = 0, 

1188 palette=None, 

1189 dither: Dither = Dither.FLOYDSTEINBERG, 

1190 ) -> Image: 

1191 """ 

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

1193 of colors. 

1194 

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

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

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

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

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

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

1201 ``feature="libimagequant"``). 

1202 

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

1204 

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

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

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

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

1209 :param palette: Quantize to the palette of given 

1210 :py:class:`PIL.Image.Image`. 

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

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

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

1214 (default). 

1215 :returns: A new image 

1216 """ 

1217 

1218 self.load() 

1219 

1220 if method is None: 

1221 # defaults: 

1222 method = Quantize.MEDIANCUT 

1223 if self.mode == "RGBA": 

1224 method = Quantize.FASTOCTREE 

1225 

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

1227 Quantize.FASTOCTREE, 

1228 Quantize.LIBIMAGEQUANT, 

1229 ): 

1230 # Caller specified an invalid mode. 

1231 msg = ( 

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

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

1234 ) 

1235 raise ValueError(msg) 

1236 

1237 if palette: 

1238 # use palette from reference image 

1239 palette.load() 

1240 if palette.mode != "P": 

1241 msg = "bad mode for palette image" 

1242 raise ValueError(msg) 

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

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

1245 raise ValueError(msg) 

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

1247 new_im = self._new(im) 

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 = im.im.getpalette(mode, mode)[: colors * len(mode)] 

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

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 if TYPE_CHECKING: 

1358 from . import ImageFilter 

1359 

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

1361 """ 

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

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

1364 

1365 :param filter: Filter kernel. 

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

1367 

1368 from . import ImageFilter 

1369 

1370 self.load() 

1371 

1372 if callable(filter): 

1373 filter = filter() 

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

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

1376 raise TypeError(msg) 

1377 

1378 multiband = isinstance(filter, ImageFilter.MultibandFilter) 

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

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

1381 

1382 ims = [ 

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

1384 ] 

1385 return merge(self.mode, ims) 

1386 

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

1388 """ 

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

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

1391 

1392 :returns: A tuple containing band names. 

1393 :rtype: tuple 

1394 """ 

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

1396 

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

1398 """ 

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

1400 image. 

1401 

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

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

1404 Otherwise, trim pixels when all channels are zero. 

1405 Keyword-only argument. 

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

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

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

1409 method returns None. 

1410 

1411 """ 

1412 

1413 self.load() 

1414 return self.im.getbbox(alpha_only) 

1415 

1416 def getcolors(self, maxcolors: int = 256): 

1417 """ 

1418 Returns a list of colors used in this image. 

1419 

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

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

1422 return the index of the color in the palette. 

1423 

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

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

1426 256 colors. 

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

1428 """ 

1429 

1430 self.load() 

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

1432 h = self.im.histogram() 

1433 out = [(h[i], i) for i in range(256) if h[i]] 

1434 if len(out) > maxcolors: 

1435 return None 

1436 return out 

1437 return self.im.getcolors(maxcolors) 

1438 

1439 def getdata(self, band: int | None = None): 

1440 """ 

1441 Returns the contents of this image as a sequence object 

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

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

1444 line zero, and so on. 

1445 

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

1447 internal PIL data type, which only supports certain sequence 

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

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

1450 

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

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

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

1454 :returns: A sequence-like object. 

1455 """ 

1456 

1457 self.load() 

1458 if band is not None: 

1459 return self.im.getband(band) 

1460 return self.im # could be abused 

1461 

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

1463 """ 

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

1465 the image. 

1466 

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

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

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

1470 """ 

1471 

1472 self.load() 

1473 if self.im.bands > 1: 

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

1475 return self.im.getextrema() 

1476 

1477 def getxmp(self): 

1478 """ 

1479 Returns a dictionary containing the XMP tags. 

1480 Requires defusedxml to be installed. 

1481 

1482 :returns: XMP tags in a dictionary. 

1483 """ 

1484 

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

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

1487 

1488 def get_value(element): 

1489 value = {get_name(k): v for k, v in element.attrib.items()} 

1490 children = list(element) 

1491 if children: 

1492 for child in children: 

1493 name = get_name(child.tag) 

1494 child_value = get_value(child) 

1495 if name in value: 

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

1497 value[name] = [value[name]] 

1498 value[name].append(child_value) 

1499 else: 

1500 value[name] = child_value 

1501 elif value: 

1502 if element.text: 

1503 value["text"] = element.text 

1504 else: 

1505 return element.text 

1506 return value 

1507 

1508 if ElementTree is None: 

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

1510 return {} 

1511 if "xmp" not in self.info: 

1512 return {} 

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

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

1515 

1516 def getexif(self) -> Exif: 

1517 """ 

1518 Gets EXIF data from the image. 

1519 

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

1521 """ 

1522 if self._exif is None: 

1523 self._exif = Exif() 

1524 elif self._exif._loaded: 

1525 return self._exif 

1526 self._exif._loaded = True 

1527 

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

1529 if exif_info is None: 

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

1531 exif_info = bytes.fromhex( 

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

1533 ) 

1534 elif hasattr(self, "tag_v2"): 

1535 self._exif.bigtiff = self.tag_v2._bigtiff 

1536 self._exif.endian = self.tag_v2._endian 

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

1538 if exif_info is not None: 

1539 self._exif.load(exif_info) 

1540 

1541 # XMP tags 

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

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

1544 if xmp_tags: 

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

1546 if match: 

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

1548 

1549 return self._exif 

1550 

1551 def _reload_exif(self) -> None: 

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

1553 return 

1554 self._exif._loaded = False 

1555 self.getexif() 

1556 

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

1558 child_images = [] 

1559 exif = self.getexif() 

1560 ifds = [] 

1561 if ExifTags.Base.SubIFDs in exif: 

1562 subifd_offsets = exif[ExifTags.Base.SubIFDs] 

1563 if subifd_offsets: 

1564 if not isinstance(subifd_offsets, tuple): 

1565 subifd_offsets = (subifd_offsets,) 

1566 for subifd_offset in subifd_offsets: 

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

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

1569 if ifd1 and ifd1.get(513): 

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 thumbnail_offset = ifd.get(513) 

1580 if thumbnail_offset is not None: 

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

1582 self.fp.seek(thumbnail_offset) 

1583 data = self.fp.read(ifd.get(514)) 

1584 fp = io.BytesIO(data) 

1585 

1586 with open(fp) as im: 

1587 from . import TiffImagePlugin 

1588 

1589 if thumbnail_offset is None and isinstance( 

1590 im, TiffImagePlugin.TiffImageFile 

1591 ): 

1592 im._frame_pos = [ifd_offset] 

1593 im._seek(0) 

1594 im.load() 

1595 child_images.append(im) 

1596 

1597 if offset is not None: 

1598 self.fp.seek(offset) 

1599 return child_images 

1600 

1601 def getim(self): 

1602 """ 

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

1604 

1605 :returns: A capsule object. 

1606 """ 

1607 

1608 self.load() 

1609 return self.im.ptr 

1610 

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

1612 """ 

1613 Returns the image palette as a list. 

1614 

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

1616 return the palette in its current mode. 

1617 

1618 .. versionadded:: 9.1.0 

1619 

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

1621 image has no palette. 

1622 """ 

1623 

1624 self.load() 

1625 try: 

1626 mode = self.im.getpalettemode() 

1627 except ValueError: 

1628 return None # no palette 

1629 if rawmode is None: 

1630 rawmode = mode 

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

1632 

1633 @property 

1634 def has_transparency_data(self) -> bool: 

1635 """ 

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

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

1638 in the info dictionary. 

1639 

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

1641 within are opaque. 

1642 

1643 :returns: A boolean. 

1644 """ 

1645 return ( 

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

1647 or (self.mode == "P" and self.palette.mode.endswith("A")) 

1648 or "transparency" in self.info 

1649 ) 

1650 

1651 def apply_transparency(self) -> None: 

1652 """ 

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

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

1655 Otherwise, the image is unchanged. 

1656 """ 

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

1658 return 

1659 

1660 from . import ImagePalette 

1661 

1662 palette = self.getpalette("RGBA") 

1663 assert palette is not None 

1664 transparency = self.info["transparency"] 

1665 if isinstance(transparency, bytes): 

1666 for i, alpha in enumerate(transparency): 

1667 palette[i * 4 + 3] = alpha 

1668 else: 

1669 palette[transparency * 4 + 3] = 0 

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

1671 self.palette.dirty = 1 

1672 

1673 del self.info["transparency"] 

1674 

1675 def getpixel( 

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

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

1678 """ 

1679 Returns the pixel value at a given position. 

1680 

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

1682 :ref:`coordinate-system`. 

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

1684 this method returns a tuple. 

1685 """ 

1686 

1687 self.load() 

1688 if self.pyaccess: 

1689 return self.pyaccess.getpixel(xy) 

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

1691 

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

1693 """ 

1694 Get projection to x and y axes 

1695 

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

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

1698 """ 

1699 

1700 self.load() 

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

1702 return list(x), list(y) 

1703 

1704 def histogram(self, mask: Image | None = None, extrema=None) -> list[int]: 

1705 """ 

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

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

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

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

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

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

1712 

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

1714 by this method. 

1715 

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

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

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

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

1720 

1721 :param mask: An optional mask. 

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

1723 :returns: A list containing pixel counts. 

1724 """ 

1725 self.load() 

1726 if mask: 

1727 mask.load() 

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

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

1730 if extrema is None: 

1731 extrema = self.getextrema() 

1732 return self.im.histogram(extrema) 

1733 return self.im.histogram() 

1734 

1735 def entropy(self, mask=None, extrema=None): 

1736 """ 

1737 Calculates and returns the entropy for the image. 

1738 

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

1740 image by this method. 

1741 

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

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

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

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

1746 

1747 :param mask: An optional mask. 

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

1749 :returns: A float value representing the image entropy 

1750 """ 

1751 self.load() 

1752 if mask: 

1753 mask.load() 

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

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

1756 if extrema is None: 

1757 extrema = self.getextrema() 

1758 return self.im.entropy(extrema) 

1759 return self.im.entropy() 

1760 

1761 def paste( 

1762 self, 

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

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

1765 mask: Image | None = None, 

1766 ) -> None: 

1767 """ 

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

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

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

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

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

1773 

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

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

1776 details). 

1777 

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

1779 containing pixel values. The method then fills the region 

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

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

1782 

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

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

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

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

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

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

1789 channels if they have them. 

1790 

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

1792 combine images with respect to their alpha channels. 

1793 

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

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

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

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

1798 upper left corner. 

1799 

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

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

1802 is interpreted as a mask image. 

1803 :param mask: An optional mask image. 

1804 """ 

1805 

1806 if isImageType(box): 

1807 if mask is not None: 

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

1809 raise ValueError(msg) 

1810 # abbreviated paste(im, mask) syntax 

1811 mask = box 

1812 box = None 

1813 assert not isinstance(box, Image) 

1814 

1815 if box is None: 

1816 box = (0, 0) 

1817 

1818 if len(box) == 2: 

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

1820 if isImageType(im): 

1821 size = im.size 

1822 elif isImageType(mask): 

1823 size = mask.size 

1824 else: 

1825 # FIXME: use self.size here? 

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

1827 raise ValueError(msg) 

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

1829 

1830 if isinstance(im, str): 

1831 from . import ImageColor 

1832 

1833 im = ImageColor.getcolor(im, self.mode) 

1834 

1835 elif isImageType(im): 

1836 im.load() 

1837 if self.mode != im.mode: 

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

1839 # should use an adapter for this! 

1840 im = im.convert(self.mode) 

1841 im = im.im 

1842 

1843 self._ensure_mutable() 

1844 

1845 if mask: 

1846 mask.load() 

1847 self.im.paste(im, box, mask.im) 

1848 else: 

1849 self.im.paste(im, box) 

1850 

1851 def alpha_composite( 

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

1853 ) -> None: 

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

1855 onto this image. 

1856 

1857 :param im: image to composite over this one 

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

1859 left corner in this (destination) image. 

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

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

1862 bottom) for the bounds of the source rectangle 

1863 

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

1865 """ 

1866 

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

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

1869 raise ValueError(msg) 

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

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

1872 raise ValueError(msg) 

1873 

1874 if len(source) == 4: 

1875 overlay_crop_box = tuple(source) 

1876 elif len(source) == 2: 

1877 overlay_crop_box = tuple(source) + im.size 

1878 else: 

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

1880 raise ValueError(msg) 

1881 

1882 if not len(dest) == 2: 

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

1884 raise ValueError(msg) 

1885 if min(source) < 0: 

1886 msg = "Source must be non-negative" 

1887 raise ValueError(msg) 

1888 

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

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

1891 overlay = im 

1892 else: 

1893 overlay = im.crop(overlay_crop_box) 

1894 

1895 # target for the paste 

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

1897 

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

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

1900 background = self 

1901 else: 

1902 background = self.crop(box) 

1903 

1904 result = alpha_composite(background, overlay) 

1905 self.paste(result, box) 

1906 

1907 def point( 

1908 self, 

1909 lut: Sequence[float] | Callable[[int], float] | ImagePointHandler, 

1910 mode: str | None = None, 

1911 ) -> Image: 

1912 """ 

1913 Maps this image through a lookup table or function. 

1914 

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

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

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

1918 single argument. The function is called once for each 

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

1920 all bands of the image. 

1921 

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

1923 object:: 

1924 

1925 class Example(Image.ImagePointHandler): 

1926 def point(self, data): 

1927 # Return result 

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

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

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

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

1932 """ 

1933 

1934 self.load() 

1935 

1936 if isinstance(lut, ImagePointHandler): 

1937 return lut.point(self) 

1938 

1939 if callable(lut): 

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

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

1942 # check if the function can be used with point_transform 

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

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

1945 scale, offset = _getscaleoffset(lut) 

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

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

1948 flatLut = [lut(i) for i in range(256)] * self.im.bands 

1949 else: 

1950 flatLut = lut 

1951 

1952 if self.mode == "F": 

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

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

1955 raise ValueError(msg) 

1956 

1957 if mode != "F": 

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

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

1960 

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

1962 """ 

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

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

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

1966 

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

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

1969 """ 

1970 

1971 self._ensure_mutable() 

1972 

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

1974 # attempt to promote self to a matching alpha mode 

1975 try: 

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

1977 try: 

1978 self.im.setmode(mode) 

1979 except (AttributeError, ValueError) as e: 

1980 # do things the hard way 

1981 im = self.im.convert(mode) 

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

1983 msg = "alpha channel could not be added" 

1984 raise ValueError(msg) from e # sanity check 

1985 self.im = im 

1986 self.pyaccess = None 

1987 self._mode = self.im.mode 

1988 except KeyError as e: 

1989 msg = "illegal image mode" 

1990 raise ValueError(msg) from e 

1991 

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

1993 band = 1 

1994 else: 

1995 band = 3 

1996 

1997 if isImageType(alpha): 

1998 # alpha layer 

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

2000 msg = "illegal image mode" 

2001 raise ValueError(msg) 

2002 alpha.load() 

2003 if alpha.mode == "1": 

2004 alpha = alpha.convert("L") 

2005 else: 

2006 # constant alpha 

2007 alpha = cast(int, alpha) # see python/typing#1013 

2008 try: 

2009 self.im.fillband(band, alpha) 

2010 except (AttributeError, ValueError): 

2011 # do things the hard way 

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

2013 else: 

2014 return 

2015 

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

2017 

2018 def putdata( 

2019 self, 

2020 data: Sequence[float] | Sequence[Sequence[int]], 

2021 scale: float = 1.0, 

2022 offset: float = 0.0, 

2023 ) -> None: 

2024 """ 

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

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

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

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

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

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

2031 

2032 :param data: A flattened sequence object. 

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

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

2035 """ 

2036 

2037 self._ensure_mutable() 

2038 

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

2040 

2041 def putpalette(self, data, rawmode="RGB") -> None: 

2042 """ 

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

2044 or "LA" image. 

2045 

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

2047 integer value for each channel in the raw mode. 

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

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

2050 index in the 256 colors. 

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

2052 containing red, green, blue and alpha values. 

2053 

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

2055 

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

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

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

2059 """ 

2060 from . import ImagePalette 

2061 

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

2063 msg = "illegal image mode" 

2064 raise ValueError(msg) 

2065 if isinstance(data, ImagePalette.ImagePalette): 

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

2067 else: 

2068 if not isinstance(data, bytes): 

2069 data = bytes(data) 

2070 palette = ImagePalette.raw(rawmode, data) 

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

2072 self.palette = palette 

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

2074 self.load() # install new palette 

2075 

2076 def putpixel( 

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

2078 ) -> None: 

2079 """ 

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

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

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

2083 accepted for P and PA images. 

2084 

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

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

2087 module instead. 

2088 

2089 See: 

2090 

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

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

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

2094 

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

2096 :ref:`coordinate-system`. 

2097 :param value: The pixel value. 

2098 """ 

2099 

2100 if self.readonly: 

2101 self._copy() 

2102 self.load() 

2103 

2104 if self.pyaccess: 

2105 return self.pyaccess.putpixel(xy, value) 

2106 

2107 if ( 

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

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

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

2111 ): 

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

2113 if self.mode == "PA": 

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

2115 value = value[:3] 

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

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

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

2119 

2120 def remap_palette(self, dest_map, source_palette=None): 

2121 """ 

2122 Rewrites the image to reorder the palette. 

2123 

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

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

2126 is the identity transform. 

2127 :param source_palette: Bytes or None. 

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

2129 

2130 """ 

2131 from . import ImagePalette 

2132 

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

2134 msg = "illegal image mode" 

2135 raise ValueError(msg) 

2136 

2137 bands = 3 

2138 palette_mode = "RGB" 

2139 if source_palette is None: 

2140 if self.mode == "P": 

2141 self.load() 

2142 palette_mode = self.im.getpalettemode() 

2143 if palette_mode == "RGBA": 

2144 bands = 4 

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

2146 else: # L-mode 

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

2148 

2149 palette_bytes = b"" 

2150 new_positions = [0] * 256 

2151 

2152 # pick only the used colors from the palette 

2153 for i, oldPosition in enumerate(dest_map): 

2154 palette_bytes += source_palette[ 

2155 oldPosition * bands : oldPosition * bands + bands 

2156 ] 

2157 new_positions[oldPosition] = i 

2158 

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

2160 

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

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

2163 # from palette 1 to palette 2. New_positions is 

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

2165 # palette 1 with any holes removed. 

2166 

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

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

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

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

2171 # sans palette thus converting the image bytes, then 

2172 # assigning the optimized RGB palette. 

2173 

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

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

2176 

2177 mapping_palette = bytearray(new_positions) 

2178 

2179 m_im = self.copy() 

2180 m_im._mode = "P" 

2181 

2182 m_im.palette = ImagePalette.ImagePalette( 

2183 palette_mode, palette=mapping_palette * bands 

2184 ) 

2185 # possibly set palette dirty, then 

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

2187 # or just force it. 

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

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

2190 

2191 m_im = m_im.convert("L") 

2192 

2193 m_im.putpalette(palette_bytes, palette_mode) 

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

2195 

2196 if "transparency" in self.info: 

2197 try: 

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

2199 except ValueError: 

2200 if "transparency" in m_im.info: 

2201 del m_im.info["transparency"] 

2202 

2203 return m_im 

2204 

2205 def _get_safe_box(self, size, resample, box): 

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

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

2208 """ 

2209 filter_support = _filters_support[resample] - 0.5 

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

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

2212 support_x = filter_support * scale_x 

2213 support_y = filter_support * scale_y 

2214 

2215 return ( 

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

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

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

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

2220 ) 

2221 

2222 def resize( 

2223 self, 

2224 size: tuple[int, int], 

2225 resample: int | None = None, 

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

2227 reducing_gap: float | None = None, 

2228 ) -> Image: 

2229 """ 

2230 Returns a resized copy of this image. 

2231 

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

2233 (width, height). 

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

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

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

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

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

2239 :py:data:`Resampling.NEAREST`. If the image mode specifies a number 

2240 of bits, such as "I;16", then the default filter is 

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

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

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

2244 the source image region to be scaled. 

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

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

2247 :param reducing_gap: Apply optimization by resizing the image 

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

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

2250 Second, resizing using regular resampling. The last step 

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

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

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

2254 the closer the result to the fair resampling. 

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

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

2257 indistinguishable from fair resampling in most cases. 

2258 The default value is None (no optimization). 

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

2260 """ 

2261 

2262 if resample is None: 

2263 type_special = ";" in self.mode 

2264 resample = Resampling.NEAREST if type_special else Resampling.BICUBIC 

2265 elif resample not in ( 

2266 Resampling.NEAREST, 

2267 Resampling.BILINEAR, 

2268 Resampling.BICUBIC, 

2269 Resampling.LANCZOS, 

2270 Resampling.BOX, 

2271 Resampling.HAMMING, 

2272 ): 

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

2274 

2275 filters = [ 

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

2277 for filter in ( 

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

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

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

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

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

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

2284 ) 

2285 ] 

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

2287 raise ValueError(msg) 

2288 

2289 if reducing_gap is not None and reducing_gap < 1.0: 

2290 msg = "reducing_gap must be 1.0 or greater" 

2291 raise ValueError(msg) 

2292 

2293 self.load() 

2294 if box is None: 

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

2296 

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

2298 return self.copy() 

2299 

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

2301 resample = Resampling.NEAREST 

2302 

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

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

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

2306 return im.convert(self.mode) 

2307 

2308 self.load() 

2309 

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

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

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

2313 if factor_x > 1 or factor_y > 1: 

2314 reduce_box = self._get_safe_box(size, resample, box) 

2315 factor = (factor_x, factor_y) 

2316 self = ( 

2317 self.reduce(factor, box=reduce_box) 

2318 if callable(self.reduce) 

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

2320 ) 

2321 box = ( 

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

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

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

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

2326 ) 

2327 

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

2329 

2330 def reduce( 

2331 self, 

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

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

2334 ) -> Image: 

2335 """ 

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

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

2338 the resulting size will be rounded up. 

2339 

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

2341 for width and height separately. 

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

2343 the source image region to be reduced. 

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

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

2346 """ 

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

2348 factor = (factor, factor) 

2349 

2350 if box is None: 

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

2352 

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

2354 return self.copy() 

2355 

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

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

2358 im = im.reduce(factor, box) 

2359 return im.convert(self.mode) 

2360 

2361 self.load() 

2362 

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

2364 

2365 def rotate( 

2366 self, 

2367 angle: float, 

2368 resample: Resampling = Resampling.NEAREST, 

2369 expand: int | bool = False, 

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

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

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

2373 ) -> Image: 

2374 """ 

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

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

2377 clockwise around its centre. 

2378 

2379 :param angle: In degrees counter clockwise. 

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

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

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

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

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

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

2386 See :ref:`concept-filters`. 

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

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

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

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

2391 the center and no translation. 

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

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

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

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

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

2397 """ 

2398 

2399 angle = angle % 360.0 

2400 

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

2402 # translating or changing the center. 

2403 if not (center or translate): 

2404 if angle == 0: 

2405 return self.copy() 

2406 if angle == 180: 

2407 return self.transpose(Transpose.ROTATE_180) 

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

2409 return self.transpose( 

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

2411 ) 

2412 

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

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

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

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

2417 

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

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

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

2421 # (0, 0, 1) (0, 0, 1) ( 0, 0, 1) (0, 0, 1) 

2422 

2423 # The reverse matrix is thus: 

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

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

2426 # (0, 0, 1) ( 0, 0, 1) (0, 0, 1) (0, 0, 1) 

2427 

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

2429 # compensate for the expand flag. 

2430 

2431 w, h = self.size 

2432 

2433 if translate is None: 

2434 post_trans = (0, 0) 

2435 else: 

2436 post_trans = translate 

2437 if center is None: 

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

2439 

2440 angle = -math.radians(angle) 

2441 matrix = [ 

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

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

2444 0.0, 

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

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

2447 0.0, 

2448 ] 

2449 

2450 def transform(x, y, matrix): 

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

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

2453 

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

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

2456 ) 

2457 matrix[2] += center[0] 

2458 matrix[5] += center[1] 

2459 

2460 if expand: 

2461 # calculate output size 

2462 xx = [] 

2463 yy = [] 

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

2465 x, y = transform(x, y, matrix) 

2466 xx.append(x) 

2467 yy.append(y) 

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

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

2470 

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

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

2473 # translation vector as new translation vector. 

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

2475 w, h = nw, nh 

2476 

2477 return self.transform( 

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

2479 ) 

2480 

2481 def save( 

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

2483 ) -> None: 

2484 """ 

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

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

2487 extension, if possible. 

2488 

2489 Keyword options can be used to provide additional instructions 

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

2491 silently ignored. The available options are described in the 

2492 :doc:`image format documentation 

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

2494 

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

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

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

2498 methods, and be opened in binary mode. 

2499 

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

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

2502 format to use is determined from the filename extension. 

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

2504 parameter should always be used. 

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

2506 :returns: None 

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

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

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

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

2511 """ 

2512 

2513 filename: str | bytes = "" 

2514 open_fp = False 

2515 if is_path(fp): 

2516 filename = os.path.realpath(os.fspath(fp)) 

2517 open_fp = True 

2518 elif fp == sys.stdout: 

2519 try: 

2520 fp = sys.stdout.buffer 

2521 except AttributeError: 

2522 pass 

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

2524 # only set the name for metadata purposes 

2525 filename = os.path.realpath(os.fspath(fp.name)) 

2526 

2527 # may mutate self! 

2528 self._ensure_mutable() 

2529 

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

2531 self.encoderinfo = params 

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

2533 

2534 preinit() 

2535 

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

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

2538 

2539 if not format: 

2540 if ext not in EXTENSION: 

2541 init() 

2542 try: 

2543 format = EXTENSION[ext] 

2544 except KeyError as e: 

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

2546 raise ValueError(msg) from e 

2547 

2548 if format.upper() not in SAVE: 

2549 init() 

2550 if save_all: 

2551 save_handler = SAVE_ALL[format.upper()] 

2552 else: 

2553 save_handler = SAVE[format.upper()] 

2554 

2555 created = False 

2556 if open_fp: 

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

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

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

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

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

2562 else: 

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

2564 else: 

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

2566 

2567 try: 

2568 save_handler(self, fp, filename) 

2569 except Exception: 

2570 if open_fp: 

2571 fp.close() 

2572 if created: 

2573 try: 

2574 os.remove(filename) 

2575 except PermissionError: 

2576 pass 

2577 raise 

2578 if open_fp: 

2579 fp.close() 

2580 

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

2582 """ 

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

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

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

2586 library automatically seeks to frame 0. 

2587 

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

2589 

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

2591 number of available frames. 

2592 

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

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

2595 of the sequence. 

2596 """ 

2597 

2598 # overridden by file handlers 

2599 if frame != 0: 

2600 msg = "no more images in file" 

2601 raise EOFError(msg) 

2602 

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

2604 """ 

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

2606 

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

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

2609 

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

2611 PNG format. 

2612 

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

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

2615 

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

2617 

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

2619 

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

2621 """ 

2622 

2623 _show(self, title=title) 

2624 

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

2626 """ 

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

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

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

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

2631 blue). 

2632 

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

2634 method can be more convenient and faster. 

2635 

2636 :returns: A tuple containing bands. 

2637 """ 

2638 

2639 self.load() 

2640 if self.im.bands == 1: 

2641 return (self.copy(),) 

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

2643 

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

2645 """ 

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

2647 

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

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

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

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

2652 

2653 .. versionadded:: 4.3.0 

2654 """ 

2655 self.load() 

2656 

2657 if isinstance(channel, str): 

2658 try: 

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

2660 except ValueError as e: 

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

2662 raise ValueError(msg) from e 

2663 

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

2665 

2666 def tell(self) -> int: 

2667 """ 

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

2669 

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

2671 number of available frames. 

2672 

2673 :returns: Frame number, starting with 0. 

2674 """ 

2675 return 0 

2676 

2677 def thumbnail( 

2678 self, 

2679 size: tuple[float, float], 

2680 resample: Resampling = Resampling.BICUBIC, 

2681 reducing_gap: float | None = 2.0, 

2682 ) -> None: 

2683 """ 

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

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

2686 the given size. This method calculates an appropriate thumbnail 

2687 size to preserve the aspect of the image, calls the 

2688 :py:meth:`~PIL.Image.Image.draft` method to configure the file reader 

2689 (where applicable), and finally resizes the image. 

2690 

2691 Note that this function modifies the :py:class:`~PIL.Image.Image` 

2692 object in place. If you need to use the full resolution image as well, 

2693 apply this method to a :py:meth:`~PIL.Image.Image.copy` of the original 

2694 image. 

2695 

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

2697 (width, height). 

2698 :param resample: Optional resampling filter. This can be one 

2699 of :py:data:`Resampling.NEAREST`, :py:data:`Resampling.BOX`, 

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

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

2702 If omitted, it defaults to :py:data:`Resampling.BICUBIC`. 

2703 (was :py:data:`Resampling.NEAREST` prior to version 2.5.0). 

2704 See: :ref:`concept-filters`. 

2705 :param reducing_gap: Apply optimization by resizing the image 

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

2707 using :py:meth:`~PIL.Image.Image.reduce` or 

2708 :py:meth:`~PIL.Image.Image.draft` for JPEG images. 

2709 Second, resizing using regular resampling. The last step 

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

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

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

2713 the closer the result to the fair resampling. 

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

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

2716 indistinguishable from fair resampling in most cases. 

2717 The default value is 2.0 (very close to fair resampling 

2718 while still being faster in many cases). 

2719 :returns: None 

2720 """ 

2721 

2722 provided_size = tuple(map(math.floor, size)) 

2723 

2724 def preserve_aspect_ratio() -> tuple[int, int] | None: 

2725 def round_aspect(number, key): 

2726 return max(min(math.floor(number), math.ceil(number), key=key), 1) 

2727 

2728 x, y = provided_size 

2729 if x >= self.width and y >= self.height: 

2730 return None 

2731 

2732 aspect = self.width / self.height 

2733 if x / y >= aspect: 

2734 x = round_aspect(y * aspect, key=lambda n: abs(aspect - n / y)) 

2735 else: 

2736 y = round_aspect( 

2737 x / aspect, key=lambda n: 0 if n == 0 else abs(aspect - x / n) 

2738 ) 

2739 return x, y 

2740 

2741 box = None 

2742 final_size: tuple[int, int] 

2743 if reducing_gap is not None: 

2744 preserved_size = preserve_aspect_ratio() 

2745 if preserved_size is None: 

2746 return 

2747 final_size = preserved_size 

2748 

2749 res = self.draft( 

2750 None, (int(size[0] * reducing_gap), int(size[1] * reducing_gap)) 

2751 ) 

2752 if res is not None: 

2753 box = res[1] 

2754 if box is None: 

2755 self.load() 

2756 

2757 # load() may have changed the size of the image 

2758 preserved_size = preserve_aspect_ratio() 

2759 if preserved_size is None: 

2760 return 

2761 final_size = preserved_size 

2762 

2763 if self.size != final_size: 

2764 im = self.resize(final_size, resample, box=box, reducing_gap=reducing_gap) 

2765 

2766 self.im = im.im 

2767 self._size = final_size 

2768 self._mode = self.im.mode 

2769 

2770 self.readonly = 0 

2771 self.pyaccess = None 

2772 

2773 # FIXME: the different transform methods need further explanation 

2774 # instead of bloating the method docs, add a separate chapter. 

2775 def transform( 

2776 self, 

2777 size: tuple[int, int], 

2778 method: Transform | ImageTransformHandler | SupportsGetData, 

2779 data: Sequence[Any] | None = None, 

2780 resample: int = Resampling.NEAREST, 

2781 fill: int = 1, 

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

2783 ) -> Image: 

2784 """ 

2785 Transforms this image. This method creates a new image with the 

2786 given size, and the same mode as the original, and copies data 

2787 to the new image using the given transform. 

2788 

2789 :param size: The output size in pixels, as a 2-tuple: 

2790 (width, height). 

2791 :param method: The transformation method. This is one of 

2792 :py:data:`Transform.EXTENT` (cut out a rectangular subregion), 

2793 :py:data:`Transform.AFFINE` (affine transform), 

2794 :py:data:`Transform.PERSPECTIVE` (perspective transform), 

2795 :py:data:`Transform.QUAD` (map a quadrilateral to a rectangle), or 

2796 :py:data:`Transform.MESH` (map a number of source quadrilaterals 

2797 in one operation). 

2798 

2799 It may also be an :py:class:`~PIL.Image.ImageTransformHandler` 

2800 object:: 

2801 

2802 class Example(Image.ImageTransformHandler): 

2803 def transform(self, size, data, resample, fill=1): 

2804 # Return result 

2805 

2806 Implementations of :py:class:`~PIL.Image.ImageTransformHandler` 

2807 for some of the :py:class:`Transform` methods are provided 

2808 in :py:mod:`~PIL.ImageTransform`. 

2809 

2810 It may also be an object with a ``method.getdata`` method 

2811 that returns a tuple supplying new ``method`` and ``data`` values:: 

2812 

2813 class Example: 

2814 def getdata(self): 

2815 method = Image.Transform.EXTENT 

2816 data = (0, 0, 100, 100) 

2817 return method, data 

2818 :param data: Extra data to the transformation method. 

2819 :param resample: Optional resampling filter. It can be one of 

2820 :py:data:`Resampling.NEAREST` (use nearest neighbour), 

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

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

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

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

2825 See: :ref:`concept-filters`. 

2826 :param fill: If ``method`` is an 

2827 :py:class:`~PIL.Image.ImageTransformHandler` object, this is one of 

2828 the arguments passed to it. Otherwise, it is unused. 

2829 :param fillcolor: Optional fill color for the area outside the 

2830 transform in the output image. 

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

2832 """ 

2833 

2834 if self.mode in ("LA", "RGBA") and resample != Resampling.NEAREST: 

2835 return ( 

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

2837 .transform(size, method, data, resample, fill, fillcolor) 

2838 .convert(self.mode) 

2839 ) 

2840 

2841 if isinstance(method, ImageTransformHandler): 

2842 return method.transform(size, self, resample=resample, fill=fill) 

2843 

2844 if hasattr(method, "getdata"): 

2845 # compatibility w. old-style transform objects 

2846 method, data = method.getdata() 

2847 

2848 if data is None: 

2849 msg = "missing method data" 

2850 raise ValueError(msg) 

2851 

2852 im = new(self.mode, size, fillcolor) 

2853 if self.mode == "P" and self.palette: 

2854 im.palette = self.palette.copy() 

2855 im.info = self.info.copy() 

2856 if method == Transform.MESH: 

2857 # list of quads 

2858 for box, quad in data: 

2859 im.__transformer( 

2860 box, self, Transform.QUAD, quad, resample, fillcolor is None 

2861 ) 

2862 else: 

2863 im.__transformer( 

2864 (0, 0) + size, self, method, data, resample, fillcolor is None 

2865 ) 

2866 

2867 return im 

2868 

2869 def __transformer( 

2870 self, box, image, method, data, resample=Resampling.NEAREST, fill=1 

2871 ): 

2872 w = box[2] - box[0] 

2873 h = box[3] - box[1] 

2874 

2875 if method == Transform.AFFINE: 

2876 data = data[:6] 

2877 

2878 elif method == Transform.EXTENT: 

2879 # convert extent to an affine transform 

2880 x0, y0, x1, y1 = data 

2881 xs = (x1 - x0) / w 

2882 ys = (y1 - y0) / h 

2883 method = Transform.AFFINE 

2884 data = (xs, 0, x0, 0, ys, y0) 

2885 

2886 elif method == Transform.PERSPECTIVE: 

2887 data = data[:8] 

2888 

2889 elif method == Transform.QUAD: 

2890 # quadrilateral warp. data specifies the four corners 

2891 # given as NW, SW, SE, and NE. 

2892 nw = data[:2] 

2893 sw = data[2:4] 

2894 se = data[4:6] 

2895 ne = data[6:8] 

2896 x0, y0 = nw 

2897 As = 1.0 / w 

2898 At = 1.0 / h 

2899 data = ( 

2900 x0, 

2901 (ne[0] - x0) * As, 

2902 (sw[0] - x0) * At, 

2903 (se[0] - sw[0] - ne[0] + x0) * As * At, 

2904 y0, 

2905 (ne[1] - y0) * As, 

2906 (sw[1] - y0) * At, 

2907 (se[1] - sw[1] - ne[1] + y0) * As * At, 

2908 ) 

2909 

2910 else: 

2911 msg = "unknown transformation method" 

2912 raise ValueError(msg) 

2913 

2914 if resample not in ( 

2915 Resampling.NEAREST, 

2916 Resampling.BILINEAR, 

2917 Resampling.BICUBIC, 

2918 ): 

2919 if resample in (Resampling.BOX, Resampling.HAMMING, Resampling.LANCZOS): 

2920 msg = { 

2921 Resampling.BOX: "Image.Resampling.BOX", 

2922 Resampling.HAMMING: "Image.Resampling.HAMMING", 

2923 Resampling.LANCZOS: "Image.Resampling.LANCZOS", 

2924 }[resample] + f" ({resample}) cannot be used." 

2925 else: 

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

2927 

2928 filters = [ 

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

2930 for filter in ( 

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

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

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

2934 ) 

2935 ] 

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

2937 raise ValueError(msg) 

2938 

2939 image.load() 

2940 

2941 self.load() 

2942 

2943 if image.mode in ("1", "P"): 

2944 resample = Resampling.NEAREST 

2945 

2946 self.im.transform(box, image.im, method, data, resample, fill) 

2947 

2948 def transpose(self, method: Transpose) -> Image: 

2949 """ 

2950 Transpose image (flip or rotate in 90 degree steps) 

2951 

2952 :param method: One of :py:data:`Transpose.FLIP_LEFT_RIGHT`, 

2953 :py:data:`Transpose.FLIP_TOP_BOTTOM`, :py:data:`Transpose.ROTATE_90`, 

2954 :py:data:`Transpose.ROTATE_180`, :py:data:`Transpose.ROTATE_270`, 

2955 :py:data:`Transpose.TRANSPOSE` or :py:data:`Transpose.TRANSVERSE`. 

2956 :returns: Returns a flipped or rotated copy of this image. 

2957 """ 

2958 

2959 self.load() 

2960 return self._new(self.im.transpose(method)) 

2961 

2962 def effect_spread(self, distance: int) -> Image: 

2963 """ 

2964 Randomly spread pixels in an image. 

2965 

2966 :param distance: Distance to spread pixels. 

2967 """ 

2968 self.load() 

2969 return self._new(self.im.effect_spread(distance)) 

2970 

2971 def toqimage(self): 

2972 """Returns a QImage copy of this image""" 

2973 from . import ImageQt 

2974 

2975 if not ImageQt.qt_is_installed: 

2976 msg = "Qt bindings are not installed" 

2977 raise ImportError(msg) 

2978 return ImageQt.toqimage(self) 

2979 

2980 def toqpixmap(self): 

2981 """Returns a QPixmap copy of this image""" 

2982 from . import ImageQt 

2983 

2984 if not ImageQt.qt_is_installed: 

2985 msg = "Qt bindings are not installed" 

2986 raise ImportError(msg) 

2987 return ImageQt.toqpixmap(self) 

2988 

2989 

2990# -------------------------------------------------------------------- 

2991# Abstract handlers. 

2992 

2993 

2994class ImagePointHandler: 

2995 """ 

2996 Used as a mixin by point transforms 

2997 (for use with :py:meth:`~PIL.Image.Image.point`) 

2998 """ 

2999 

3000 @abc.abstractmethod 

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

3002 pass 

3003 

3004 

3005class ImageTransformHandler: 

3006 """ 

3007 Used as a mixin by geometry transforms 

3008 (for use with :py:meth:`~PIL.Image.Image.transform`) 

3009 """ 

3010 

3011 @abc.abstractmethod 

3012 def transform( 

3013 self, 

3014 size: tuple[int, int], 

3015 image: Image, 

3016 **options: Any, 

3017 ) -> Image: 

3018 pass 

3019 

3020 

3021# -------------------------------------------------------------------- 

3022# Factories 

3023 

3024# 

3025# Debugging 

3026 

3027 

3028def _wedge() -> Image: 

3029 """Create grayscale wedge (for debugging only)""" 

3030 

3031 return Image()._new(core.wedge("L")) 

3032 

3033 

3034def _check_size(size: Any) -> None: 

3035 """ 

3036 Common check to enforce type and sanity check on size tuples 

3037 

3038 :param size: Should be a 2 tuple of (width, height) 

3039 :returns: None, or raises a ValueError 

3040 """ 

3041 

3042 if not isinstance(size, (list, tuple)): 

3043 msg = "Size must be a list or tuple" 

3044 raise ValueError(msg) 

3045 if len(size) != 2: 

3046 msg = "Size must be a sequence of length 2" 

3047 raise ValueError(msg) 

3048 if size[0] < 0 or size[1] < 0: 

3049 msg = "Width and height must be >= 0" 

3050 raise ValueError(msg) 

3051 

3052 

3053def new( 

3054 mode: str, 

3055 size: tuple[int, int] | list[int], 

3056 color: float | tuple[float, ...] | str | None = 0, 

3057) -> Image: 

3058 """ 

3059 Creates a new image with the given mode and size. 

3060 

3061 :param mode: The mode to use for the new image. See: 

3062 :ref:`concept-modes`. 

3063 :param size: A 2-tuple, containing (width, height) in pixels. 

3064 :param color: What color to use for the image. Default is black. 

3065 If given, this should be a single integer or floating point value 

3066 for single-band modes, and a tuple for multi-band modes (one value 

3067 per band). When creating RGB or HSV images, you can also use color 

3068 strings as supported by the ImageColor module. If the color is 

3069 None, the image is not initialised. 

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

3071 """ 

3072 

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

3074 deprecate(mode, 12) 

3075 

3076 _check_size(size) 

3077 

3078 if color is None: 

3079 # don't initialize 

3080 return Image()._new(core.new(mode, size)) 

3081 

3082 if isinstance(color, str): 

3083 # css3-style specifier 

3084 

3085 from . import ImageColor 

3086 

3087 color = ImageColor.getcolor(color, mode) 

3088 

3089 im = Image() 

3090 if ( 

3091 mode == "P" 

3092 and isinstance(color, (list, tuple)) 

3093 and all(isinstance(i, int) for i in color) 

3094 ): 

3095 color_ints: tuple[int, ...] = cast(Tuple[int, ...], tuple(color)) 

3096 if len(color_ints) == 3 or len(color_ints) == 4: 

3097 # RGB or RGBA value for a P image 

3098 from . import ImagePalette 

3099 

3100 im.palette = ImagePalette.ImagePalette() 

3101 color = im.palette.getcolor(color_ints) 

3102 return im._new(core.fill(mode, size, color)) 

3103 

3104 

3105def frombytes( 

3106 mode: str, 

3107 size: tuple[int, int], 

3108 data: bytes | bytearray, 

3109 decoder_name: str = "raw", 

3110 *args: Any, 

3111) -> Image: 

3112 """ 

3113 Creates a copy of an image memory from pixel data in a buffer. 

3114 

3115 In its simplest form, this function takes three arguments 

3116 (mode, size, and unpacked pixel data). 

3117 

3118 You can also use any pixel decoder supported by PIL. For more 

3119 information on available decoders, see the section 

3120 :ref:`Writing Your Own File Codec <file-codecs>`. 

3121 

3122 Note that this function decodes pixel data only, not entire images. 

3123 If you have an entire image in a string, wrap it in a 

3124 :py:class:`~io.BytesIO` object, and use :py:func:`~PIL.Image.open` to load 

3125 it. 

3126 

3127 :param mode: The image mode. See: :ref:`concept-modes`. 

3128 :param size: The image size. 

3129 :param data: A byte buffer containing raw data for the given mode. 

3130 :param decoder_name: What decoder to use. 

3131 :param args: Additional parameters for the given decoder. 

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

3133 """ 

3134 

3135 _check_size(size) 

3136 

3137 im = new(mode, size) 

3138 if im.width != 0 and im.height != 0: 

3139 decoder_args: Any = args 

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

3141 # may pass tuple instead of argument list 

3142 decoder_args = decoder_args[0] 

3143 

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

3145 decoder_args = mode 

3146 

3147 im.frombytes(data, decoder_name, decoder_args) 

3148 return im 

3149 

3150 

3151def frombuffer( 

3152 mode: str, size: tuple[int, int], data, decoder_name: str = "raw", *args: Any 

3153) -> Image: 

3154 """ 

3155 Creates an image memory referencing pixel data in a byte buffer. 

3156 

3157 This function is similar to :py:func:`~PIL.Image.frombytes`, but uses data 

3158 in the byte buffer, where possible. This means that changes to the 

3159 original buffer object are reflected in this image). Not all modes can 

3160 share memory; supported modes include "L", "RGBX", "RGBA", and "CMYK". 

3161 

3162 Note that this function decodes pixel data only, not entire images. 

3163 If you have an entire image file in a string, wrap it in a 

3164 :py:class:`~io.BytesIO` object, and use :py:func:`~PIL.Image.open` to load it. 

3165 

3166 The default parameters used for the "raw" decoder differs from that used for 

3167 :py:func:`~PIL.Image.frombytes`. This is a bug, and will probably be fixed in a 

3168 future release. The current release issues a warning if you do this; to disable 

3169 the warning, you should provide the full set of parameters. See below for details. 

3170 

3171 :param mode: The image mode. See: :ref:`concept-modes`. 

3172 :param size: The image size. 

3173 :param data: A bytes or other buffer object containing raw 

3174 data for the given mode. 

3175 :param decoder_name: What decoder to use. 

3176 :param args: Additional parameters for the given decoder. For the 

3177 default encoder ("raw"), it's recommended that you provide the 

3178 full set of parameters:: 

3179 

3180 frombuffer(mode, size, data, "raw", mode, 0, 1) 

3181 

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

3183 

3184 .. versionadded:: 1.1.4 

3185 """ 

3186 

3187 _check_size(size) 

3188 

3189 # may pass tuple instead of argument list 

3190 if len(args) == 1 and isinstance(args[0], tuple): 

3191 args = args[0] 

3192 

3193 if decoder_name == "raw": 

3194 if args == (): 

3195 args = mode, 0, 1 

3196 if args[0] in _MAPMODES: 

3197 im = new(mode, (0, 0)) 

3198 im = im._new(core.map_buffer(data, size, decoder_name, 0, args)) 

3199 if mode == "P": 

3200 from . import ImagePalette 

3201 

3202 im.palette = ImagePalette.ImagePalette("RGB", im.im.getpalette("RGB")) 

3203 im.readonly = 1 

3204 return im 

3205 

3206 return frombytes(mode, size, data, decoder_name, args) 

3207 

3208 

3209class SupportsArrayInterface(Protocol): 

3210 """ 

3211 An object that has an ``__array_interface__`` dictionary. 

3212 """ 

3213 

3214 @property 

3215 def __array_interface__(self) -> dict[str, Any]: 

3216 raise NotImplementedError() 

3217 

3218 

3219def fromarray(obj: SupportsArrayInterface, mode: str | None = None) -> Image: 

3220 """ 

3221 Creates an image memory from an object exporting the array interface 

3222 (using the buffer protocol):: 

3223 

3224 from PIL import Image 

3225 import numpy as np 

3226 a = np.zeros((5, 5)) 

3227 im = Image.fromarray(a) 

3228 

3229 If ``obj`` is not contiguous, then the ``tobytes`` method is called 

3230 and :py:func:`~PIL.Image.frombuffer` is used. 

3231 

3232 In the case of NumPy, be aware that Pillow modes do not always correspond 

3233 to NumPy dtypes. Pillow modes only offer 1-bit pixels, 8-bit pixels, 

3234 32-bit signed integer pixels, and 32-bit floating point pixels. 

3235 

3236 Pillow images can also be converted to arrays:: 

3237 

3238 from PIL import Image 

3239 import numpy as np 

3240 im = Image.open("hopper.jpg") 

3241 a = np.asarray(im) 

3242 

3243 When converting Pillow images to arrays however, only pixel values are 

3244 transferred. This means that P and PA mode images will lose their palette. 

3245 

3246 :param obj: Object with array interface 

3247 :param mode: Optional mode to use when reading ``obj``. Will be determined from 

3248 type if ``None``. 

3249 

3250 This will not be used to convert the data after reading, but will be used to 

3251 change how the data is read:: 

3252 

3253 from PIL import Image 

3254 import numpy as np 

3255 a = np.full((1, 1), 300) 

3256 im = Image.fromarray(a, mode="L") 

3257 im.getpixel((0, 0)) # 44 

3258 im = Image.fromarray(a, mode="RGB") 

3259 im.getpixel((0, 0)) # (44, 1, 0) 

3260 

3261 See: :ref:`concept-modes` for general information about modes. 

3262 :returns: An image object. 

3263 

3264 .. versionadded:: 1.1.6 

3265 """ 

3266 arr = obj.__array_interface__ 

3267 shape = arr["shape"] 

3268 ndim = len(shape) 

3269 strides = arr.get("strides", None) 

3270 if mode is None: 

3271 try: 

3272 typekey = (1, 1) + shape[2:], arr["typestr"] 

3273 except KeyError as e: 

3274 msg = "Cannot handle this data type" 

3275 raise TypeError(msg) from e 

3276 try: 

3277 mode, rawmode = _fromarray_typemap[typekey] 

3278 except KeyError as e: 

3279 typekey_shape, typestr = typekey 

3280 msg = f"Cannot handle this data type: {typekey_shape}, {typestr}" 

3281 raise TypeError(msg) from e 

3282 else: 

3283 rawmode = mode 

3284 if mode in ["1", "L", "I", "P", "F"]: 

3285 ndmax = 2 

3286 elif mode == "RGB": 

3287 ndmax = 3 

3288 else: 

3289 ndmax = 4 

3290 if ndim > ndmax: 

3291 msg = f"Too many dimensions: {ndim} > {ndmax}." 

3292 raise ValueError(msg) 

3293 

3294 size = 1 if ndim == 1 else shape[1], shape[0] 

3295 if strides is not None: 

3296 if hasattr(obj, "tobytes"): 

3297 obj = obj.tobytes() 

3298 elif hasattr(obj, "tostring"): 

3299 obj = obj.tostring() 

3300 else: 

3301 msg = "'strides' requires either tobytes() or tostring()" 

3302 raise ValueError(msg) 

3303 

3304 return frombuffer(mode, size, obj, "raw", rawmode, 0, 1) 

3305 

3306 

3307def fromqimage(im): 

3308 """Creates an image instance from a QImage image""" 

3309 from . import ImageQt 

3310 

3311 if not ImageQt.qt_is_installed: 

3312 msg = "Qt bindings are not installed" 

3313 raise ImportError(msg) 

3314 return ImageQt.fromqimage(im) 

3315 

3316 

3317def fromqpixmap(im): 

3318 """Creates an image instance from a QPixmap image""" 

3319 from . import ImageQt 

3320 

3321 if not ImageQt.qt_is_installed: 

3322 msg = "Qt bindings are not installed" 

3323 raise ImportError(msg) 

3324 return ImageQt.fromqpixmap(im) 

3325 

3326 

3327_fromarray_typemap = { 

3328 # (shape, typestr) => mode, rawmode 

3329 # first two members of shape are set to one 

3330 ((1, 1), "|b1"): ("1", "1;8"), 

3331 ((1, 1), "|u1"): ("L", "L"), 

3332 ((1, 1), "|i1"): ("I", "I;8"), 

3333 ((1, 1), "<u2"): ("I", "I;16"), 

3334 ((1, 1), ">u2"): ("I", "I;16B"), 

3335 ((1, 1), "<i2"): ("I", "I;16S"), 

3336 ((1, 1), ">i2"): ("I", "I;16BS"), 

3337 ((1, 1), "<u4"): ("I", "I;32"), 

3338 ((1, 1), ">u4"): ("I", "I;32B"), 

3339 ((1, 1), "<i4"): ("I", "I;32S"), 

3340 ((1, 1), ">i4"): ("I", "I;32BS"), 

3341 ((1, 1), "<f4"): ("F", "F;32F"), 

3342 ((1, 1), ">f4"): ("F", "F;32BF"), 

3343 ((1, 1), "<f8"): ("F", "F;64F"), 

3344 ((1, 1), ">f8"): ("F", "F;64BF"), 

3345 ((1, 1, 2), "|u1"): ("LA", "LA"), 

3346 ((1, 1, 3), "|u1"): ("RGB", "RGB"), 

3347 ((1, 1, 4), "|u1"): ("RGBA", "RGBA"), 

3348 # shortcuts: 

3349 ((1, 1), f"{_ENDIAN}i4"): ("I", "I"), 

3350 ((1, 1), f"{_ENDIAN}f4"): ("F", "F"), 

3351} 

3352 

3353 

3354def _decompression_bomb_check(size: tuple[int, int]) -> None: 

3355 if MAX_IMAGE_PIXELS is None: 

3356 return 

3357 

3358 pixels = max(1, size[0]) * max(1, size[1]) 

3359 

3360 if pixels > 2 * MAX_IMAGE_PIXELS: 

3361 msg = ( 

3362 f"Image size ({pixels} pixels) exceeds limit of {2 * MAX_IMAGE_PIXELS} " 

3363 "pixels, could be decompression bomb DOS attack." 

3364 ) 

3365 raise DecompressionBombError(msg) 

3366 

3367 if pixels > MAX_IMAGE_PIXELS: 

3368 warnings.warn( 

3369 f"Image size ({pixels} pixels) exceeds limit of {MAX_IMAGE_PIXELS} pixels, " 

3370 "could be decompression bomb DOS attack.", 

3371 DecompressionBombWarning, 

3372 ) 

3373 

3374 

3375def open( 

3376 fp: StrOrBytesPath | IO[bytes], 

3377 mode: Literal["r"] = "r", 

3378 formats: list[str] | tuple[str, ...] | None = None, 

3379) -> ImageFile.ImageFile: 

3380 """ 

3381 Opens and identifies the given image file. 

3382 

3383 This is a lazy operation; this function identifies the file, but 

3384 the file remains open and the actual image data is not read from 

3385 the file until you try to process the data (or call the 

3386 :py:meth:`~PIL.Image.Image.load` method). See 

3387 :py:func:`~PIL.Image.new`. See :ref:`file-handling`. 

3388 

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

3390 The file object must implement ``file.read``, 

3391 ``file.seek``, and ``file.tell`` methods, 

3392 and be opened in binary mode. The file object will also seek to zero 

3393 before reading. 

3394 :param mode: The mode. If given, this argument must be "r". 

3395 :param formats: A list or tuple of formats to attempt to load the file in. 

3396 This can be used to restrict the set of formats checked. 

3397 Pass ``None`` to try all supported formats. You can print the set of 

3398 available formats by running ``python3 -m PIL`` or using 

3399 the :py:func:`PIL.features.pilinfo` function. 

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

3401 :exception FileNotFoundError: If the file cannot be found. 

3402 :exception PIL.UnidentifiedImageError: If the image cannot be opened and 

3403 identified. 

3404 :exception ValueError: If the ``mode`` is not "r", or if a ``StringIO`` 

3405 instance is used for ``fp``. 

3406 :exception TypeError: If ``formats`` is not ``None``, a list or a tuple. 

3407 """ 

3408 

3409 if mode != "r": 

3410 msg = f"bad mode {repr(mode)}" # type: ignore[unreachable] 

3411 raise ValueError(msg) 

3412 elif isinstance(fp, io.StringIO): 

3413 msg = ( # type: ignore[unreachable] 

3414 "StringIO cannot be used to open an image. " 

3415 "Binary data must be used instead." 

3416 ) 

3417 raise ValueError(msg) 

3418 

3419 if formats is None: 

3420 formats = ID 

3421 elif not isinstance(formats, (list, tuple)): 

3422 msg = "formats must be a list or tuple" # type: ignore[unreachable] 

3423 raise TypeError(msg) 

3424 

3425 exclusive_fp = False 

3426 filename: str | bytes = "" 

3427 if is_path(fp): 

3428 filename = os.path.realpath(os.fspath(fp)) 

3429 

3430 if filename: 

3431 fp = builtins.open(filename, "rb") 

3432 exclusive_fp = True 

3433 else: 

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

3435 

3436 try: 

3437 fp.seek(0) 

3438 except (AttributeError, io.UnsupportedOperation): 

3439 fp = io.BytesIO(fp.read()) 

3440 exclusive_fp = True 

3441 

3442 prefix = fp.read(16) 

3443 

3444 preinit() 

3445 

3446 warning_messages: list[str] = [] 

3447 

3448 def _open_core( 

3449 fp: IO[bytes], 

3450 filename: str | bytes, 

3451 prefix: bytes, 

3452 formats: list[str] | tuple[str, ...], 

3453 ) -> ImageFile.ImageFile | None: 

3454 for i in formats: 

3455 i = i.upper() 

3456 if i not in OPEN: 

3457 init() 

3458 try: 

3459 factory, accept = OPEN[i] 

3460 result = not accept or accept(prefix) 

3461 if isinstance(result, str): 

3462 warning_messages.append(result) 

3463 elif result: 

3464 fp.seek(0) 

3465 im = factory(fp, filename) 

3466 _decompression_bomb_check(im.size) 

3467 return im 

3468 except (SyntaxError, IndexError, TypeError, struct.error) as e: 

3469 if WARN_POSSIBLE_FORMATS: 

3470 warning_messages.append(i + " opening failed. " + str(e)) 

3471 except BaseException: 

3472 if exclusive_fp: 

3473 fp.close() 

3474 raise 

3475 return None 

3476 

3477 im = _open_core(fp, filename, prefix, formats) 

3478 

3479 if im is None and formats is ID: 

3480 checked_formats = ID.copy() 

3481 if init(): 

3482 im = _open_core( 

3483 fp, 

3484 filename, 

3485 prefix, 

3486 tuple(format for format in formats if format not in checked_formats), 

3487 ) 

3488 

3489 if im: 

3490 im._exclusive_fp = exclusive_fp 

3491 return im 

3492 

3493 if exclusive_fp: 

3494 fp.close() 

3495 for message in warning_messages: 

3496 warnings.warn(message) 

3497 msg = "cannot identify image file %r" % (filename if filename else fp) 

3498 raise UnidentifiedImageError(msg) 

3499 

3500 

3501# 

3502# Image processing. 

3503 

3504 

3505def alpha_composite(im1: Image, im2: Image) -> Image: 

3506 """ 

3507 Alpha composite im2 over im1. 

3508 

3509 :param im1: The first image. Must have mode RGBA. 

3510 :param im2: The second image. Must have mode RGBA, and the same size as 

3511 the first image. 

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

3513 """ 

3514 

3515 im1.load() 

3516 im2.load() 

3517 return im1._new(core.alpha_composite(im1.im, im2.im)) 

3518 

3519 

3520def blend(im1: Image, im2: Image, alpha: float) -> Image: 

3521 """ 

3522 Creates a new image by interpolating between two input images, using 

3523 a constant alpha:: 

3524 

3525 out = image1 * (1.0 - alpha) + image2 * alpha 

3526 

3527 :param im1: The first image. 

3528 :param im2: The second image. Must have the same mode and size as 

3529 the first image. 

3530 :param alpha: The interpolation alpha factor. If alpha is 0.0, a 

3531 copy of the first image is returned. If alpha is 1.0, a copy of 

3532 the second image is returned. There are no restrictions on the 

3533 alpha value. If necessary, the result is clipped to fit into 

3534 the allowed output range. 

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

3536 """ 

3537 

3538 im1.load() 

3539 im2.load() 

3540 return im1._new(core.blend(im1.im, im2.im, alpha)) 

3541 

3542 

3543def composite(image1: Image, image2: Image, mask: Image) -> Image: 

3544 """ 

3545 Create composite image by blending images using a transparency mask. 

3546 

3547 :param image1: The first image. 

3548 :param image2: The second image. Must have the same mode and 

3549 size as the first image. 

3550 :param mask: A mask image. This image can have mode 

3551 "1", "L", or "RGBA", and must have the same size as the 

3552 other two images. 

3553 """ 

3554 

3555 image = image2.copy() 

3556 image.paste(image1, None, mask) 

3557 return image 

3558 

3559 

3560def eval(image, *args): 

3561 """ 

3562 Applies the function (which should take one argument) to each pixel 

3563 in the given image. If the image has more than one band, the same 

3564 function is applied to each band. Note that the function is 

3565 evaluated once for each possible pixel value, so you cannot use 

3566 random components or other generators. 

3567 

3568 :param image: The input image. 

3569 :param function: A function object, taking one integer argument. 

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

3571 """ 

3572 

3573 return image.point(args[0]) 

3574 

3575 

3576def merge(mode: str, bands: Sequence[Image]) -> Image: 

3577 """ 

3578 Merge a set of single band images into a new multiband image. 

3579 

3580 :param mode: The mode to use for the output image. See: 

3581 :ref:`concept-modes`. 

3582 :param bands: A sequence containing one single-band image for 

3583 each band in the output image. All bands must have the 

3584 same size. 

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

3586 """ 

3587 

3588 if getmodebands(mode) != len(bands) or "*" in mode: 

3589 msg = "wrong number of bands" 

3590 raise ValueError(msg) 

3591 for band in bands[1:]: 

3592 if band.mode != getmodetype(mode): 

3593 msg = "mode mismatch" 

3594 raise ValueError(msg) 

3595 if band.size != bands[0].size: 

3596 msg = "size mismatch" 

3597 raise ValueError(msg) 

3598 for band in bands: 

3599 band.load() 

3600 return bands[0]._new(core.merge(mode, *[b.im for b in bands])) 

3601 

3602 

3603# -------------------------------------------------------------------- 

3604# Plugin registry 

3605 

3606 

3607def register_open( 

3608 id: str, 

3609 factory: Callable[[IO[bytes], str | bytes], ImageFile.ImageFile], 

3610 accept: Callable[[bytes], bool | str] | None = None, 

3611) -> None: 

3612 """ 

3613 Register an image file plugin. This function should not be used 

3614 in application code. 

3615 

3616 :param id: An image format identifier. 

3617 :param factory: An image file factory method. 

3618 :param accept: An optional function that can be used to quickly 

3619 reject images having another format. 

3620 """ 

3621 id = id.upper() 

3622 if id not in ID: 

3623 ID.append(id) 

3624 OPEN[id] = factory, accept 

3625 

3626 

3627def register_mime(id: str, mimetype: str) -> None: 

3628 """ 

3629 Registers an image MIME type by populating ``Image.MIME``. This function 

3630 should not be used in application code. 

3631 

3632 ``Image.MIME`` provides a mapping from image format identifiers to mime 

3633 formats, but :py:meth:`~PIL.ImageFile.ImageFile.get_format_mimetype` can 

3634 provide a different result for specific images. 

3635 

3636 :param id: An image format identifier. 

3637 :param mimetype: The image MIME type for this format. 

3638 """ 

3639 MIME[id.upper()] = mimetype 

3640 

3641 

3642def register_save( 

3643 id: str, driver: Callable[[Image, IO[bytes], str | bytes], None] 

3644) -> None: 

3645 """ 

3646 Registers an image save function. This function should not be 

3647 used in application code. 

3648 

3649 :param id: An image format identifier. 

3650 :param driver: A function to save images in this format. 

3651 """ 

3652 SAVE[id.upper()] = driver 

3653 

3654 

3655def register_save_all( 

3656 id: str, driver: Callable[[Image, IO[bytes], str | bytes], None] 

3657) -> None: 

3658 """ 

3659 Registers an image function to save all the frames 

3660 of a multiframe format. This function should not be 

3661 used in application code. 

3662 

3663 :param id: An image format identifier. 

3664 :param driver: A function to save images in this format. 

3665 """ 

3666 SAVE_ALL[id.upper()] = driver 

3667 

3668 

3669def register_extension(id: str, extension: str) -> None: 

3670 """ 

3671 Registers an image extension. This function should not be 

3672 used in application code. 

3673 

3674 :param id: An image format identifier. 

3675 :param extension: An extension used for this format. 

3676 """ 

3677 EXTENSION[extension.lower()] = id.upper() 

3678 

3679 

3680def register_extensions(id: str, extensions: list[str]) -> None: 

3681 """ 

3682 Registers image extensions. This function should not be 

3683 used in application code. 

3684 

3685 :param id: An image format identifier. 

3686 :param extensions: A list of extensions used for this format. 

3687 """ 

3688 for extension in extensions: 

3689 register_extension(id, extension) 

3690 

3691 

3692def registered_extensions() -> dict[str, str]: 

3693 """ 

3694 Returns a dictionary containing all file extensions belonging 

3695 to registered plugins 

3696 """ 

3697 init() 

3698 return EXTENSION 

3699 

3700 

3701def register_decoder(name: str, decoder: type[ImageFile.PyDecoder]) -> None: 

3702 """ 

3703 Registers an image decoder. This function should not be 

3704 used in application code. 

3705 

3706 :param name: The name of the decoder 

3707 :param decoder: An ImageFile.PyDecoder object 

3708 

3709 .. versionadded:: 4.1.0 

3710 """ 

3711 DECODERS[name] = decoder 

3712 

3713 

3714def register_encoder(name: str, encoder: type[ImageFile.PyEncoder]) -> None: 

3715 """ 

3716 Registers an image encoder. This function should not be 

3717 used in application code. 

3718 

3719 :param name: The name of the encoder 

3720 :param encoder: An ImageFile.PyEncoder object 

3721 

3722 .. versionadded:: 4.1.0 

3723 """ 

3724 ENCODERS[name] = encoder 

3725 

3726 

3727# -------------------------------------------------------------------- 

3728# Simple display support. 

3729 

3730 

3731def _show(image: Image, **options: Any) -> None: 

3732 from . import ImageShow 

3733 

3734 ImageShow.show(image, **options) 

3735 

3736 

3737# -------------------------------------------------------------------- 

3738# Effects 

3739 

3740 

3741def effect_mandelbrot( 

3742 size: tuple[int, int], extent: tuple[float, float, float, float], quality: int 

3743) -> Image: 

3744 """ 

3745 Generate a Mandelbrot set covering the given extent. 

3746 

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

3748 (width, height). 

3749 :param extent: The extent to cover, as a 4-tuple: 

3750 (x0, y0, x1, y1). 

3751 :param quality: Quality. 

3752 """ 

3753 return Image()._new(core.effect_mandelbrot(size, extent, quality)) 

3754 

3755 

3756def effect_noise(size: tuple[int, int], sigma: float) -> Image: 

3757 """ 

3758 Generate Gaussian noise centered around 128. 

3759 

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

3761 (width, height). 

3762 :param sigma: Standard deviation of noise. 

3763 """ 

3764 return Image()._new(core.effect_noise(size, sigma)) 

3765 

3766 

3767def linear_gradient(mode: str) -> Image: 

3768 """ 

3769 Generate 256x256 linear gradient from black to white, top to bottom. 

3770 

3771 :param mode: Input mode. 

3772 """ 

3773 return Image()._new(core.linear_gradient(mode)) 

3774 

3775 

3776def radial_gradient(mode: str) -> Image: 

3777 """ 

3778 Generate 256x256 radial gradient from black to white, centre to edge. 

3779 

3780 :param mode: Input mode. 

3781 """ 

3782 return Image()._new(core.radial_gradient(mode)) 

3783 

3784 

3785# -------------------------------------------------------------------- 

3786# Resources 

3787 

3788 

3789def _apply_env_variables(env: dict[str, str] | None = None) -> None: 

3790 env_dict = env if env is not None else os.environ 

3791 

3792 for var_name, setter in [ 

3793 ("PILLOW_ALIGNMENT", core.set_alignment), 

3794 ("PILLOW_BLOCK_SIZE", core.set_block_size), 

3795 ("PILLOW_BLOCKS_MAX", core.set_blocks_max), 

3796 ]: 

3797 if var_name not in env_dict: 

3798 continue 

3799 

3800 var = env_dict[var_name].lower() 

3801 

3802 units = 1 

3803 for postfix, mul in [("k", 1024), ("m", 1024 * 1024)]: 

3804 if var.endswith(postfix): 

3805 units = mul 

3806 var = var[: -len(postfix)] 

3807 

3808 try: 

3809 var_int = int(var) * units 

3810 except ValueError: 

3811 warnings.warn(f"{var_name} is not int") 

3812 continue 

3813 

3814 try: 

3815 setter(var_int) 

3816 except ValueError as e: 

3817 warnings.warn(f"{var_name}: {e}") 

3818 

3819 

3820_apply_env_variables() 

3821atexit.register(core.clear_cache) 

3822 

3823 

3824if TYPE_CHECKING: 

3825 _ExifBase = MutableMapping[int, Any] 

3826else: 

3827 _ExifBase = MutableMapping 

3828 

3829 

3830class Exif(_ExifBase): 

3831 """ 

3832 This class provides read and write access to EXIF image data:: 

3833 

3834 from PIL import Image 

3835 im = Image.open("exif.png") 

3836 exif = im.getexif() # Returns an instance of this class 

3837 

3838 Information can be read and written, iterated over or deleted:: 

3839 

3840 print(exif[274]) # 1 

3841 exif[274] = 2 

3842 for k, v in exif.items(): 

3843 print("Tag", k, "Value", v) # Tag 274 Value 2 

3844 del exif[274] 

3845 

3846 To access information beyond IFD0, :py:meth:`~PIL.Image.Exif.get_ifd` 

3847 returns a dictionary:: 

3848 

3849 from PIL import ExifTags 

3850 im = Image.open("exif_gps.jpg") 

3851 exif = im.getexif() 

3852 gps_ifd = exif.get_ifd(ExifTags.IFD.GPSInfo) 

3853 print(gps_ifd) 

3854 

3855 Other IFDs include ``ExifTags.IFD.Exif``, ``ExifTags.IFD.Makernote``, 

3856 ``ExifTags.IFD.Interop`` and ``ExifTags.IFD.IFD1``. 

3857 

3858 :py:mod:`~PIL.ExifTags` also has enum classes to provide names for data:: 

3859 

3860 print(exif[ExifTags.Base.Software]) # PIL 

3861 print(gps_ifd[ExifTags.GPS.GPSDateStamp]) # 1999:99:99 99:99:99 

3862 """ 

3863 

3864 endian = None 

3865 bigtiff = False 

3866 _loaded = False 

3867 

3868 def __init__(self): 

3869 self._data = {} 

3870 self._hidden_data = {} 

3871 self._ifds = {} 

3872 self._info = None 

3873 self._loaded_exif = None 

3874 

3875 def _fixup(self, value): 

3876 try: 

3877 if len(value) == 1 and isinstance(value, tuple): 

3878 return value[0] 

3879 except Exception: 

3880 pass 

3881 return value 

3882 

3883 def _fixup_dict(self, src_dict): 

3884 # Helper function 

3885 # returns a dict with any single item tuples/lists as individual values 

3886 return {k: self._fixup(v) for k, v in src_dict.items()} 

3887 

3888 def _get_ifd_dict(self, offset, group=None): 

3889 try: 

3890 # an offset pointer to the location of the nested embedded IFD. 

3891 # It should be a long, but may be corrupted. 

3892 self.fp.seek(offset) 

3893 except (KeyError, TypeError): 

3894 pass 

3895 else: 

3896 from . import TiffImagePlugin 

3897 

3898 info = TiffImagePlugin.ImageFileDirectory_v2(self.head, group=group) 

3899 info.load(self.fp) 

3900 return self._fixup_dict(info) 

3901 

3902 def _get_head(self): 

3903 version = b"\x2B" if self.bigtiff else b"\x2A" 

3904 if self.endian == "<": 

3905 head = b"II" + version + b"\x00" + o32le(8) 

3906 else: 

3907 head = b"MM\x00" + version + o32be(8) 

3908 if self.bigtiff: 

3909 head += o32le(8) if self.endian == "<" else o32be(8) 

3910 head += b"\x00\x00\x00\x00" 

3911 return head 

3912 

3913 def load(self, data): 

3914 # Extract EXIF information. This is highly experimental, 

3915 # and is likely to be replaced with something better in a future 

3916 # version. 

3917 

3918 # The EXIF record consists of a TIFF file embedded in a JPEG 

3919 # application marker (!). 

3920 if data == self._loaded_exif: 

3921 return 

3922 self._loaded_exif = data 

3923 self._data.clear() 

3924 self._hidden_data.clear() 

3925 self._ifds.clear() 

3926 if data and data.startswith(b"Exif\x00\x00"): 

3927 data = data[6:] 

3928 if not data: 

3929 self._info = None 

3930 return 

3931 

3932 self.fp = io.BytesIO(data) 

3933 self.head = self.fp.read(8) 

3934 # process dictionary 

3935 from . import TiffImagePlugin 

3936 

3937 self._info = TiffImagePlugin.ImageFileDirectory_v2(self.head) 

3938 self.endian = self._info._endian 

3939 self.fp.seek(self._info.next) 

3940 self._info.load(self.fp) 

3941 

3942 def load_from_fp(self, fp, offset=None): 

3943 self._loaded_exif = None 

3944 self._data.clear() 

3945 self._hidden_data.clear() 

3946 self._ifds.clear() 

3947 

3948 # process dictionary 

3949 from . import TiffImagePlugin 

3950 

3951 self.fp = fp 

3952 if offset is not None: 

3953 self.head = self._get_head() 

3954 else: 

3955 self.head = self.fp.read(8) 

3956 self._info = TiffImagePlugin.ImageFileDirectory_v2(self.head) 

3957 if self.endian is None: 

3958 self.endian = self._info._endian 

3959 if offset is None: 

3960 offset = self._info.next 

3961 self.fp.tell() 

3962 self.fp.seek(offset) 

3963 self._info.load(self.fp) 

3964 

3965 def _get_merged_dict(self): 

3966 merged_dict = dict(self) 

3967 

3968 # get EXIF extension 

3969 if ExifTags.IFD.Exif in self: 

3970 ifd = self._get_ifd_dict(self[ExifTags.IFD.Exif], ExifTags.IFD.Exif) 

3971 if ifd: 

3972 merged_dict.update(ifd) 

3973 

3974 # GPS 

3975 if ExifTags.IFD.GPSInfo in self: 

3976 merged_dict[ExifTags.IFD.GPSInfo] = self._get_ifd_dict( 

3977 self[ExifTags.IFD.GPSInfo], ExifTags.IFD.GPSInfo 

3978 ) 

3979 

3980 return merged_dict 

3981 

3982 def tobytes(self, offset: int = 8) -> bytes: 

3983 from . import TiffImagePlugin 

3984 

3985 head = self._get_head() 

3986 ifd = TiffImagePlugin.ImageFileDirectory_v2(ifh=head) 

3987 for tag, value in self.items(): 

3988 if tag in [ 

3989 ExifTags.IFD.Exif, 

3990 ExifTags.IFD.GPSInfo, 

3991 ] and not isinstance(value, dict): 

3992 value = self.get_ifd(tag) 

3993 if ( 

3994 tag == ExifTags.IFD.Exif 

3995 and ExifTags.IFD.Interop in value 

3996 and not isinstance(value[ExifTags.IFD.Interop], dict) 

3997 ): 

3998 value = value.copy() 

3999 value[ExifTags.IFD.Interop] = self.get_ifd(ExifTags.IFD.Interop) 

4000 ifd[tag] = value 

4001 return b"Exif\x00\x00" + head + ifd.tobytes(offset) 

4002 

4003 def get_ifd(self, tag): 

4004 if tag not in self._ifds: 

4005 if tag == ExifTags.IFD.IFD1: 

4006 if self._info is not None and self._info.next != 0: 

4007 self._ifds[tag] = self._get_ifd_dict(self._info.next) 

4008 elif tag in [ExifTags.IFD.Exif, ExifTags.IFD.GPSInfo]: 

4009 offset = self._hidden_data.get(tag, self.get(tag)) 

4010 if offset is not None: 

4011 self._ifds[tag] = self._get_ifd_dict(offset, tag) 

4012 elif tag in [ExifTags.IFD.Interop, ExifTags.IFD.Makernote]: 

4013 if ExifTags.IFD.Exif not in self._ifds: 

4014 self.get_ifd(ExifTags.IFD.Exif) 

4015 tag_data = self._ifds[ExifTags.IFD.Exif][tag] 

4016 if tag == ExifTags.IFD.Makernote: 

4017 from .TiffImagePlugin import ImageFileDirectory_v2 

4018 

4019 if tag_data[:8] == b"FUJIFILM": 

4020 ifd_offset = i32le(tag_data, 8) 

4021 ifd_data = tag_data[ifd_offset:] 

4022 

4023 makernote = {} 

4024 for i in range(0, struct.unpack("<H", ifd_data[:2])[0]): 

4025 ifd_tag, typ, count, data = struct.unpack( 

4026 "<HHL4s", ifd_data[i * 12 + 2 : (i + 1) * 12 + 2] 

4027 ) 

4028 try: 

4029 ( 

4030 unit_size, 

4031 handler, 

4032 ) = ImageFileDirectory_v2._load_dispatch[typ] 

4033 except KeyError: 

4034 continue 

4035 size = count * unit_size 

4036 if size > 4: 

4037 (offset,) = struct.unpack("<L", data) 

4038 data = ifd_data[offset - 12 : offset + size - 12] 

4039 else: 

4040 data = data[:size] 

4041 

4042 if len(data) != size: 

4043 warnings.warn( 

4044 "Possibly corrupt EXIF MakerNote data. " 

4045 f"Expecting to read {size} bytes but only got " 

4046 f"{len(data)}. Skipping tag {ifd_tag}" 

4047 ) 

4048 continue 

4049 

4050 if not data: 

4051 continue 

4052 

4053 makernote[ifd_tag] = handler( 

4054 ImageFileDirectory_v2(), data, False 

4055 ) 

4056 self._ifds[tag] = dict(self._fixup_dict(makernote)) 

4057 elif self.get(0x010F) == "Nintendo": 

4058 makernote = {} 

4059 for i in range(0, struct.unpack(">H", tag_data[:2])[0]): 

4060 ifd_tag, typ, count, data = struct.unpack( 

4061 ">HHL4s", tag_data[i * 12 + 2 : (i + 1) * 12 + 2] 

4062 ) 

4063 if ifd_tag == 0x1101: 

4064 # CameraInfo 

4065 (offset,) = struct.unpack(">L", data) 

4066 self.fp.seek(offset) 

4067 

4068 camerainfo = {"ModelID": self.fp.read(4)} 

4069 

4070 self.fp.read(4) 

4071 # Seconds since 2000 

4072 camerainfo["TimeStamp"] = i32le(self.fp.read(12)) 

4073 

4074 self.fp.read(4) 

4075 camerainfo["InternalSerialNumber"] = self.fp.read(4) 

4076 

4077 self.fp.read(12) 

4078 parallax = self.fp.read(4) 

4079 handler = ImageFileDirectory_v2._load_dispatch[ 

4080 TiffTags.FLOAT 

4081 ][1] 

4082 camerainfo["Parallax"] = handler( 

4083 ImageFileDirectory_v2(), parallax, False 

4084 ) 

4085 

4086 self.fp.read(4) 

4087 camerainfo["Category"] = self.fp.read(2) 

4088 

4089 makernote = {0x1101: dict(self._fixup_dict(camerainfo))} 

4090 self._ifds[tag] = makernote 

4091 else: 

4092 # Interop 

4093 self._ifds[tag] = self._get_ifd_dict(tag_data, tag) 

4094 ifd = self._ifds.get(tag, {}) 

4095 if tag == ExifTags.IFD.Exif and self._hidden_data: 

4096 ifd = { 

4097 k: v 

4098 for (k, v) in ifd.items() 

4099 if k not in (ExifTags.IFD.Interop, ExifTags.IFD.Makernote) 

4100 } 

4101 return ifd 

4102 

4103 def hide_offsets(self) -> None: 

4104 for tag in (ExifTags.IFD.Exif, ExifTags.IFD.GPSInfo): 

4105 if tag in self: 

4106 self._hidden_data[tag] = self[tag] 

4107 del self[tag] 

4108 

4109 def __str__(self) -> str: 

4110 if self._info is not None: 

4111 # Load all keys into self._data 

4112 for tag in self._info: 

4113 self[tag] 

4114 

4115 return str(self._data) 

4116 

4117 def __len__(self) -> int: 

4118 keys = set(self._data) 

4119 if self._info is not None: 

4120 keys.update(self._info) 

4121 return len(keys) 

4122 

4123 def __getitem__(self, tag): 

4124 if self._info is not None and tag not in self._data and tag in self._info: 

4125 self._data[tag] = self._fixup(self._info[tag]) 

4126 del self._info[tag] 

4127 return self._data[tag] 

4128 

4129 def __contains__(self, tag) -> bool: 

4130 return tag in self._data or (self._info is not None and tag in self._info) 

4131 

4132 def __setitem__(self, tag, value) -> None: 

4133 if self._info is not None and tag in self._info: 

4134 del self._info[tag] 

4135 self._data[tag] = value 

4136 

4137 def __delitem__(self, tag: int) -> None: 

4138 if self._info is not None and tag in self._info: 

4139 del self._info[tag] 

4140 else: 

4141 del self._data[tag] 

4142 

4143 def __iter__(self): 

4144 keys = set(self._data) 

4145 if self._info is not None: 

4146 keys.update(self._info) 

4147 return iter(keys)