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)