Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/PIL/Image.py: 17%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
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#
27from __future__ import annotations
29import abc
30import atexit
31import builtins
32import io
33import logging
34import math
35import os
36import re
37import struct
38import sys
39import tempfile
40import warnings
41from collections.abc import Callable, Iterator, MutableMapping, Sequence
42from enum import IntEnum
43from types import ModuleType
44from typing import IO, Any, Literal, Protocol, cast
46# VERSION was removed in Pillow 6.0.0.
47# PILLOW_VERSION was removed in Pillow 9.0.0.
48# Use __version__ instead.
49from . import (
50 ExifTags,
51 ImageMode,
52 TiffTags,
53 UnidentifiedImageError,
54 __version__,
55 _plugins,
56)
57from ._binary import i32le, o32be, o32le
58from ._deprecate import deprecate
59from ._util import DeferredError, is_path
61ElementTree: ModuleType | None
62try:
63 from defusedxml import ElementTree
64except ImportError:
65 ElementTree = None
67logger = logging.getLogger(__name__)
70class DecompressionBombWarning(RuntimeWarning):
71 pass
74class DecompressionBombError(Exception):
75 pass
78WARN_POSSIBLE_FORMATS: bool = False
80# Limit to around a quarter gigabyte for a 24-bit (3 bpp) image
81MAX_IMAGE_PIXELS: int | None = int(1024 * 1024 * 1024 // 4 // 3)
84try:
85 # If the _imaging C module is not present, Pillow will not load.
86 # Note that other modules should not refer to _imaging directly;
87 # import Image and use the Image.core variable instead.
88 # Also note that Image.core is not a publicly documented interface,
89 # and should be considered private and subject to change.
90 from . import _imaging as core
92 if __version__ != getattr(core, "PILLOW_VERSION", None):
93 msg = (
94 "The _imaging extension was built for another version of Pillow or PIL:\n"
95 f"Core version: {getattr(core, 'PILLOW_VERSION', None)}\n"
96 f"Pillow version: {__version__}"
97 )
98 raise ImportError(msg)
100except ImportError as v:
101 core = DeferredError.new(ImportError("The _imaging C module is not installed."))
102 # Explanations for ways that we know we might have an import error
103 if str(v).startswith("Module use of python"):
104 # The _imaging C module is present, but not compiled for
105 # the right version (windows only). Print a warning, if
106 # possible.
107 warnings.warn(
108 "The _imaging extension was built for another version of Python.",
109 RuntimeWarning,
110 )
111 elif str(v).startswith("The _imaging extension"):
112 warnings.warn(str(v), RuntimeWarning)
113 # Fail here anyway. Don't let people run with a mostly broken Pillow.
114 # see docs/porting.rst
115 raise
118def isImageType(t: Any) -> TypeGuard[Image]:
119 """
120 Checks if an object is an image object.
122 .. warning::
124 This function is for internal use only.
126 :param t: object to check if it's an image
127 :returns: True if the object is an image
128 """
129 deprecate("Image.isImageType(im)", 12, "isinstance(im, Image.Image)")
130 return hasattr(t, "im")
133#
134# Constants
137# transpose
138class Transpose(IntEnum):
139 FLIP_LEFT_RIGHT = 0
140 FLIP_TOP_BOTTOM = 1
141 ROTATE_90 = 2
142 ROTATE_180 = 3
143 ROTATE_270 = 4
144 TRANSPOSE = 5
145 TRANSVERSE = 6
148# transforms (also defined in Imaging.h)
149class Transform(IntEnum):
150 AFFINE = 0
151 EXTENT = 1
152 PERSPECTIVE = 2
153 QUAD = 3
154 MESH = 4
157# resampling filters (also defined in Imaging.h)
158class Resampling(IntEnum):
159 NEAREST = 0
160 BOX = 4
161 BILINEAR = 2
162 HAMMING = 5
163 BICUBIC = 3
164 LANCZOS = 1
167_filters_support = {
168 Resampling.BOX: 0.5,
169 Resampling.BILINEAR: 1.0,
170 Resampling.HAMMING: 1.0,
171 Resampling.BICUBIC: 2.0,
172 Resampling.LANCZOS: 3.0,
173}
176# dithers
177class Dither(IntEnum):
178 NONE = 0
179 ORDERED = 1 # Not yet implemented
180 RASTERIZE = 2 # Not yet implemented
181 FLOYDSTEINBERG = 3 # default
184# palettes/quantizers
185class Palette(IntEnum):
186 WEB = 0
187 ADAPTIVE = 1
190class Quantize(IntEnum):
191 MEDIANCUT = 0
192 MAXCOVERAGE = 1
193 FASTOCTREE = 2
194 LIBIMAGEQUANT = 3
197module = sys.modules[__name__]
198for enum in (Transpose, Transform, Resampling, Dither, Palette, Quantize):
199 for item in enum:
200 setattr(module, item.name, item.value)
203if hasattr(core, "DEFAULT_STRATEGY"):
204 DEFAULT_STRATEGY = core.DEFAULT_STRATEGY
205 FILTERED = core.FILTERED
206 HUFFMAN_ONLY = core.HUFFMAN_ONLY
207 RLE = core.RLE
208 FIXED = core.FIXED
211# --------------------------------------------------------------------
212# Registries
214TYPE_CHECKING = False
215if TYPE_CHECKING:
216 import mmap
217 from xml.etree.ElementTree import Element
219 from IPython.lib.pretty import PrettyPrinter
221 from . import ImageFile, ImageFilter, ImagePalette, ImageQt, TiffImagePlugin
222 from ._typing import CapsuleType, NumpyArray, StrOrBytesPath, TypeGuard
223ID: list[str] = []
224OPEN: dict[
225 str,
226 tuple[
227 Callable[[IO[bytes], str | bytes], ImageFile.ImageFile],
228 Callable[[bytes], bool | str] | None,
229 ],
230] = {}
231MIME: dict[str, str] = {}
232SAVE: dict[str, Callable[[Image, IO[bytes], str | bytes], None]] = {}
233SAVE_ALL: dict[str, Callable[[Image, IO[bytes], str | bytes], None]] = {}
234EXTENSION: dict[str, str] = {}
235DECODERS: dict[str, type[ImageFile.PyDecoder]] = {}
236ENCODERS: dict[str, type[ImageFile.PyEncoder]] = {}
238# --------------------------------------------------------------------
239# Modes
241_ENDIAN = "<" if sys.byteorder == "little" else ">"
244def _conv_type_shape(im: Image) -> tuple[tuple[int, ...], str]:
245 m = ImageMode.getmode(im.mode)
246 shape: tuple[int, ...] = (im.height, im.width)
247 extra = len(m.bands)
248 if extra != 1:
249 shape += (extra,)
250 return shape, m.typestr
253MODES = [
254 "1",
255 "CMYK",
256 "F",
257 "HSV",
258 "I",
259 "I;16",
260 "I;16B",
261 "I;16L",
262 "I;16N",
263 "L",
264 "LA",
265 "La",
266 "LAB",
267 "P",
268 "PA",
269 "RGB",
270 "RGBA",
271 "RGBa",
272 "RGBX",
273 "YCbCr",
274]
276# raw modes that may be memory mapped. NOTE: if you change this, you
277# may have to modify the stride calculation in map.c too!
278_MAPMODES = ("L", "P", "RGBX", "RGBA", "CMYK", "I;16", "I;16L", "I;16B")
281def getmodebase(mode: str) -> str:
282 """
283 Gets the "base" mode for given mode. This function returns "L" for
284 images that contain grayscale data, and "RGB" for images that
285 contain color data.
287 :param mode: Input mode.
288 :returns: "L" or "RGB".
289 :exception KeyError: If the input mode was not a standard mode.
290 """
291 return ImageMode.getmode(mode).basemode
294def getmodetype(mode: str) -> str:
295 """
296 Gets the storage type mode. Given a mode, this function returns a
297 single-layer mode suitable for storing individual bands.
299 :param mode: Input mode.
300 :returns: "L", "I", or "F".
301 :exception KeyError: If the input mode was not a standard mode.
302 """
303 return ImageMode.getmode(mode).basetype
306def getmodebandnames(mode: str) -> tuple[str, ...]:
307 """
308 Gets a list of individual band names. Given a mode, this function returns
309 a tuple containing the names of individual bands (use
310 :py:method:`~PIL.Image.getmodetype` to get the mode used to store each
311 individual band.
313 :param mode: Input mode.
314 :returns: A tuple containing band names. The length of the tuple
315 gives the number of bands in an image of the given mode.
316 :exception KeyError: If the input mode was not a standard mode.
317 """
318 return ImageMode.getmode(mode).bands
321def getmodebands(mode: str) -> int:
322 """
323 Gets the number of individual bands for this mode.
325 :param mode: Input mode.
326 :returns: The number of bands in this mode.
327 :exception KeyError: If the input mode was not a standard mode.
328 """
329 return len(ImageMode.getmode(mode).bands)
332# --------------------------------------------------------------------
333# Helpers
335_initialized = 0
338def preinit() -> None:
339 """
340 Explicitly loads BMP, GIF, JPEG, PPM and PPM file format drivers.
342 It is called when opening or saving images.
343 """
345 global _initialized
346 if _initialized >= 1:
347 return
349 try:
350 from . import BmpImagePlugin
352 assert BmpImagePlugin
353 except ImportError:
354 pass
355 try:
356 from . import GifImagePlugin
358 assert GifImagePlugin
359 except ImportError:
360 pass
361 try:
362 from . import JpegImagePlugin
364 assert JpegImagePlugin
365 except ImportError:
366 pass
367 try:
368 from . import PpmImagePlugin
370 assert PpmImagePlugin
371 except ImportError:
372 pass
373 try:
374 from . import PngImagePlugin
376 assert PngImagePlugin
377 except ImportError:
378 pass
380 _initialized = 1
383def init() -> bool:
384 """
385 Explicitly initializes the Python Imaging Library. This function
386 loads all available file format drivers.
388 It is called when opening or saving images if :py:meth:`~preinit()` is
389 insufficient, and by :py:meth:`~PIL.features.pilinfo`.
390 """
392 global _initialized
393 if _initialized >= 2:
394 return False
396 parent_name = __name__.rpartition(".")[0]
397 for plugin in _plugins:
398 try:
399 logger.debug("Importing %s", plugin)
400 __import__(f"{parent_name}.{plugin}", globals(), locals(), [])
401 except ImportError as e:
402 logger.debug("Image: failed to import %s: %s", plugin, e)
404 if OPEN or SAVE:
405 _initialized = 2
406 return True
407 return False
410# --------------------------------------------------------------------
411# Codec factories (used by tobytes/frombytes and ImageFile.load)
414def _getdecoder(
415 mode: str, decoder_name: str, args: Any, extra: tuple[Any, ...] = ()
416) -> core.ImagingDecoder | ImageFile.PyDecoder:
417 # tweak arguments
418 if args is None:
419 args = ()
420 elif not isinstance(args, tuple):
421 args = (args,)
423 try:
424 decoder = DECODERS[decoder_name]
425 except KeyError:
426 pass
427 else:
428 return decoder(mode, *args + extra)
430 try:
431 # get decoder
432 decoder = getattr(core, f"{decoder_name}_decoder")
433 except AttributeError as e:
434 msg = f"decoder {decoder_name} not available"
435 raise OSError(msg) from e
436 return decoder(mode, *args + extra)
439def _getencoder(
440 mode: str, encoder_name: str, args: Any, extra: tuple[Any, ...] = ()
441) -> core.ImagingEncoder | ImageFile.PyEncoder:
442 # tweak arguments
443 if args is None:
444 args = ()
445 elif not isinstance(args, tuple):
446 args = (args,)
448 try:
449 encoder = ENCODERS[encoder_name]
450 except KeyError:
451 pass
452 else:
453 return encoder(mode, *args + extra)
455 try:
456 # get encoder
457 encoder = getattr(core, f"{encoder_name}_encoder")
458 except AttributeError as e:
459 msg = f"encoder {encoder_name} not available"
460 raise OSError(msg) from e
461 return encoder(mode, *args + extra)
464# --------------------------------------------------------------------
465# Simple expression analyzer
468class ImagePointTransform:
469 """
470 Used with :py:meth:`~PIL.Image.Image.point` for single band images with more than
471 8 bits, this represents an affine transformation, where the value is multiplied by
472 ``scale`` and ``offset`` is added.
473 """
475 def __init__(self, scale: float, offset: float) -> None:
476 self.scale = scale
477 self.offset = offset
479 def __neg__(self) -> ImagePointTransform:
480 return ImagePointTransform(-self.scale, -self.offset)
482 def __add__(self, other: ImagePointTransform | float) -> ImagePointTransform:
483 if isinstance(other, ImagePointTransform):
484 return ImagePointTransform(
485 self.scale + other.scale, self.offset + other.offset
486 )
487 return ImagePointTransform(self.scale, self.offset + other)
489 __radd__ = __add__
491 def __sub__(self, other: ImagePointTransform | float) -> ImagePointTransform:
492 return self + -other
494 def __rsub__(self, other: ImagePointTransform | float) -> ImagePointTransform:
495 return other + -self
497 def __mul__(self, other: ImagePointTransform | float) -> ImagePointTransform:
498 if isinstance(other, ImagePointTransform):
499 return NotImplemented
500 return ImagePointTransform(self.scale * other, self.offset * other)
502 __rmul__ = __mul__
504 def __truediv__(self, other: ImagePointTransform | float) -> ImagePointTransform:
505 if isinstance(other, ImagePointTransform):
506 return NotImplemented
507 return ImagePointTransform(self.scale / other, self.offset / other)
510def _getscaleoffset(
511 expr: Callable[[ImagePointTransform], ImagePointTransform | float],
512) -> tuple[float, float]:
513 a = expr(ImagePointTransform(1, 0))
514 return (a.scale, a.offset) if isinstance(a, ImagePointTransform) else (0, a)
517# --------------------------------------------------------------------
518# Implementation wrapper
521class SupportsGetData(Protocol):
522 def getdata(
523 self,
524 ) -> tuple[Transform, Sequence[int]]: ...
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.
534 * :py:func:`~PIL.Image.open`
535 * :py:func:`~PIL.Image.new`
536 * :py:func:`~PIL.Image.frombytes`
537 """
539 format: str | None = None
540 format_description: str | None = None
541 _close_exclusive_fp_after_loading = True
543 def __init__(self) -> None:
544 # FIXME: take "new" parameters / other image?
545 self._im: core.ImagingCore | DeferredError | None = None
546 self._mode = ""
547 self._size = (0, 0)
548 self.palette: ImagePalette.ImagePalette | None = None
549 self.info: dict[str | tuple[int, int], Any] = {}
550 self.readonly = 0
551 self._exif: Exif | None = None
553 @property
554 def im(self) -> core.ImagingCore:
555 if isinstance(self._im, DeferredError):
556 raise self._im.ex
557 assert self._im is not None
558 return self._im
560 @im.setter
561 def im(self, im: core.ImagingCore) -> None:
562 self._im = im
564 @property
565 def width(self) -> int:
566 return self.size[0]
568 @property
569 def height(self) -> int:
570 return self.size[1]
572 @property
573 def size(self) -> tuple[int, int]:
574 return self._size
576 @property
577 def mode(self) -> str:
578 return self._mode
580 @property
581 def readonly(self) -> int:
582 return (self._im and self._im.readonly) or self._readonly
584 @readonly.setter
585 def readonly(self, readonly: int) -> None:
586 self._readonly = readonly
588 def _new(self, im: core.ImagingCore) -> Image:
589 new = Image()
590 new.im = im
591 new._mode = im.mode
592 new._size = im.size
593 if im.mode in ("P", "PA"):
594 if self.palette:
595 new.palette = self.palette.copy()
596 else:
597 from . import ImagePalette
599 new.palette = ImagePalette.ImagePalette()
600 new.info = self.info.copy()
601 return new
603 # Context manager support
604 def __enter__(self):
605 return self
607 def __exit__(self, *args):
608 from . import ImageFile
610 if isinstance(self, ImageFile.ImageFile):
611 if getattr(self, "_exclusive_fp", False):
612 self._close_fp()
613 self.fp = None
615 def close(self) -> None:
616 """
617 This operation will destroy the image core and release its memory.
618 The image data will be unusable afterward.
620 This function is required to close images that have multiple frames or
621 have not had their file read and closed by the
622 :py:meth:`~PIL.Image.Image.load` method. See :ref:`file-handling` for
623 more information.
624 """
625 if getattr(self, "map", None):
626 if sys.platform == "win32" and hasattr(sys, "pypy_version_info"):
627 self.map.close()
628 self.map: mmap.mmap | None = None
630 # Instead of simply setting to None, we're setting up a
631 # deferred error that will better explain that the core image
632 # object is gone.
633 self._im = DeferredError(ValueError("Operation on closed image"))
635 def _copy(self) -> None:
636 self.load()
637 self.im = self.im.copy()
638 self.readonly = 0
640 def _ensure_mutable(self) -> None:
641 if self.readonly:
642 self._copy()
643 else:
644 self.load()
646 def _dump(
647 self, file: str | None = None, format: str | None = None, **options: Any
648 ) -> str:
649 suffix = ""
650 if format:
651 suffix = f".{format}"
653 if not file:
654 f, filename = tempfile.mkstemp(suffix)
655 os.close(f)
656 else:
657 filename = file
658 if not filename.endswith(suffix):
659 filename = filename + suffix
661 self.load()
663 if not format or format == "PPM":
664 self.im.save_ppm(filename)
665 else:
666 self.save(filename, format, **options)
668 return filename
670 def __eq__(self, other: object) -> bool:
671 if self.__class__ is not other.__class__:
672 return False
673 assert isinstance(other, Image)
674 return (
675 self.mode == other.mode
676 and self.size == other.size
677 and self.info == other.info
678 and self.getpalette() == other.getpalette()
679 and self.tobytes() == other.tobytes()
680 )
682 def __repr__(self) -> str:
683 return (
684 f"<{self.__class__.__module__}.{self.__class__.__name__} "
685 f"image mode={self.mode} size={self.size[0]}x{self.size[1]} "
686 f"at 0x{id(self):X}>"
687 )
689 def _repr_pretty_(self, p: PrettyPrinter, cycle: bool) -> None:
690 """IPython plain text display support"""
692 # Same as __repr__ but without unpredictable id(self),
693 # to keep Jupyter notebook `text/plain` output stable.
694 p.text(
695 f"<{self.__class__.__module__}.{self.__class__.__name__} "
696 f"image mode={self.mode} size={self.size[0]}x{self.size[1]}>"
697 )
699 def _repr_image(self, image_format: str, **kwargs: Any) -> bytes | None:
700 """Helper function for iPython display hook.
702 :param image_format: Image format.
703 :returns: image as bytes, saved into the given format.
704 """
705 b = io.BytesIO()
706 try:
707 self.save(b, image_format, **kwargs)
708 except Exception:
709 return None
710 return b.getvalue()
712 def _repr_png_(self) -> bytes | None:
713 """iPython display hook support for PNG format.
715 :returns: PNG version of the image as bytes
716 """
717 return self._repr_image("PNG", compress_level=1)
719 def _repr_jpeg_(self) -> bytes | None:
720 """iPython display hook support for JPEG format.
722 :returns: JPEG version of the image as bytes
723 """
724 return self._repr_image("JPEG")
726 @property
727 def __array_interface__(self) -> dict[str, str | bytes | int | tuple[int, ...]]:
728 # numpy array interface support
729 new: dict[str, str | bytes | int | tuple[int, ...]] = {"version": 3}
730 if self.mode == "1":
731 # Binary images need to be extended from bits to bytes
732 # See: https://github.com/python-pillow/Pillow/issues/350
733 new["data"] = self.tobytes("raw", "L")
734 else:
735 new["data"] = self.tobytes()
736 new["shape"], new["typestr"] = _conv_type_shape(self)
737 return new
739 def __arrow_c_schema__(self) -> object:
740 self.load()
741 return self.im.__arrow_c_schema__()
743 def __arrow_c_array__(
744 self, requested_schema: object | None = None
745 ) -> tuple[object, object]:
746 self.load()
747 return (self.im.__arrow_c_schema__(), self.im.__arrow_c_array__())
749 def __getstate__(self) -> list[Any]:
750 im_data = self.tobytes() # load image first
751 return [self.info, self.mode, self.size, self.getpalette(), im_data]
753 def __setstate__(self, state: list[Any]) -> None:
754 Image.__init__(self)
755 info, mode, size, palette, data = state[:5]
756 self.info = info
757 self._mode = mode
758 self._size = size
759 self.im = core.new(mode, size)
760 if mode in ("L", "LA", "P", "PA") and palette:
761 self.putpalette(palette)
762 self.frombytes(data)
764 def tobytes(self, encoder_name: str = "raw", *args: Any) -> bytes:
765 """
766 Return image as a bytes object.
768 .. warning::
770 This method returns the raw image data from the internal
771 storage. For compressed image data (e.g. PNG, JPEG) use
772 :meth:`~.save`, with a BytesIO parameter for in-memory
773 data.
775 :param encoder_name: What encoder to use. The default is to
776 use the standard "raw" encoder.
778 A list of C encoders can be seen under
779 codecs section of the function array in
780 :file:`_imaging.c`. Python encoders are
781 registered within the relevant plugins.
782 :param args: Extra arguments to the encoder.
783 :returns: A :py:class:`bytes` object.
784 """
786 encoder_args: Any = args
787 if len(encoder_args) == 1 and isinstance(encoder_args[0], tuple):
788 # may pass tuple instead of argument list
789 encoder_args = encoder_args[0]
791 if encoder_name == "raw" and encoder_args == ():
792 encoder_args = self.mode
794 self.load()
796 if self.width == 0 or self.height == 0:
797 return b""
799 # unpack data
800 e = _getencoder(self.mode, encoder_name, encoder_args)
801 e.setimage(self.im)
803 bufsize = max(65536, self.size[0] * 4) # see RawEncode.c
805 output = []
806 while True:
807 bytes_consumed, errcode, data = e.encode(bufsize)
808 output.append(data)
809 if errcode:
810 break
811 if errcode < 0:
812 msg = f"encoder error {errcode} in tobytes"
813 raise RuntimeError(msg)
815 return b"".join(output)
817 def tobitmap(self, name: str = "image") -> bytes:
818 """
819 Returns the image converted to an X11 bitmap.
821 .. note:: This method only works for mode "1" images.
823 :param name: The name prefix to use for the bitmap variables.
824 :returns: A string containing an X11 bitmap.
825 :raises ValueError: If the mode is not "1"
826 """
828 self.load()
829 if self.mode != "1":
830 msg = "not a bitmap"
831 raise ValueError(msg)
832 data = self.tobytes("xbm")
833 return b"".join(
834 [
835 f"#define {name}_width {self.size[0]}\n".encode("ascii"),
836 f"#define {name}_height {self.size[1]}\n".encode("ascii"),
837 f"static char {name}_bits[] = {{\n".encode("ascii"),
838 data,
839 b"};",
840 ]
841 )
843 def frombytes(
844 self,
845 data: bytes | bytearray | SupportsArrayInterface,
846 decoder_name: str = "raw",
847 *args: Any,
848 ) -> None:
849 """
850 Loads this image with pixel data from a bytes object.
852 This method is similar to the :py:func:`~PIL.Image.frombytes` function,
853 but loads data into this image instead of creating a new image object.
854 """
856 if self.width == 0 or self.height == 0:
857 return
859 decoder_args: Any = args
860 if len(decoder_args) == 1 and isinstance(decoder_args[0], tuple):
861 # may pass tuple instead of argument list
862 decoder_args = decoder_args[0]
864 # default format
865 if decoder_name == "raw" and decoder_args == ():
866 decoder_args = self.mode
868 # unpack data
869 d = _getdecoder(self.mode, decoder_name, decoder_args)
870 d.setimage(self.im)
871 s = d.decode(data)
873 if s[0] >= 0:
874 msg = "not enough image data"
875 raise ValueError(msg)
876 if s[1] != 0:
877 msg = "cannot decode image data"
878 raise ValueError(msg)
880 def load(self) -> core.PixelAccess | None:
881 """
882 Allocates storage for the image and loads the pixel data. In
883 normal cases, you don't need to call this method, since the
884 Image class automatically loads an opened image when it is
885 accessed for the first time.
887 If the file associated with the image was opened by Pillow, then this
888 method will close it. The exception to this is if the image has
889 multiple frames, in which case the file will be left open for seek
890 operations. See :ref:`file-handling` for more information.
892 :returns: An image access object.
893 :rtype: :py:class:`.PixelAccess`
894 """
895 if self._im is not None and self.palette and self.palette.dirty:
896 # realize palette
897 mode, arr = self.palette.getdata()
898 self.im.putpalette(self.palette.mode, mode, arr)
899 self.palette.dirty = 0
900 self.palette.rawmode = None
901 if "transparency" in self.info and mode in ("LA", "PA"):
902 if isinstance(self.info["transparency"], int):
903 self.im.putpalettealpha(self.info["transparency"], 0)
904 else:
905 self.im.putpalettealphas(self.info["transparency"])
906 self.palette.mode = "RGBA"
907 else:
908 self.palette.palette = self.im.getpalette(
909 self.palette.mode, self.palette.mode
910 )
912 if self._im is not None:
913 return self.im.pixel_access(self.readonly)
914 return None
916 def verify(self) -> None:
917 """
918 Verifies the contents of a file. For data read from a file, this
919 method attempts to determine if the file is broken, without
920 actually decoding the image data. If this method finds any
921 problems, it raises suitable exceptions. If you need to load
922 the image after using this method, you must reopen the image
923 file.
924 """
925 pass
927 def convert(
928 self,
929 mode: str | None = None,
930 matrix: tuple[float, ...] | None = None,
931 dither: Dither | None = None,
932 palette: Palette = Palette.WEB,
933 colors: int = 256,
934 ) -> Image:
935 """
936 Returns a converted copy of this image. For the "P" mode, this
937 method translates pixels through the palette. If mode is
938 omitted, a mode is chosen so that all information in the image
939 and the palette can be represented without a palette.
941 This supports all possible conversions between "L", "RGB" and "CMYK". The
942 ``matrix`` argument only supports "L" and "RGB".
944 When translating a color image to grayscale (mode "L"),
945 the library uses the ITU-R 601-2 luma transform::
947 L = R * 299/1000 + G * 587/1000 + B * 114/1000
949 The default method of converting a grayscale ("L") or "RGB"
950 image into a bilevel (mode "1") image uses Floyd-Steinberg
951 dither to approximate the original image luminosity levels. If
952 dither is ``None``, all values larger than 127 are set to 255 (white),
953 all other values to 0 (black). To use other thresholds, use the
954 :py:meth:`~PIL.Image.Image.point` method.
956 When converting from "RGBA" to "P" without a ``matrix`` argument,
957 this passes the operation to :py:meth:`~PIL.Image.Image.quantize`,
958 and ``dither`` and ``palette`` are ignored.
960 When converting from "PA", if an "RGBA" palette is present, the alpha
961 channel from the image will be used instead of the values from the palette.
963 :param mode: The requested mode. See: :ref:`concept-modes`.
964 :param matrix: An optional conversion matrix. If given, this
965 should be 4- or 12-tuple containing floating point values.
966 :param dither: Dithering method, used when converting from
967 mode "RGB" to "P" or from "RGB" or "L" to "1".
968 Available methods are :data:`Dither.NONE` or :data:`Dither.FLOYDSTEINBERG`
969 (default). Note that this is not used when ``matrix`` is supplied.
970 :param palette: Palette to use when converting from mode "RGB"
971 to "P". Available palettes are :data:`Palette.WEB` or
972 :data:`Palette.ADAPTIVE`.
973 :param colors: Number of colors to use for the :data:`Palette.ADAPTIVE`
974 palette. Defaults to 256.
975 :rtype: :py:class:`~PIL.Image.Image`
976 :returns: An :py:class:`~PIL.Image.Image` object.
977 """
979 if mode in ("BGR;15", "BGR;16", "BGR;24"):
980 deprecate(mode, 12)
982 self.load()
984 has_transparency = "transparency" in self.info
985 if not mode and self.mode == "P":
986 # determine default mode
987 if self.palette:
988 mode = self.palette.mode
989 else:
990 mode = "RGB"
991 if mode == "RGB" and has_transparency:
992 mode = "RGBA"
993 if not mode or (mode == self.mode and not matrix):
994 return self.copy()
996 if matrix:
997 # matrix conversion
998 if mode not in ("L", "RGB"):
999 msg = "illegal conversion"
1000 raise ValueError(msg)
1001 im = self.im.convert_matrix(mode, matrix)
1002 new_im = self._new(im)
1003 if has_transparency and self.im.bands == 3:
1004 transparency = new_im.info["transparency"]
1006 def convert_transparency(
1007 m: tuple[float, ...], v: tuple[int, int, int]
1008 ) -> int:
1009 value = m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3] * 0.5
1010 return max(0, min(255, int(value)))
1012 if mode == "L":
1013 transparency = convert_transparency(matrix, transparency)
1014 elif len(mode) == 3:
1015 transparency = tuple(
1016 convert_transparency(matrix[i * 4 : i * 4 + 4], transparency)
1017 for i in range(len(transparency))
1018 )
1019 new_im.info["transparency"] = transparency
1020 return new_im
1022 if mode == "P" and self.mode == "RGBA":
1023 return self.quantize(colors)
1025 trns = None
1026 delete_trns = False
1027 # transparency handling
1028 if has_transparency:
1029 if (self.mode in ("1", "L", "I", "I;16") and mode in ("LA", "RGBA")) or (
1030 self.mode == "RGB" and mode in ("La", "LA", "RGBa", "RGBA")
1031 ):
1032 # Use transparent conversion to promote from transparent
1033 # color to an alpha channel.
1034 new_im = self._new(
1035 self.im.convert_transparent(mode, self.info["transparency"])
1036 )
1037 del new_im.info["transparency"]
1038 return new_im
1039 elif self.mode in ("L", "RGB", "P") and mode in ("L", "RGB", "P"):
1040 t = self.info["transparency"]
1041 if isinstance(t, bytes):
1042 # Dragons. This can't be represented by a single color
1043 warnings.warn(
1044 "Palette images with Transparency expressed in bytes should be "
1045 "converted to RGBA images"
1046 )
1047 delete_trns = True
1048 else:
1049 # get the new transparency color.
1050 # use existing conversions
1051 trns_im = new(self.mode, (1, 1))
1052 if self.mode == "P":
1053 assert self.palette is not None
1054 trns_im.putpalette(self.palette, self.palette.mode)
1055 if isinstance(t, tuple):
1056 err = "Couldn't allocate a palette color for transparency"
1057 assert trns_im.palette is not None
1058 try:
1059 t = trns_im.palette.getcolor(t, self)
1060 except ValueError as e:
1061 if str(e) == "cannot allocate more than 256 colors":
1062 # If all 256 colors are in use,
1063 # then there is no need for transparency
1064 t = None
1065 else:
1066 raise ValueError(err) from e
1067 if t is None:
1068 trns = None
1069 else:
1070 trns_im.putpixel((0, 0), t)
1072 if mode in ("L", "RGB"):
1073 trns_im = trns_im.convert(mode)
1074 else:
1075 # can't just retrieve the palette number, got to do it
1076 # after quantization.
1077 trns_im = trns_im.convert("RGB")
1078 trns = trns_im.getpixel((0, 0))
1080 elif self.mode == "P" and mode in ("LA", "PA", "RGBA"):
1081 t = self.info["transparency"]
1082 delete_trns = True
1084 if isinstance(t, bytes):
1085 self.im.putpalettealphas(t)
1086 elif isinstance(t, int):
1087 self.im.putpalettealpha(t, 0)
1088 else:
1089 msg = "Transparency for P mode should be bytes or int"
1090 raise ValueError(msg)
1092 if mode == "P" and palette == Palette.ADAPTIVE:
1093 im = self.im.quantize(colors)
1094 new_im = self._new(im)
1095 from . import ImagePalette
1097 new_im.palette = ImagePalette.ImagePalette(
1098 "RGB", new_im.im.getpalette("RGB")
1099 )
1100 if delete_trns:
1101 # This could possibly happen if we requantize to fewer colors.
1102 # The transparency would be totally off in that case.
1103 del new_im.info["transparency"]
1104 if trns is not None:
1105 try:
1106 new_im.info["transparency"] = new_im.palette.getcolor(
1107 cast(tuple[int, ...], trns), # trns was converted to RGB
1108 new_im,
1109 )
1110 except Exception:
1111 # if we can't make a transparent color, don't leave the old
1112 # transparency hanging around to mess us up.
1113 del new_im.info["transparency"]
1114 warnings.warn("Couldn't allocate palette entry for transparency")
1115 return new_im
1117 if "LAB" in (self.mode, mode):
1118 im = self
1119 if mode == "LAB":
1120 if im.mode not in ("RGB", "RGBA", "RGBX"):
1121 im = im.convert("RGBA")
1122 other_mode = im.mode
1123 else:
1124 other_mode = mode
1125 if other_mode in ("RGB", "RGBA", "RGBX"):
1126 from . import ImageCms
1128 srgb = ImageCms.createProfile("sRGB")
1129 lab = ImageCms.createProfile("LAB")
1130 profiles = [lab, srgb] if im.mode == "LAB" else [srgb, lab]
1131 transform = ImageCms.buildTransform(
1132 profiles[0], profiles[1], im.mode, mode
1133 )
1134 return transform.apply(im)
1136 # colorspace conversion
1137 if dither is None:
1138 dither = Dither.FLOYDSTEINBERG
1140 try:
1141 im = self.im.convert(mode, dither)
1142 except ValueError:
1143 try:
1144 # normalize source image and try again
1145 modebase = getmodebase(self.mode)
1146 if modebase == self.mode:
1147 raise
1148 im = self.im.convert(modebase)
1149 im = im.convert(mode, dither)
1150 except KeyError as e:
1151 msg = "illegal conversion"
1152 raise ValueError(msg) from e
1154 new_im = self._new(im)
1155 if mode == "P" and palette != Palette.ADAPTIVE:
1156 from . import ImagePalette
1158 new_im.palette = ImagePalette.ImagePalette("RGB", im.getpalette("RGB"))
1159 if delete_trns:
1160 # crash fail if we leave a bytes transparency in an rgb/l mode.
1161 del new_im.info["transparency"]
1162 if trns is not None:
1163 if new_im.mode == "P" and new_im.palette:
1164 try:
1165 new_im.info["transparency"] = new_im.palette.getcolor(
1166 cast(tuple[int, ...], trns), new_im # trns was converted to RGB
1167 )
1168 except ValueError as e:
1169 del new_im.info["transparency"]
1170 if str(e) != "cannot allocate more than 256 colors":
1171 # If all 256 colors are in use,
1172 # then there is no need for transparency
1173 warnings.warn(
1174 "Couldn't allocate palette entry for transparency"
1175 )
1176 else:
1177 new_im.info["transparency"] = trns
1178 return new_im
1180 def quantize(
1181 self,
1182 colors: int = 256,
1183 method: int | None = None,
1184 kmeans: int = 0,
1185 palette: Image | None = None,
1186 dither: Dither = Dither.FLOYDSTEINBERG,
1187 ) -> Image:
1188 """
1189 Convert the image to 'P' mode with the specified number
1190 of colors.
1192 :param colors: The desired number of colors, <= 256
1193 :param method: :data:`Quantize.MEDIANCUT` (median cut),
1194 :data:`Quantize.MAXCOVERAGE` (maximum coverage),
1195 :data:`Quantize.FASTOCTREE` (fast octree),
1196 :data:`Quantize.LIBIMAGEQUANT` (libimagequant; check support
1197 using :py:func:`PIL.features.check_feature` with
1198 ``feature="libimagequant"``).
1200 By default, :data:`Quantize.MEDIANCUT` will be used.
1202 The exception to this is RGBA images. :data:`Quantize.MEDIANCUT`
1203 and :data:`Quantize.MAXCOVERAGE` do not support RGBA images, so
1204 :data:`Quantize.FASTOCTREE` is used by default instead.
1205 :param kmeans: Integer greater than or equal to zero.
1206 :param palette: Quantize to the palette of given
1207 :py:class:`PIL.Image.Image`.
1208 :param dither: Dithering method, used when converting from
1209 mode "RGB" to "P" or from "RGB" or "L" to "1".
1210 Available methods are :data:`Dither.NONE` or :data:`Dither.FLOYDSTEINBERG`
1211 (default).
1212 :returns: A new image
1213 """
1215 self.load()
1217 if method is None:
1218 # defaults:
1219 method = Quantize.MEDIANCUT
1220 if self.mode == "RGBA":
1221 method = Quantize.FASTOCTREE
1223 if self.mode == "RGBA" and method not in (
1224 Quantize.FASTOCTREE,
1225 Quantize.LIBIMAGEQUANT,
1226 ):
1227 # Caller specified an invalid mode.
1228 msg = (
1229 "Fast Octree (method == 2) and libimagequant (method == 3) "
1230 "are the only valid methods for quantizing RGBA images"
1231 )
1232 raise ValueError(msg)
1234 if palette:
1235 # use palette from reference image
1236 palette.load()
1237 if palette.mode != "P":
1238 msg = "bad mode for palette image"
1239 raise ValueError(msg)
1240 if self.mode not in {"RGB", "L"}:
1241 msg = "only RGB or L mode images can be quantized to a palette"
1242 raise ValueError(msg)
1243 im = self.im.convert("P", dither, palette.im)
1244 new_im = self._new(im)
1245 assert palette.palette is not None
1246 new_im.palette = palette.palette.copy()
1247 return new_im
1249 if kmeans < 0:
1250 msg = "kmeans must not be negative"
1251 raise ValueError(msg)
1253 im = self._new(self.im.quantize(colors, method, kmeans))
1255 from . import ImagePalette
1257 mode = im.im.getpalettemode()
1258 palette_data = im.im.getpalette(mode, mode)[: colors * len(mode)]
1259 im.palette = ImagePalette.ImagePalette(mode, palette_data)
1261 return im
1263 def copy(self) -> Image:
1264 """
1265 Copies this image. Use this method if you wish to paste things
1266 into an image, but still retain the original.
1268 :rtype: :py:class:`~PIL.Image.Image`
1269 :returns: An :py:class:`~PIL.Image.Image` object.
1270 """
1271 self.load()
1272 return self._new(self.im.copy())
1274 __copy__ = copy
1276 def crop(self, box: tuple[float, float, float, float] | None = None) -> Image:
1277 """
1278 Returns a rectangular region from this image. The box is a
1279 4-tuple defining the left, upper, right, and lower pixel
1280 coordinate. See :ref:`coordinate-system`.
1282 Note: Prior to Pillow 3.4.0, this was a lazy operation.
1284 :param box: The crop rectangle, as a (left, upper, right, lower)-tuple.
1285 :rtype: :py:class:`~PIL.Image.Image`
1286 :returns: An :py:class:`~PIL.Image.Image` object.
1287 """
1289 if box is None:
1290 return self.copy()
1292 if box[2] < box[0]:
1293 msg = "Coordinate 'right' is less than 'left'"
1294 raise ValueError(msg)
1295 elif box[3] < box[1]:
1296 msg = "Coordinate 'lower' is less than 'upper'"
1297 raise ValueError(msg)
1299 self.load()
1300 return self._new(self._crop(self.im, box))
1302 def _crop(
1303 self, im: core.ImagingCore, box: tuple[float, float, float, float]
1304 ) -> core.ImagingCore:
1305 """
1306 Returns a rectangular region from the core image object im.
1308 This is equivalent to calling im.crop((x0, y0, x1, y1)), but
1309 includes additional sanity checks.
1311 :param im: a core image object
1312 :param box: The crop rectangle, as a (left, upper, right, lower)-tuple.
1313 :returns: A core image object.
1314 """
1316 x0, y0, x1, y1 = map(int, map(round, box))
1318 absolute_values = (abs(x1 - x0), abs(y1 - y0))
1320 _decompression_bomb_check(absolute_values)
1322 return im.crop((x0, y0, x1, y1))
1324 def draft(
1325 self, mode: str | None, size: tuple[int, int] | None
1326 ) -> tuple[str, tuple[int, int, float, float]] | None:
1327 """
1328 Configures the image file loader so it returns a version of the
1329 image that as closely as possible matches the given mode and
1330 size. For example, you can use this method to convert a color
1331 JPEG to grayscale while loading it.
1333 If any changes are made, returns a tuple with the chosen ``mode`` and
1334 ``box`` with coordinates of the original image within the altered one.
1336 Note that this method modifies the :py:class:`~PIL.Image.Image` object
1337 in place. If the image has already been loaded, this method has no
1338 effect.
1340 Note: This method is not implemented for most images. It is
1341 currently implemented only for JPEG and MPO images.
1343 :param mode: The requested mode.
1344 :param size: The requested size in pixels, as a 2-tuple:
1345 (width, height).
1346 """
1347 pass
1349 def _expand(self, xmargin: int, ymargin: int | None = None) -> Image:
1350 if ymargin is None:
1351 ymargin = xmargin
1352 self.load()
1353 return self._new(self.im.expand(xmargin, ymargin))
1355 def filter(self, filter: ImageFilter.Filter | type[ImageFilter.Filter]) -> Image:
1356 """
1357 Filters this image using the given filter. For a list of
1358 available filters, see the :py:mod:`~PIL.ImageFilter` module.
1360 :param filter: Filter kernel.
1361 :returns: An :py:class:`~PIL.Image.Image` object."""
1363 from . import ImageFilter
1365 self.load()
1367 if callable(filter):
1368 filter = filter()
1369 if not hasattr(filter, "filter"):
1370 msg = "filter argument should be ImageFilter.Filter instance or class"
1371 raise TypeError(msg)
1373 multiband = isinstance(filter, ImageFilter.MultibandFilter)
1374 if self.im.bands == 1 or multiband:
1375 return self._new(filter.filter(self.im))
1377 ims = [
1378 self._new(filter.filter(self.im.getband(c))) for c in range(self.im.bands)
1379 ]
1380 return merge(self.mode, ims)
1382 def getbands(self) -> tuple[str, ...]:
1383 """
1384 Returns a tuple containing the name of each band in this image.
1385 For example, ``getbands`` on an RGB image returns ("R", "G", "B").
1387 :returns: A tuple containing band names.
1388 :rtype: tuple
1389 """
1390 return ImageMode.getmode(self.mode).bands
1392 def getbbox(self, *, alpha_only: bool = True) -> tuple[int, int, int, int] | None:
1393 """
1394 Calculates the bounding box of the non-zero regions in the
1395 image.
1397 :param alpha_only: Optional flag, defaulting to ``True``.
1398 If ``True`` and the image has an alpha channel, trim transparent pixels.
1399 Otherwise, trim pixels when all channels are zero.
1400 Keyword-only argument.
1401 :returns: The bounding box is returned as a 4-tuple defining the
1402 left, upper, right, and lower pixel coordinate. See
1403 :ref:`coordinate-system`. If the image is completely empty, this
1404 method returns None.
1406 """
1408 self.load()
1409 return self.im.getbbox(alpha_only)
1411 def getcolors(
1412 self, maxcolors: int = 256
1413 ) -> list[tuple[int, tuple[int, ...]]] | list[tuple[int, float]] | None:
1414 """
1415 Returns a list of colors used in this image.
1417 The colors will be in the image's mode. For example, an RGB image will
1418 return a tuple of (red, green, blue) color values, and a P image will
1419 return the index of the color in the palette.
1421 :param maxcolors: Maximum number of colors. If this number is
1422 exceeded, this method returns None. The default limit is
1423 256 colors.
1424 :returns: An unsorted list of (count, pixel) values.
1425 """
1427 self.load()
1428 if self.mode in ("1", "L", "P"):
1429 h = self.im.histogram()
1430 out: list[tuple[int, float]] = [(h[i], i) for i in range(256) if h[i]]
1431 if len(out) > maxcolors:
1432 return None
1433 return out
1434 return self.im.getcolors(maxcolors)
1436 def getdata(self, band: int | None = None) -> core.ImagingCore:
1437 """
1438 Returns the contents of this image as a sequence object
1439 containing pixel values. The sequence object is flattened, so
1440 that values for line one follow directly after the values of
1441 line zero, and so on.
1443 Note that the sequence object returned by this method is an
1444 internal PIL data type, which only supports certain sequence
1445 operations. To convert it to an ordinary sequence (e.g. for
1446 printing), use ``list(im.getdata())``.
1448 :param band: What band to return. The default is to return
1449 all bands. To return a single band, pass in the index
1450 value (e.g. 0 to get the "R" band from an "RGB" image).
1451 :returns: A sequence-like object.
1452 """
1454 self.load()
1455 if band is not None:
1456 return self.im.getband(band)
1457 return self.im # could be abused
1459 def getextrema(self) -> tuple[float, float] | tuple[tuple[int, int], ...]:
1460 """
1461 Gets the minimum and maximum pixel values for each band in
1462 the image.
1464 :returns: For a single-band image, a 2-tuple containing the
1465 minimum and maximum pixel value. For a multi-band image,
1466 a tuple containing one 2-tuple for each band.
1467 """
1469 self.load()
1470 if self.im.bands > 1:
1471 return tuple(self.im.getband(i).getextrema() for i in range(self.im.bands))
1472 return self.im.getextrema()
1474 def getxmp(self) -> dict[str, Any]:
1475 """
1476 Returns a dictionary containing the XMP tags.
1477 Requires defusedxml to be installed.
1479 :returns: XMP tags in a dictionary.
1480 """
1482 def get_name(tag: str) -> str:
1483 return re.sub("^{[^}]+}", "", tag)
1485 def get_value(element: Element) -> str | dict[str, Any] | None:
1486 value: dict[str, Any] = {get_name(k): v for k, v in element.attrib.items()}
1487 children = list(element)
1488 if children:
1489 for child in children:
1490 name = get_name(child.tag)
1491 child_value = get_value(child)
1492 if name in value:
1493 if not isinstance(value[name], list):
1494 value[name] = [value[name]]
1495 value[name].append(child_value)
1496 else:
1497 value[name] = child_value
1498 elif value:
1499 if element.text:
1500 value["text"] = element.text
1501 else:
1502 return element.text
1503 return value
1505 if ElementTree is None:
1506 warnings.warn("XMP data cannot be read without defusedxml dependency")
1507 return {}
1508 if "xmp" not in self.info:
1509 return {}
1510 root = ElementTree.fromstring(self.info["xmp"].rstrip(b"\x00"))
1511 return {get_name(root.tag): get_value(root)}
1513 def getexif(self) -> Exif:
1514 """
1515 Gets EXIF data from the image.
1517 :returns: an :py:class:`~PIL.Image.Exif` object.
1518 """
1519 if self._exif is None:
1520 self._exif = Exif()
1521 elif self._exif._loaded:
1522 return self._exif
1523 self._exif._loaded = True
1525 exif_info = self.info.get("exif")
1526 if exif_info is None:
1527 if "Raw profile type exif" in self.info:
1528 exif_info = bytes.fromhex(
1529 "".join(self.info["Raw profile type exif"].split("\n")[3:])
1530 )
1531 elif hasattr(self, "tag_v2"):
1532 self._exif.bigtiff = self.tag_v2._bigtiff
1533 self._exif.endian = self.tag_v2._endian
1534 self._exif.load_from_fp(self.fp, self.tag_v2._offset)
1535 if exif_info is not None:
1536 self._exif.load(exif_info)
1538 # XMP tags
1539 if ExifTags.Base.Orientation not in self._exif:
1540 xmp_tags = self.info.get("XML:com.adobe.xmp")
1541 if not xmp_tags and (xmp_tags := self.info.get("xmp")):
1542 xmp_tags = xmp_tags.decode("utf-8")
1543 if xmp_tags:
1544 match = re.search(r'tiff:Orientation(="|>)([0-9])', xmp_tags)
1545 if match:
1546 self._exif[ExifTags.Base.Orientation] = int(match[2])
1548 return self._exif
1550 def _reload_exif(self) -> None:
1551 if self._exif is None or not self._exif._loaded:
1552 return
1553 self._exif._loaded = False
1554 self.getexif()
1556 def get_child_images(self) -> list[ImageFile.ImageFile]:
1557 from . import ImageFile
1559 deprecate("Image.Image.get_child_images", 13)
1560 return ImageFile.ImageFile.get_child_images(self) # type: ignore[arg-type]
1562 def getim(self) -> CapsuleType:
1563 """
1564 Returns a capsule that points to the internal image memory.
1566 :returns: A capsule object.
1567 """
1569 self.load()
1570 return self.im.ptr
1572 def getpalette(self, rawmode: str | None = "RGB") -> list[int] | None:
1573 """
1574 Returns the image palette as a list.
1576 :param rawmode: The mode in which to return the palette. ``None`` will
1577 return the palette in its current mode.
1579 .. versionadded:: 9.1.0
1581 :returns: A list of color values [r, g, b, ...], or None if the
1582 image has no palette.
1583 """
1585 self.load()
1586 try:
1587 mode = self.im.getpalettemode()
1588 except ValueError:
1589 return None # no palette
1590 if rawmode is None:
1591 rawmode = mode
1592 return list(self.im.getpalette(mode, rawmode))
1594 @property
1595 def has_transparency_data(self) -> bool:
1596 """
1597 Determine if an image has transparency data, whether in the form of an
1598 alpha channel, a palette with an alpha channel, or a "transparency" key
1599 in the info dictionary.
1601 Note the image might still appear solid, if all of the values shown
1602 within are opaque.
1604 :returns: A boolean.
1605 """
1606 if (
1607 self.mode in ("LA", "La", "PA", "RGBA", "RGBa")
1608 or "transparency" in self.info
1609 ):
1610 return True
1611 if self.mode == "P":
1612 assert self.palette is not None
1613 return self.palette.mode.endswith("A")
1614 return False
1616 def apply_transparency(self) -> None:
1617 """
1618 If a P mode image has a "transparency" key in the info dictionary,
1619 remove the key and instead apply the transparency to the palette.
1620 Otherwise, the image is unchanged.
1621 """
1622 if self.mode != "P" or "transparency" not in self.info:
1623 return
1625 from . import ImagePalette
1627 palette = self.getpalette("RGBA")
1628 assert palette is not None
1629 transparency = self.info["transparency"]
1630 if isinstance(transparency, bytes):
1631 for i, alpha in enumerate(transparency):
1632 palette[i * 4 + 3] = alpha
1633 else:
1634 palette[transparency * 4 + 3] = 0
1635 self.palette = ImagePalette.ImagePalette("RGBA", bytes(palette))
1636 self.palette.dirty = 1
1638 del self.info["transparency"]
1640 def getpixel(
1641 self, xy: tuple[int, int] | list[int]
1642 ) -> float | tuple[int, ...] | None:
1643 """
1644 Returns the pixel value at a given position.
1646 :param xy: The coordinate, given as (x, y). See
1647 :ref:`coordinate-system`.
1648 :returns: The pixel value. If the image is a multi-layer image,
1649 this method returns a tuple.
1650 """
1652 self.load()
1653 return self.im.getpixel(tuple(xy))
1655 def getprojection(self) -> tuple[list[int], list[int]]:
1656 """
1657 Get projection to x and y axes
1659 :returns: Two sequences, indicating where there are non-zero
1660 pixels along the X-axis and the Y-axis, respectively.
1661 """
1663 self.load()
1664 x, y = self.im.getprojection()
1665 return list(x), list(y)
1667 def histogram(
1668 self, mask: Image | None = None, extrema: tuple[float, float] | None = None
1669 ) -> list[int]:
1670 """
1671 Returns a histogram for the image. The histogram is returned as a
1672 list of pixel counts, one for each pixel value in the source
1673 image. Counts are grouped into 256 bins for each band, even if
1674 the image has more than 8 bits per band. If the image has more
1675 than one band, the histograms for all bands are concatenated (for
1676 example, the histogram for an "RGB" image contains 768 values).
1678 A bilevel image (mode "1") is treated as a grayscale ("L") image
1679 by this method.
1681 If a mask is provided, the method returns a histogram for those
1682 parts of the image where the mask image is non-zero. The mask
1683 image must have the same size as the image, and be either a
1684 bi-level image (mode "1") or a grayscale image ("L").
1686 :param mask: An optional mask.
1687 :param extrema: An optional tuple of manually-specified extrema.
1688 :returns: A list containing pixel counts.
1689 """
1690 self.load()
1691 if mask:
1692 mask.load()
1693 return self.im.histogram((0, 0), mask.im)
1694 if self.mode in ("I", "F"):
1695 return self.im.histogram(
1696 extrema if extrema is not None else self.getextrema()
1697 )
1698 return self.im.histogram()
1700 def entropy(
1701 self, mask: Image | None = None, extrema: tuple[float, float] | None = None
1702 ) -> float:
1703 """
1704 Calculates and returns the entropy for the image.
1706 A bilevel image (mode "1") is treated as a grayscale ("L")
1707 image by this method.
1709 If a mask is provided, the method employs the histogram for
1710 those parts of the image where the mask image is non-zero.
1711 The mask image must have the same size as the image, and be
1712 either a bi-level image (mode "1") or a grayscale image ("L").
1714 :param mask: An optional mask.
1715 :param extrema: An optional tuple of manually-specified extrema.
1716 :returns: A float value representing the image entropy
1717 """
1718 self.load()
1719 if mask:
1720 mask.load()
1721 return self.im.entropy((0, 0), mask.im)
1722 if self.mode in ("I", "F"):
1723 return self.im.entropy(
1724 extrema if extrema is not None else self.getextrema()
1725 )
1726 return self.im.entropy()
1728 def paste(
1729 self,
1730 im: Image | str | float | tuple[float, ...],
1731 box: Image | tuple[int, int, int, int] | tuple[int, int] | None = None,
1732 mask: Image | None = None,
1733 ) -> None:
1734 """
1735 Pastes another image into this image. The box argument is either
1736 a 2-tuple giving the upper left corner, a 4-tuple defining the
1737 left, upper, right, and lower pixel coordinate, or None (same as
1738 (0, 0)). See :ref:`coordinate-system`. If a 4-tuple is given, the size
1739 of the pasted image must match the size of the region.
1741 If the modes don't match, the pasted image is converted to the mode of
1742 this image (see the :py:meth:`~PIL.Image.Image.convert` method for
1743 details).
1745 Instead of an image, the source can be a integer or tuple
1746 containing pixel values. The method then fills the region
1747 with the given color. When creating RGB images, you can
1748 also use color strings as supported by the ImageColor module.
1750 If a mask is given, this method updates only the regions
1751 indicated by the mask. You can use either "1", "L", "LA", "RGBA"
1752 or "RGBa" images (if present, the alpha band is used as mask).
1753 Where the mask is 255, the given image is copied as is. Where
1754 the mask is 0, the current value is preserved. Intermediate
1755 values will mix the two images together, including their alpha
1756 channels if they have them.
1758 See :py:meth:`~PIL.Image.Image.alpha_composite` if you want to
1759 combine images with respect to their alpha channels.
1761 :param im: Source image or pixel value (integer, float or tuple).
1762 :param box: An optional 4-tuple giving the region to paste into.
1763 If a 2-tuple is used instead, it's treated as the upper left
1764 corner. If omitted or None, the source is pasted into the
1765 upper left corner.
1767 If an image is given as the second argument and there is no
1768 third, the box defaults to (0, 0), and the second argument
1769 is interpreted as a mask image.
1770 :param mask: An optional mask image.
1771 """
1773 if isinstance(box, Image):
1774 if mask is not None:
1775 msg = "If using second argument as mask, third argument must be None"
1776 raise ValueError(msg)
1777 # abbreviated paste(im, mask) syntax
1778 mask = box
1779 box = None
1781 if box is None:
1782 box = (0, 0)
1784 if len(box) == 2:
1785 # upper left corner given; get size from image or mask
1786 if isinstance(im, Image):
1787 size = im.size
1788 elif isinstance(mask, Image):
1789 size = mask.size
1790 else:
1791 # FIXME: use self.size here?
1792 msg = "cannot determine region size; use 4-item box"
1793 raise ValueError(msg)
1794 box += (box[0] + size[0], box[1] + size[1])
1796 source: core.ImagingCore | str | float | tuple[float, ...]
1797 if isinstance(im, str):
1798 from . import ImageColor
1800 source = ImageColor.getcolor(im, self.mode)
1801 elif isinstance(im, Image):
1802 im.load()
1803 if self.mode != im.mode:
1804 if self.mode != "RGB" or im.mode not in ("LA", "RGBA", "RGBa"):
1805 # should use an adapter for this!
1806 im = im.convert(self.mode)
1807 source = im.im
1808 else:
1809 source = im
1811 self._ensure_mutable()
1813 if mask:
1814 mask.load()
1815 self.im.paste(source, box, mask.im)
1816 else:
1817 self.im.paste(source, box)
1819 def alpha_composite(
1820 self, im: Image, dest: Sequence[int] = (0, 0), source: Sequence[int] = (0, 0)
1821 ) -> None:
1822 """'In-place' analog of Image.alpha_composite. Composites an image
1823 onto this image.
1825 :param im: image to composite over this one
1826 :param dest: Optional 2 tuple (left, top) specifying the upper
1827 left corner in this (destination) image.
1828 :param source: Optional 2 (left, top) tuple for the upper left
1829 corner in the overlay source image, or 4 tuple (left, top, right,
1830 bottom) for the bounds of the source rectangle
1832 Performance Note: Not currently implemented in-place in the core layer.
1833 """
1835 if not isinstance(source, (list, tuple)):
1836 msg = "Source must be a list or tuple"
1837 raise ValueError(msg)
1838 if not isinstance(dest, (list, tuple)):
1839 msg = "Destination must be a list or tuple"
1840 raise ValueError(msg)
1842 if len(source) == 4:
1843 overlay_crop_box = tuple(source)
1844 elif len(source) == 2:
1845 overlay_crop_box = tuple(source) + im.size
1846 else:
1847 msg = "Source must be a sequence of length 2 or 4"
1848 raise ValueError(msg)
1850 if not len(dest) == 2:
1851 msg = "Destination must be a sequence of length 2"
1852 raise ValueError(msg)
1853 if min(source) < 0:
1854 msg = "Source must be non-negative"
1855 raise ValueError(msg)
1857 # over image, crop if it's not the whole image.
1858 if overlay_crop_box == (0, 0) + im.size:
1859 overlay = im
1860 else:
1861 overlay = im.crop(overlay_crop_box)
1863 # target for the paste
1864 box = tuple(dest) + (dest[0] + overlay.width, dest[1] + overlay.height)
1866 # destination image. don't copy if we're using the whole image.
1867 if box == (0, 0) + self.size:
1868 background = self
1869 else:
1870 background = self.crop(box)
1872 result = alpha_composite(background, overlay)
1873 self.paste(result, box)
1875 def point(
1876 self,
1877 lut: (
1878 Sequence[float]
1879 | NumpyArray
1880 | Callable[[int], float]
1881 | Callable[[ImagePointTransform], ImagePointTransform | float]
1882 | ImagePointHandler
1883 ),
1884 mode: str | None = None,
1885 ) -> Image:
1886 """
1887 Maps this image through a lookup table or function.
1889 :param lut: A lookup table, containing 256 (or 65536 if
1890 self.mode=="I" and mode == "L") values per band in the
1891 image. A function can be used instead, it should take a
1892 single argument. The function is called once for each
1893 possible pixel value, and the resulting table is applied to
1894 all bands of the image.
1896 It may also be an :py:class:`~PIL.Image.ImagePointHandler`
1897 object::
1899 class Example(Image.ImagePointHandler):
1900 def point(self, im: Image) -> Image:
1901 # Return result
1902 :param mode: Output mode (default is same as input). This can only be used if
1903 the source image has mode "L" or "P", and the output has mode "1" or the
1904 source image mode is "I" and the output mode is "L".
1905 :returns: An :py:class:`~PIL.Image.Image` object.
1906 """
1908 self.load()
1910 if isinstance(lut, ImagePointHandler):
1911 return lut.point(self)
1913 if callable(lut):
1914 # if it isn't a list, it should be a function
1915 if self.mode in ("I", "I;16", "F"):
1916 # check if the function can be used with point_transform
1917 # UNDONE wiredfool -- I think this prevents us from ever doing
1918 # a gamma function point transform on > 8bit images.
1919 scale, offset = _getscaleoffset(lut) # type: ignore[arg-type]
1920 return self._new(self.im.point_transform(scale, offset))
1921 # for other modes, convert the function to a table
1922 flatLut = [lut(i) for i in range(256)] * self.im.bands # type: ignore[arg-type]
1923 else:
1924 flatLut = lut
1926 if self.mode == "F":
1927 # FIXME: _imaging returns a confusing error message for this case
1928 msg = "point operation not supported for this mode"
1929 raise ValueError(msg)
1931 if mode != "F":
1932 flatLut = [round(i) for i in flatLut]
1933 return self._new(self.im.point(flatLut, mode))
1935 def putalpha(self, alpha: Image | int) -> None:
1936 """
1937 Adds or replaces the alpha layer in this image. If the image
1938 does not have an alpha layer, it's converted to "LA" or "RGBA".
1939 The new layer must be either "L" or "1".
1941 :param alpha: The new alpha layer. This can either be an "L" or "1"
1942 image having the same size as this image, or an integer.
1943 """
1945 self._ensure_mutable()
1947 if self.mode not in ("LA", "PA", "RGBA"):
1948 # attempt to promote self to a matching alpha mode
1949 try:
1950 mode = getmodebase(self.mode) + "A"
1951 try:
1952 self.im.setmode(mode)
1953 except (AttributeError, ValueError) as e:
1954 # do things the hard way
1955 im = self.im.convert(mode)
1956 if im.mode not in ("LA", "PA", "RGBA"):
1957 msg = "alpha channel could not be added"
1958 raise ValueError(msg) from e # sanity check
1959 self.im = im
1960 self._mode = self.im.mode
1961 except KeyError as e:
1962 msg = "illegal image mode"
1963 raise ValueError(msg) from e
1965 if self.mode in ("LA", "PA"):
1966 band = 1
1967 else:
1968 band = 3
1970 if isinstance(alpha, Image):
1971 # alpha layer
1972 if alpha.mode not in ("1", "L"):
1973 msg = "illegal image mode"
1974 raise ValueError(msg)
1975 alpha.load()
1976 if alpha.mode == "1":
1977 alpha = alpha.convert("L")
1978 else:
1979 # constant alpha
1980 try:
1981 self.im.fillband(band, alpha)
1982 except (AttributeError, ValueError):
1983 # do things the hard way
1984 alpha = new("L", self.size, alpha)
1985 else:
1986 return
1988 self.im.putband(alpha.im, band)
1990 def putdata(
1991 self,
1992 data: Sequence[float] | Sequence[Sequence[int]] | core.ImagingCore | NumpyArray,
1993 scale: float = 1.0,
1994 offset: float = 0.0,
1995 ) -> None:
1996 """
1997 Copies pixel data from a flattened sequence object into the image. The
1998 values should start at the upper left corner (0, 0), continue to the
1999 end of the line, followed directly by the first value of the second
2000 line, and so on. Data will be read until either the image or the
2001 sequence ends. The scale and offset values are used to adjust the
2002 sequence values: **pixel = value*scale + offset**.
2004 :param data: A flattened sequence object.
2005 :param scale: An optional scale value. The default is 1.0.
2006 :param offset: An optional offset value. The default is 0.0.
2007 """
2009 self._ensure_mutable()
2011 self.im.putdata(data, scale, offset)
2013 def putpalette(
2014 self,
2015 data: ImagePalette.ImagePalette | bytes | Sequence[int],
2016 rawmode: str = "RGB",
2017 ) -> None:
2018 """
2019 Attaches a palette to this image. The image must be a "P", "PA", "L"
2020 or "LA" image.
2022 The palette sequence must contain at most 256 colors, made up of one
2023 integer value for each channel in the raw mode.
2024 For example, if the raw mode is "RGB", then it can contain at most 768
2025 values, made up of red, green and blue values for the corresponding pixel
2026 index in the 256 colors.
2027 If the raw mode is "RGBA", then it can contain at most 1024 values,
2028 containing red, green, blue and alpha values.
2030 Alternatively, an 8-bit string may be used instead of an integer sequence.
2032 :param data: A palette sequence (either a list or a string).
2033 :param rawmode: The raw mode of the palette. Either "RGB", "RGBA", or a mode
2034 that can be transformed to "RGB" or "RGBA" (e.g. "R", "BGR;15", "RGBA;L").
2035 """
2036 from . import ImagePalette
2038 if self.mode not in ("L", "LA", "P", "PA"):
2039 msg = "illegal image mode"
2040 raise ValueError(msg)
2041 if isinstance(data, ImagePalette.ImagePalette):
2042 if data.rawmode is not None:
2043 palette = ImagePalette.raw(data.rawmode, data.palette)
2044 else:
2045 palette = ImagePalette.ImagePalette(palette=data.palette)
2046 palette.dirty = 1
2047 else:
2048 if not isinstance(data, bytes):
2049 data = bytes(data)
2050 palette = ImagePalette.raw(rawmode, data)
2051 self._mode = "PA" if "A" in self.mode else "P"
2052 self.palette = palette
2053 self.palette.mode = "RGBA" if "A" in rawmode else "RGB"
2054 self.load() # install new palette
2056 def putpixel(
2057 self, xy: tuple[int, int], value: float | tuple[int, ...] | list[int]
2058 ) -> None:
2059 """
2060 Modifies the pixel at the given position. The color is given as
2061 a single numerical value for single-band images, and a tuple for
2062 multi-band images. In addition to this, RGB and RGBA tuples are
2063 accepted for P and PA images.
2065 Note that this method is relatively slow. For more extensive changes,
2066 use :py:meth:`~PIL.Image.Image.paste` or the :py:mod:`~PIL.ImageDraw`
2067 module instead.
2069 See:
2071 * :py:meth:`~PIL.Image.Image.paste`
2072 * :py:meth:`~PIL.Image.Image.putdata`
2073 * :py:mod:`~PIL.ImageDraw`
2075 :param xy: The pixel coordinate, given as (x, y). See
2076 :ref:`coordinate-system`.
2077 :param value: The pixel value.
2078 """
2080 if self.readonly:
2081 self._copy()
2082 self.load()
2084 if (
2085 self.mode in ("P", "PA")
2086 and isinstance(value, (list, tuple))
2087 and len(value) in [3, 4]
2088 ):
2089 # RGB or RGBA value for a P or PA image
2090 if self.mode == "PA":
2091 alpha = value[3] if len(value) == 4 else 255
2092 value = value[:3]
2093 assert self.palette is not None
2094 palette_index = self.palette.getcolor(tuple(value), self)
2095 value = (palette_index, alpha) if self.mode == "PA" else palette_index
2096 return self.im.putpixel(xy, value)
2098 def remap_palette(
2099 self, dest_map: list[int], source_palette: bytes | bytearray | None = None
2100 ) -> Image:
2101 """
2102 Rewrites the image to reorder the palette.
2104 :param dest_map: A list of indexes into the original palette.
2105 e.g. ``[1,0]`` would swap a two item palette, and ``list(range(256))``
2106 is the identity transform.
2107 :param source_palette: Bytes or None.
2108 :returns: An :py:class:`~PIL.Image.Image` object.
2110 """
2111 from . import ImagePalette
2113 if self.mode not in ("L", "P"):
2114 msg = "illegal image mode"
2115 raise ValueError(msg)
2117 bands = 3
2118 palette_mode = "RGB"
2119 if source_palette is None:
2120 if self.mode == "P":
2121 self.load()
2122 palette_mode = self.im.getpalettemode()
2123 if palette_mode == "RGBA":
2124 bands = 4
2125 source_palette = self.im.getpalette(palette_mode, palette_mode)
2126 else: # L-mode
2127 source_palette = bytearray(i // 3 for i in range(768))
2128 elif len(source_palette) > 768:
2129 bands = 4
2130 palette_mode = "RGBA"
2132 palette_bytes = b""
2133 new_positions = [0] * 256
2135 # pick only the used colors from the palette
2136 for i, oldPosition in enumerate(dest_map):
2137 palette_bytes += source_palette[
2138 oldPosition * bands : oldPosition * bands + bands
2139 ]
2140 new_positions[oldPosition] = i
2142 # replace the palette color id of all pixel with the new id
2144 # Palette images are [0..255], mapped through a 1 or 3
2145 # byte/color map. We need to remap the whole image
2146 # from palette 1 to palette 2. New_positions is
2147 # an array of indexes into palette 1. Palette 2 is
2148 # palette 1 with any holes removed.
2150 # We're going to leverage the convert mechanism to use the
2151 # C code to remap the image from palette 1 to palette 2,
2152 # by forcing the source image into 'L' mode and adding a
2153 # mapping 'L' mode palette, then converting back to 'L'
2154 # sans palette thus converting the image bytes, then
2155 # assigning the optimized RGB palette.
2157 # perf reference, 9500x4000 gif, w/~135 colors
2158 # 14 sec prepatch, 1 sec postpatch with optimization forced.
2160 mapping_palette = bytearray(new_positions)
2162 m_im = self.copy()
2163 m_im._mode = "P"
2165 m_im.palette = ImagePalette.ImagePalette(
2166 palette_mode, palette=mapping_palette * bands
2167 )
2168 # possibly set palette dirty, then
2169 # m_im.putpalette(mapping_palette, 'L') # converts to 'P'
2170 # or just force it.
2171 # UNDONE -- this is part of the general issue with palettes
2172 m_im.im.putpalette(palette_mode, palette_mode + ";L", m_im.palette.tobytes())
2174 m_im = m_im.convert("L")
2176 m_im.putpalette(palette_bytes, palette_mode)
2177 m_im.palette = ImagePalette.ImagePalette(palette_mode, palette=palette_bytes)
2179 if "transparency" in self.info:
2180 try:
2181 m_im.info["transparency"] = dest_map.index(self.info["transparency"])
2182 except ValueError:
2183 if "transparency" in m_im.info:
2184 del m_im.info["transparency"]
2186 return m_im
2188 def _get_safe_box(
2189 self,
2190 size: tuple[int, int],
2191 resample: Resampling,
2192 box: tuple[float, float, float, float],
2193 ) -> tuple[int, int, int, int]:
2194 """Expands the box so it includes adjacent pixels
2195 that may be used by resampling with the given resampling filter.
2196 """
2197 filter_support = _filters_support[resample] - 0.5
2198 scale_x = (box[2] - box[0]) / size[0]
2199 scale_y = (box[3] - box[1]) / size[1]
2200 support_x = filter_support * scale_x
2201 support_y = filter_support * scale_y
2203 return (
2204 max(0, int(box[0] - support_x)),
2205 max(0, int(box[1] - support_y)),
2206 min(self.size[0], math.ceil(box[2] + support_x)),
2207 min(self.size[1], math.ceil(box[3] + support_y)),
2208 )
2210 def resize(
2211 self,
2212 size: tuple[int, int] | list[int] | NumpyArray,
2213 resample: int | None = None,
2214 box: tuple[float, float, float, float] | None = None,
2215 reducing_gap: float | None = None,
2216 ) -> Image:
2217 """
2218 Returns a resized copy of this image.
2220 :param size: The requested size in pixels, as a tuple or array:
2221 (width, height).
2222 :param resample: An optional resampling filter. This can be
2223 one of :py:data:`Resampling.NEAREST`, :py:data:`Resampling.BOX`,
2224 :py:data:`Resampling.BILINEAR`, :py:data:`Resampling.HAMMING`,
2225 :py:data:`Resampling.BICUBIC` or :py:data:`Resampling.LANCZOS`.
2226 If the image has mode "1" or "P", it is always set to
2227 :py:data:`Resampling.NEAREST`. If the image mode is "BGR;15",
2228 "BGR;16" or "BGR;24", then the default filter is
2229 :py:data:`Resampling.NEAREST`. Otherwise, the default filter is
2230 :py:data:`Resampling.BICUBIC`. See: :ref:`concept-filters`.
2231 :param box: An optional 4-tuple of floats providing
2232 the source image region to be scaled.
2233 The values must be within (0, 0, width, height) rectangle.
2234 If omitted or None, the entire source is used.
2235 :param reducing_gap: Apply optimization by resizing the image
2236 in two steps. First, reducing the image by integer times
2237 using :py:meth:`~PIL.Image.Image.reduce`.
2238 Second, resizing using regular resampling. The last step
2239 changes size no less than by ``reducing_gap`` times.
2240 ``reducing_gap`` may be None (no first step is performed)
2241 or should be greater than 1.0. The bigger ``reducing_gap``,
2242 the closer the result to the fair resampling.
2243 The smaller ``reducing_gap``, the faster resizing.
2244 With ``reducing_gap`` greater or equal to 3.0, the result is
2245 indistinguishable from fair resampling in most cases.
2246 The default value is None (no optimization).
2247 :returns: An :py:class:`~PIL.Image.Image` object.
2248 """
2250 if resample is None:
2251 bgr = self.mode.startswith("BGR;")
2252 resample = Resampling.NEAREST if bgr else Resampling.BICUBIC
2253 elif resample not in (
2254 Resampling.NEAREST,
2255 Resampling.BILINEAR,
2256 Resampling.BICUBIC,
2257 Resampling.LANCZOS,
2258 Resampling.BOX,
2259 Resampling.HAMMING,
2260 ):
2261 msg = f"Unknown resampling filter ({resample})."
2263 filters = [
2264 f"{filter[1]} ({filter[0]})"
2265 for filter in (
2266 (Resampling.NEAREST, "Image.Resampling.NEAREST"),
2267 (Resampling.LANCZOS, "Image.Resampling.LANCZOS"),
2268 (Resampling.BILINEAR, "Image.Resampling.BILINEAR"),
2269 (Resampling.BICUBIC, "Image.Resampling.BICUBIC"),
2270 (Resampling.BOX, "Image.Resampling.BOX"),
2271 (Resampling.HAMMING, "Image.Resampling.HAMMING"),
2272 )
2273 ]
2274 msg += f" Use {', '.join(filters[:-1])} or {filters[-1]}"
2275 raise ValueError(msg)
2277 if reducing_gap is not None and reducing_gap < 1.0:
2278 msg = "reducing_gap must be 1.0 or greater"
2279 raise ValueError(msg)
2281 if box is None:
2282 box = (0, 0) + self.size
2284 size = tuple(size)
2285 if self.size == size and box == (0, 0) + self.size:
2286 return self.copy()
2288 if self.mode in ("1", "P"):
2289 resample = Resampling.NEAREST
2291 if self.mode in ["LA", "RGBA"] and resample != Resampling.NEAREST:
2292 im = self.convert({"LA": "La", "RGBA": "RGBa"}[self.mode])
2293 im = im.resize(size, resample, box)
2294 return im.convert(self.mode)
2296 self.load()
2298 if reducing_gap is not None and resample != Resampling.NEAREST:
2299 factor_x = int((box[2] - box[0]) / size[0] / reducing_gap) or 1
2300 factor_y = int((box[3] - box[1]) / size[1] / reducing_gap) or 1
2301 if factor_x > 1 or factor_y > 1:
2302 reduce_box = self._get_safe_box(size, cast(Resampling, resample), box)
2303 factor = (factor_x, factor_y)
2304 self = (
2305 self.reduce(factor, box=reduce_box)
2306 if callable(self.reduce)
2307 else Image.reduce(self, factor, box=reduce_box)
2308 )
2309 box = (
2310 (box[0] - reduce_box[0]) / factor_x,
2311 (box[1] - reduce_box[1]) / factor_y,
2312 (box[2] - reduce_box[0]) / factor_x,
2313 (box[3] - reduce_box[1]) / factor_y,
2314 )
2316 return self._new(self.im.resize(size, resample, box))
2318 def reduce(
2319 self,
2320 factor: int | tuple[int, int],
2321 box: tuple[int, int, int, int] | None = None,
2322 ) -> Image:
2323 """
2324 Returns a copy of the image reduced ``factor`` times.
2325 If the size of the image is not dividable by ``factor``,
2326 the resulting size will be rounded up.
2328 :param factor: A greater than 0 integer or tuple of two integers
2329 for width and height separately.
2330 :param box: An optional 4-tuple of ints providing
2331 the source image region to be reduced.
2332 The values must be within ``(0, 0, width, height)`` rectangle.
2333 If omitted or ``None``, the entire source is used.
2334 """
2335 if not isinstance(factor, (list, tuple)):
2336 factor = (factor, factor)
2338 if box is None:
2339 box = (0, 0) + self.size
2341 if factor == (1, 1) and box == (0, 0) + self.size:
2342 return self.copy()
2344 if self.mode in ["LA", "RGBA"]:
2345 im = self.convert({"LA": "La", "RGBA": "RGBa"}[self.mode])
2346 im = im.reduce(factor, box)
2347 return im.convert(self.mode)
2349 self.load()
2351 return self._new(self.im.reduce(factor, box))
2353 def rotate(
2354 self,
2355 angle: float,
2356 resample: Resampling = Resampling.NEAREST,
2357 expand: int | bool = False,
2358 center: tuple[float, float] | None = None,
2359 translate: tuple[int, int] | None = None,
2360 fillcolor: float | tuple[float, ...] | str | None = None,
2361 ) -> Image:
2362 """
2363 Returns a rotated copy of this image. This method returns a
2364 copy of this image, rotated the given number of degrees counter
2365 clockwise around its centre.
2367 :param angle: In degrees counter clockwise.
2368 :param resample: An optional resampling filter. This can be
2369 one of :py:data:`Resampling.NEAREST` (use nearest neighbour),
2370 :py:data:`Resampling.BILINEAR` (linear interpolation in a 2x2
2371 environment), or :py:data:`Resampling.BICUBIC` (cubic spline
2372 interpolation in a 4x4 environment). If omitted, or if the image has
2373 mode "1" or "P", it is set to :py:data:`Resampling.NEAREST`.
2374 See :ref:`concept-filters`.
2375 :param expand: Optional expansion flag. If true, expands the output
2376 image to make it large enough to hold the entire rotated image.
2377 If false or omitted, make the output image the same size as the
2378 input image. Note that the expand flag assumes rotation around
2379 the center and no translation.
2380 :param center: Optional center of rotation (a 2-tuple). Origin is
2381 the upper left corner. Default is the center of the image.
2382 :param translate: An optional post-rotate translation (a 2-tuple).
2383 :param fillcolor: An optional color for area outside the rotated image.
2384 :returns: An :py:class:`~PIL.Image.Image` object.
2385 """
2387 angle = angle % 360.0
2389 # Fast paths regardless of filter, as long as we're not
2390 # translating or changing the center.
2391 if not (center or translate):
2392 if angle == 0:
2393 return self.copy()
2394 if angle == 180:
2395 return self.transpose(Transpose.ROTATE_180)
2396 if angle in (90, 270) and (expand or self.width == self.height):
2397 return self.transpose(
2398 Transpose.ROTATE_90 if angle == 90 else Transpose.ROTATE_270
2399 )
2401 # Calculate the affine matrix. Note that this is the reverse
2402 # transformation (from destination image to source) because we
2403 # want to interpolate the (discrete) destination pixel from
2404 # the local area around the (floating) source pixel.
2406 # The matrix we actually want (note that it operates from the right):
2407 # (1, 0, tx) (1, 0, cx) ( cos a, sin a, 0) (1, 0, -cx)
2408 # (0, 1, ty) * (0, 1, cy) * (-sin a, cos a, 0) * (0, 1, -cy)
2409 # (0, 0, 1) (0, 0, 1) ( 0, 0, 1) (0, 0, 1)
2411 # The reverse matrix is thus:
2412 # (1, 0, cx) ( cos -a, sin -a, 0) (1, 0, -cx) (1, 0, -tx)
2413 # (0, 1, cy) * (-sin -a, cos -a, 0) * (0, 1, -cy) * (0, 1, -ty)
2414 # (0, 0, 1) ( 0, 0, 1) (0, 0, 1) (0, 0, 1)
2416 # In any case, the final translation may be updated at the end to
2417 # compensate for the expand flag.
2419 w, h = self.size
2421 if translate is None:
2422 post_trans = (0, 0)
2423 else:
2424 post_trans = translate
2425 if center is None:
2426 center = (w / 2, h / 2)
2428 angle = -math.radians(angle)
2429 matrix = [
2430 round(math.cos(angle), 15),
2431 round(math.sin(angle), 15),
2432 0.0,
2433 round(-math.sin(angle), 15),
2434 round(math.cos(angle), 15),
2435 0.0,
2436 ]
2438 def transform(x: float, y: float, matrix: list[float]) -> tuple[float, float]:
2439 (a, b, c, d, e, f) = matrix
2440 return a * x + b * y + c, d * x + e * y + f
2442 matrix[2], matrix[5] = transform(
2443 -center[0] - post_trans[0], -center[1] - post_trans[1], matrix
2444 )
2445 matrix[2] += center[0]
2446 matrix[5] += center[1]
2448 if expand:
2449 # calculate output size
2450 xx = []
2451 yy = []
2452 for x, y in ((0, 0), (w, 0), (w, h), (0, h)):
2453 transformed_x, transformed_y = transform(x, y, matrix)
2454 xx.append(transformed_x)
2455 yy.append(transformed_y)
2456 nw = math.ceil(max(xx)) - math.floor(min(xx))
2457 nh = math.ceil(max(yy)) - math.floor(min(yy))
2459 # We multiply a translation matrix from the right. Because of its
2460 # special form, this is the same as taking the image of the
2461 # translation vector as new translation vector.
2462 matrix[2], matrix[5] = transform(-(nw - w) / 2.0, -(nh - h) / 2.0, matrix)
2463 w, h = nw, nh
2465 return self.transform(
2466 (w, h), Transform.AFFINE, matrix, resample, fillcolor=fillcolor
2467 )
2469 def save(
2470 self, fp: StrOrBytesPath | IO[bytes], format: str | None = None, **params: Any
2471 ) -> None:
2472 """
2473 Saves this image under the given filename. If no format is
2474 specified, the format to use is determined from the filename
2475 extension, if possible.
2477 Keyword options can be used to provide additional instructions
2478 to the writer. If a writer doesn't recognise an option, it is
2479 silently ignored. The available options are described in the
2480 :doc:`image format documentation
2481 <../handbook/image-file-formats>` for each writer.
2483 You can use a file object instead of a filename. In this case,
2484 you must always specify the format. The file object must
2485 implement the ``seek``, ``tell``, and ``write``
2486 methods, and be opened in binary mode.
2488 :param fp: A filename (string), os.PathLike object or file object.
2489 :param format: Optional format override. If omitted, the
2490 format to use is determined from the filename extension.
2491 If a file object was used instead of a filename, this
2492 parameter should always be used.
2493 :param params: Extra parameters to the image writer. These can also be
2494 set on the image itself through ``encoderinfo``. This is useful when
2495 saving multiple images::
2497 # Saving XMP data to a single image
2498 from PIL import Image
2499 red = Image.new("RGB", (1, 1), "#f00")
2500 red.save("out.mpo", xmp=b"test")
2502 # Saving XMP data to the second frame of an image
2503 from PIL import Image
2504 black = Image.new("RGB", (1, 1))
2505 red = Image.new("RGB", (1, 1), "#f00")
2506 red.encoderinfo = {"xmp": b"test"}
2507 black.save("out.mpo", save_all=True, append_images=[red])
2508 :returns: None
2509 :exception ValueError: If the output format could not be determined
2510 from the file name. Use the format option to solve this.
2511 :exception OSError: If the file could not be written. The file
2512 may have been created, and may contain partial data.
2513 """
2515 filename: str | bytes = ""
2516 open_fp = False
2517 if is_path(fp):
2518 filename = os.fspath(fp)
2519 open_fp = True
2520 elif fp == sys.stdout:
2521 try:
2522 fp = sys.stdout.buffer
2523 except AttributeError:
2524 pass
2525 if not filename and hasattr(fp, "name") and is_path(fp.name):
2526 # only set the name for metadata purposes
2527 filename = os.fspath(fp.name)
2529 preinit()
2531 filename_ext = os.path.splitext(filename)[1].lower()
2532 ext = filename_ext.decode() if isinstance(filename_ext, bytes) else filename_ext
2534 if not format:
2535 if ext not in EXTENSION:
2536 init()
2537 try:
2538 format = EXTENSION[ext]
2539 except KeyError as e:
2540 msg = f"unknown file extension: {ext}"
2541 raise ValueError(msg) from e
2543 from . import ImageFile
2545 # may mutate self!
2546 if isinstance(self, ImageFile.ImageFile) and os.path.abspath(
2547 filename
2548 ) == os.path.abspath(self.filename):
2549 self._ensure_mutable()
2550 else:
2551 self.load()
2553 save_all = params.pop("save_all", None)
2554 self.encoderinfo = {**getattr(self, "encoderinfo", {}), **params}
2555 self.encoderconfig: tuple[Any, ...] = ()
2557 if format.upper() not in SAVE:
2558 init()
2559 if save_all or (
2560 save_all is None
2561 and params.get("append_images")
2562 and format.upper() in SAVE_ALL
2563 ):
2564 save_handler = SAVE_ALL[format.upper()]
2565 else:
2566 save_handler = SAVE[format.upper()]
2568 created = False
2569 if open_fp:
2570 created = not os.path.exists(filename)
2571 if params.get("append", False):
2572 # Open also for reading ("+"), because TIFF save_all
2573 # writer needs to go back and edit the written data.
2574 fp = builtins.open(filename, "r+b")
2575 else:
2576 fp = builtins.open(filename, "w+b")
2577 else:
2578 fp = cast(IO[bytes], fp)
2580 try:
2581 save_handler(self, fp, filename)
2582 except Exception:
2583 if open_fp:
2584 fp.close()
2585 if created:
2586 try:
2587 os.remove(filename)
2588 except PermissionError:
2589 pass
2590 raise
2591 finally:
2592 try:
2593 del self.encoderinfo
2594 except AttributeError:
2595 pass
2596 if open_fp:
2597 fp.close()
2599 def seek(self, frame: int) -> None:
2600 """
2601 Seeks to the given frame in this sequence file. If you seek
2602 beyond the end of the sequence, the method raises an
2603 ``EOFError`` exception. When a sequence file is opened, the
2604 library automatically seeks to frame 0.
2606 See :py:meth:`~PIL.Image.Image.tell`.
2608 If defined, :attr:`~PIL.Image.Image.n_frames` refers to the
2609 number of available frames.
2611 :param frame: Frame number, starting at 0.
2612 :exception EOFError: If the call attempts to seek beyond the end
2613 of the sequence.
2614 """
2616 # overridden by file handlers
2617 if frame != 0:
2618 msg = "no more images in file"
2619 raise EOFError(msg)
2621 def show(self, title: str | None = None) -> None:
2622 """
2623 Displays this image. This method is mainly intended for debugging purposes.
2625 This method calls :py:func:`PIL.ImageShow.show` internally. You can use
2626 :py:func:`PIL.ImageShow.register` to override its default behaviour.
2628 The image is first saved to a temporary file. By default, it will be in
2629 PNG format.
2631 On Unix, the image is then opened using the **xdg-open**, **display**,
2632 **gm**, **eog** or **xv** utility, depending on which one can be found.
2634 On macOS, the image is opened with the native Preview application.
2636 On Windows, the image is opened with the standard PNG display utility.
2638 :param title: Optional title to use for the image window, where possible.
2639 """
2641 _show(self, title=title)
2643 def split(self) -> tuple[Image, ...]:
2644 """
2645 Split this image into individual bands. This method returns a
2646 tuple of individual image bands from an image. For example,
2647 splitting an "RGB" image creates three new images each
2648 containing a copy of one of the original bands (red, green,
2649 blue).
2651 If you need only one band, :py:meth:`~PIL.Image.Image.getchannel`
2652 method can be more convenient and faster.
2654 :returns: A tuple containing bands.
2655 """
2657 self.load()
2658 if self.im.bands == 1:
2659 return (self.copy(),)
2660 return tuple(map(self._new, self.im.split()))
2662 def getchannel(self, channel: int | str) -> Image:
2663 """
2664 Returns an image containing a single channel of the source image.
2666 :param channel: What channel to return. Could be index
2667 (0 for "R" channel of "RGB") or channel name
2668 ("A" for alpha channel of "RGBA").
2669 :returns: An image in "L" mode.
2671 .. versionadded:: 4.3.0
2672 """
2673 self.load()
2675 if isinstance(channel, str):
2676 try:
2677 channel = self.getbands().index(channel)
2678 except ValueError as e:
2679 msg = f'The image has no channel "{channel}"'
2680 raise ValueError(msg) from e
2682 return self._new(self.im.getband(channel))
2684 def tell(self) -> int:
2685 """
2686 Returns the current frame number. See :py:meth:`~PIL.Image.Image.seek`.
2688 If defined, :attr:`~PIL.Image.Image.n_frames` refers to the
2689 number of available frames.
2691 :returns: Frame number, starting with 0.
2692 """
2693 return 0
2695 def thumbnail(
2696 self,
2697 size: tuple[float, float],
2698 resample: Resampling = Resampling.BICUBIC,
2699 reducing_gap: float | None = 2.0,
2700 ) -> None:
2701 """
2702 Make this image into a thumbnail. This method modifies the
2703 image to contain a thumbnail version of itself, no larger than
2704 the given size. This method calculates an appropriate thumbnail
2705 size to preserve the aspect of the image, calls the
2706 :py:meth:`~PIL.Image.Image.draft` method to configure the file reader
2707 (where applicable), and finally resizes the image.
2709 Note that this function modifies the :py:class:`~PIL.Image.Image`
2710 object in place. If you need to use the full resolution image as well,
2711 apply this method to a :py:meth:`~PIL.Image.Image.copy` of the original
2712 image.
2714 :param size: The requested size in pixels, as a 2-tuple:
2715 (width, height).
2716 :param resample: Optional resampling filter. This can be one
2717 of :py:data:`Resampling.NEAREST`, :py:data:`Resampling.BOX`,
2718 :py:data:`Resampling.BILINEAR`, :py:data:`Resampling.HAMMING`,
2719 :py:data:`Resampling.BICUBIC` or :py:data:`Resampling.LANCZOS`.
2720 If omitted, it defaults to :py:data:`Resampling.BICUBIC`.
2721 (was :py:data:`Resampling.NEAREST` prior to version 2.5.0).
2722 See: :ref:`concept-filters`.
2723 :param reducing_gap: Apply optimization by resizing the image
2724 in two steps. First, reducing the image by integer times
2725 using :py:meth:`~PIL.Image.Image.reduce` or
2726 :py:meth:`~PIL.Image.Image.draft` for JPEG images.
2727 Second, resizing using regular resampling. The last step
2728 changes size no less than by ``reducing_gap`` times.
2729 ``reducing_gap`` may be None (no first step is performed)
2730 or should be greater than 1.0. The bigger ``reducing_gap``,
2731 the closer the result to the fair resampling.
2732 The smaller ``reducing_gap``, the faster resizing.
2733 With ``reducing_gap`` greater or equal to 3.0, the result is
2734 indistinguishable from fair resampling in most cases.
2735 The default value is 2.0 (very close to fair resampling
2736 while still being faster in many cases).
2737 :returns: None
2738 """
2740 provided_size = tuple(map(math.floor, size))
2742 def preserve_aspect_ratio() -> tuple[int, int] | None:
2743 def round_aspect(number: float, key: Callable[[int], float]) -> int:
2744 return max(min(math.floor(number), math.ceil(number), key=key), 1)
2746 x, y = provided_size
2747 if x >= self.width and y >= self.height:
2748 return None
2750 aspect = self.width / self.height
2751 if x / y >= aspect:
2752 x = round_aspect(y * aspect, key=lambda n: abs(aspect - n / y))
2753 else:
2754 y = round_aspect(
2755 x / aspect, key=lambda n: 0 if n == 0 else abs(aspect - x / n)
2756 )
2757 return x, y
2759 preserved_size = preserve_aspect_ratio()
2760 if preserved_size is None:
2761 return
2762 final_size = preserved_size
2764 box = None
2765 if reducing_gap is not None:
2766 res = self.draft(
2767 None, (int(size[0] * reducing_gap), int(size[1] * reducing_gap))
2768 )
2769 if res is not None:
2770 box = res[1]
2772 if self.size != final_size:
2773 im = self.resize(final_size, resample, box=box, reducing_gap=reducing_gap)
2775 self.im = im.im
2776 self._size = final_size
2777 self._mode = self.im.mode
2779 self.readonly = 0
2781 # FIXME: the different transform methods need further explanation
2782 # instead of bloating the method docs, add a separate chapter.
2783 def transform(
2784 self,
2785 size: tuple[int, int],
2786 method: Transform | ImageTransformHandler | SupportsGetData,
2787 data: Sequence[Any] | None = None,
2788 resample: int = Resampling.NEAREST,
2789 fill: int = 1,
2790 fillcolor: float | tuple[float, ...] | str | None = None,
2791 ) -> Image:
2792 """
2793 Transforms this image. This method creates a new image with the
2794 given size, and the same mode as the original, and copies data
2795 to the new image using the given transform.
2797 :param size: The output size in pixels, as a 2-tuple:
2798 (width, height).
2799 :param method: The transformation method. This is one of
2800 :py:data:`Transform.EXTENT` (cut out a rectangular subregion),
2801 :py:data:`Transform.AFFINE` (affine transform),
2802 :py:data:`Transform.PERSPECTIVE` (perspective transform),
2803 :py:data:`Transform.QUAD` (map a quadrilateral to a rectangle), or
2804 :py:data:`Transform.MESH` (map a number of source quadrilaterals
2805 in one operation).
2807 It may also be an :py:class:`~PIL.Image.ImageTransformHandler`
2808 object::
2810 class Example(Image.ImageTransformHandler):
2811 def transform(self, size, data, resample, fill=1):
2812 # Return result
2814 Implementations of :py:class:`~PIL.Image.ImageTransformHandler`
2815 for some of the :py:class:`Transform` methods are provided
2816 in :py:mod:`~PIL.ImageTransform`.
2818 It may also be an object with a ``method.getdata`` method
2819 that returns a tuple supplying new ``method`` and ``data`` values::
2821 class Example:
2822 def getdata(self):
2823 method = Image.Transform.EXTENT
2824 data = (0, 0, 100, 100)
2825 return method, data
2826 :param data: Extra data to the transformation method.
2827 :param resample: Optional resampling filter. It can be one of
2828 :py:data:`Resampling.NEAREST` (use nearest neighbour),
2829 :py:data:`Resampling.BILINEAR` (linear interpolation in a 2x2
2830 environment), or :py:data:`Resampling.BICUBIC` (cubic spline
2831 interpolation in a 4x4 environment). If omitted, or if the image
2832 has mode "1" or "P", it is set to :py:data:`Resampling.NEAREST`.
2833 See: :ref:`concept-filters`.
2834 :param fill: If ``method`` is an
2835 :py:class:`~PIL.Image.ImageTransformHandler` object, this is one of
2836 the arguments passed to it. Otherwise, it is unused.
2837 :param fillcolor: Optional fill color for the area outside the
2838 transform in the output image.
2839 :returns: An :py:class:`~PIL.Image.Image` object.
2840 """
2842 if self.mode in ("LA", "RGBA") and resample != Resampling.NEAREST:
2843 return (
2844 self.convert({"LA": "La", "RGBA": "RGBa"}[self.mode])
2845 .transform(size, method, data, resample, fill, fillcolor)
2846 .convert(self.mode)
2847 )
2849 if isinstance(method, ImageTransformHandler):
2850 return method.transform(size, self, resample=resample, fill=fill)
2852 if hasattr(method, "getdata"):
2853 # compatibility w. old-style transform objects
2854 method, data = method.getdata()
2856 if data is None:
2857 msg = "missing method data"
2858 raise ValueError(msg)
2860 im = new(self.mode, size, fillcolor)
2861 if self.mode == "P" and self.palette:
2862 im.palette = self.palette.copy()
2863 im.info = self.info.copy()
2864 if method == Transform.MESH:
2865 # list of quads
2866 for box, quad in data:
2867 im.__transformer(
2868 box, self, Transform.QUAD, quad, resample, fillcolor is None
2869 )
2870 else:
2871 im.__transformer(
2872 (0, 0) + size, self, method, data, resample, fillcolor is None
2873 )
2875 return im
2877 def __transformer(
2878 self,
2879 box: tuple[int, int, int, int],
2880 image: Image,
2881 method: Transform,
2882 data: Sequence[float],
2883 resample: int = Resampling.NEAREST,
2884 fill: bool = True,
2885 ) -> None:
2886 w = box[2] - box[0]
2887 h = box[3] - box[1]
2889 if method == Transform.AFFINE:
2890 data = data[:6]
2892 elif method == Transform.EXTENT:
2893 # convert extent to an affine transform
2894 x0, y0, x1, y1 = data
2895 xs = (x1 - x0) / w
2896 ys = (y1 - y0) / h
2897 method = Transform.AFFINE
2898 data = (xs, 0, x0, 0, ys, y0)
2900 elif method == Transform.PERSPECTIVE:
2901 data = data[:8]
2903 elif method == Transform.QUAD:
2904 # quadrilateral warp. data specifies the four corners
2905 # given as NW, SW, SE, and NE.
2906 nw = data[:2]
2907 sw = data[2:4]
2908 se = data[4:6]
2909 ne = data[6:8]
2910 x0, y0 = nw
2911 As = 1.0 / w
2912 At = 1.0 / h
2913 data = (
2914 x0,
2915 (ne[0] - x0) * As,
2916 (sw[0] - x0) * At,
2917 (se[0] - sw[0] - ne[0] + x0) * As * At,
2918 y0,
2919 (ne[1] - y0) * As,
2920 (sw[1] - y0) * At,
2921 (se[1] - sw[1] - ne[1] + y0) * As * At,
2922 )
2924 else:
2925 msg = "unknown transformation method"
2926 raise ValueError(msg)
2928 if resample not in (
2929 Resampling.NEAREST,
2930 Resampling.BILINEAR,
2931 Resampling.BICUBIC,
2932 ):
2933 if resample in (Resampling.BOX, Resampling.HAMMING, Resampling.LANCZOS):
2934 unusable: dict[int, str] = {
2935 Resampling.BOX: "Image.Resampling.BOX",
2936 Resampling.HAMMING: "Image.Resampling.HAMMING",
2937 Resampling.LANCZOS: "Image.Resampling.LANCZOS",
2938 }
2939 msg = unusable[resample] + f" ({resample}) cannot be used."
2940 else:
2941 msg = f"Unknown resampling filter ({resample})."
2943 filters = [
2944 f"{filter[1]} ({filter[0]})"
2945 for filter in (
2946 (Resampling.NEAREST, "Image.Resampling.NEAREST"),
2947 (Resampling.BILINEAR, "Image.Resampling.BILINEAR"),
2948 (Resampling.BICUBIC, "Image.Resampling.BICUBIC"),
2949 )
2950 ]
2951 msg += f" Use {', '.join(filters[:-1])} or {filters[-1]}"
2952 raise ValueError(msg)
2954 image.load()
2956 self.load()
2958 if image.mode in ("1", "P"):
2959 resample = Resampling.NEAREST
2961 self.im.transform(box, image.im, method, data, resample, fill)
2963 def transpose(self, method: Transpose) -> Image:
2964 """
2965 Transpose image (flip or rotate in 90 degree steps)
2967 :param method: One of :py:data:`Transpose.FLIP_LEFT_RIGHT`,
2968 :py:data:`Transpose.FLIP_TOP_BOTTOM`, :py:data:`Transpose.ROTATE_90`,
2969 :py:data:`Transpose.ROTATE_180`, :py:data:`Transpose.ROTATE_270`,
2970 :py:data:`Transpose.TRANSPOSE` or :py:data:`Transpose.TRANSVERSE`.
2971 :returns: Returns a flipped or rotated copy of this image.
2972 """
2974 self.load()
2975 return self._new(self.im.transpose(method))
2977 def effect_spread(self, distance: int) -> Image:
2978 """
2979 Randomly spread pixels in an image.
2981 :param distance: Distance to spread pixels.
2982 """
2983 self.load()
2984 return self._new(self.im.effect_spread(distance))
2986 def toqimage(self) -> ImageQt.ImageQt:
2987 """Returns a QImage copy of this image"""
2988 from . import ImageQt
2990 if not ImageQt.qt_is_installed:
2991 msg = "Qt bindings are not installed"
2992 raise ImportError(msg)
2993 return ImageQt.toqimage(self)
2995 def toqpixmap(self) -> ImageQt.QPixmap:
2996 """Returns a QPixmap copy of this image"""
2997 from . import ImageQt
2999 if not ImageQt.qt_is_installed:
3000 msg = "Qt bindings are not installed"
3001 raise ImportError(msg)
3002 return ImageQt.toqpixmap(self)
3005# --------------------------------------------------------------------
3006# Abstract handlers.
3009class ImagePointHandler(abc.ABC):
3010 """
3011 Used as a mixin by point transforms
3012 (for use with :py:meth:`~PIL.Image.Image.point`)
3013 """
3015 @abc.abstractmethod
3016 def point(self, im: Image) -> Image:
3017 pass
3020class ImageTransformHandler(abc.ABC):
3021 """
3022 Used as a mixin by geometry transforms
3023 (for use with :py:meth:`~PIL.Image.Image.transform`)
3024 """
3026 @abc.abstractmethod
3027 def transform(
3028 self,
3029 size: tuple[int, int],
3030 image: Image,
3031 **options: Any,
3032 ) -> Image:
3033 pass
3036# --------------------------------------------------------------------
3037# Factories
3040def _check_size(size: Any) -> None:
3041 """
3042 Common check to enforce type and sanity check on size tuples
3044 :param size: Should be a 2 tuple of (width, height)
3045 :returns: None, or raises a ValueError
3046 """
3048 if not isinstance(size, (list, tuple)):
3049 msg = "Size must be a list or tuple"
3050 raise ValueError(msg)
3051 if len(size) != 2:
3052 msg = "Size must be a sequence of length 2"
3053 raise ValueError(msg)
3054 if size[0] < 0 or size[1] < 0:
3055 msg = "Width and height must be >= 0"
3056 raise ValueError(msg)
3059def new(
3060 mode: str,
3061 size: tuple[int, int] | list[int],
3062 color: float | tuple[float, ...] | str | None = 0,
3063) -> Image:
3064 """
3065 Creates a new image with the given mode and size.
3067 :param mode: The mode to use for the new image. See:
3068 :ref:`concept-modes`.
3069 :param size: A 2-tuple, containing (width, height) in pixels.
3070 :param color: What color to use for the image. Default is black.
3071 If given, this should be a single integer or floating point value
3072 for single-band modes, and a tuple for multi-band modes (one value
3073 per band). When creating RGB or HSV images, you can also use color
3074 strings as supported by the ImageColor module. If the color is
3075 None, the image is not initialised.
3076 :returns: An :py:class:`~PIL.Image.Image` object.
3077 """
3079 if mode in ("BGR;15", "BGR;16", "BGR;24"):
3080 deprecate(mode, 12)
3082 _check_size(size)
3084 if color is None:
3085 # don't initialize
3086 return Image()._new(core.new(mode, size))
3088 if isinstance(color, str):
3089 # css3-style specifier
3091 from . import ImageColor
3093 color = ImageColor.getcolor(color, mode)
3095 im = Image()
3096 if (
3097 mode == "P"
3098 and isinstance(color, (list, tuple))
3099 and all(isinstance(i, int) for i in color)
3100 ):
3101 color_ints: tuple[int, ...] = cast(tuple[int, ...], tuple(color))
3102 if len(color_ints) == 3 or len(color_ints) == 4:
3103 # RGB or RGBA value for a P image
3104 from . import ImagePalette
3106 im.palette = ImagePalette.ImagePalette()
3107 color = im.palette.getcolor(color_ints)
3108 return im._new(core.fill(mode, size, color))
3111def frombytes(
3112 mode: str,
3113 size: tuple[int, int],
3114 data: bytes | bytearray | SupportsArrayInterface,
3115 decoder_name: str = "raw",
3116 *args: Any,
3117) -> Image:
3118 """
3119 Creates a copy of an image memory from pixel data in a buffer.
3121 In its simplest form, this function takes three arguments
3122 (mode, size, and unpacked pixel data).
3124 You can also use any pixel decoder supported by PIL. For more
3125 information on available decoders, see the section
3126 :ref:`Writing Your Own File Codec <file-codecs>`.
3128 Note that this function decodes pixel data only, not entire images.
3129 If you have an entire image in a string, wrap it in a
3130 :py:class:`~io.BytesIO` object, and use :py:func:`~PIL.Image.open` to load
3131 it.
3133 :param mode: The image mode. See: :ref:`concept-modes`.
3134 :param size: The image size.
3135 :param data: A byte buffer containing raw data for the given mode.
3136 :param decoder_name: What decoder to use.
3137 :param args: Additional parameters for the given decoder.
3138 :returns: An :py:class:`~PIL.Image.Image` object.
3139 """
3141 _check_size(size)
3143 im = new(mode, size)
3144 if im.width != 0 and im.height != 0:
3145 decoder_args: Any = args
3146 if len(decoder_args) == 1 and isinstance(decoder_args[0], tuple):
3147 # may pass tuple instead of argument list
3148 decoder_args = decoder_args[0]
3150 if decoder_name == "raw" and decoder_args == ():
3151 decoder_args = mode
3153 im.frombytes(data, decoder_name, decoder_args)
3154 return im
3157def frombuffer(
3158 mode: str,
3159 size: tuple[int, int],
3160 data: bytes | SupportsArrayInterface,
3161 decoder_name: str = "raw",
3162 *args: Any,
3163) -> Image:
3164 """
3165 Creates an image memory referencing pixel data in a byte buffer.
3167 This function is similar to :py:func:`~PIL.Image.frombytes`, but uses data
3168 in the byte buffer, where possible. This means that changes to the
3169 original buffer object are reflected in this image). Not all modes can
3170 share memory; supported modes include "L", "RGBX", "RGBA", and "CMYK".
3172 Note that this function decodes pixel data only, not entire images.
3173 If you have an entire image file in a string, wrap it in a
3174 :py:class:`~io.BytesIO` object, and use :py:func:`~PIL.Image.open` to load it.
3176 The default parameters used for the "raw" decoder differs from that used for
3177 :py:func:`~PIL.Image.frombytes`. This is a bug, and will probably be fixed in a
3178 future release. The current release issues a warning if you do this; to disable
3179 the warning, you should provide the full set of parameters. See below for details.
3181 :param mode: The image mode. See: :ref:`concept-modes`.
3182 :param size: The image size.
3183 :param data: A bytes or other buffer object containing raw
3184 data for the given mode.
3185 :param decoder_name: What decoder to use.
3186 :param args: Additional parameters for the given decoder. For the
3187 default encoder ("raw"), it's recommended that you provide the
3188 full set of parameters::
3190 frombuffer(mode, size, data, "raw", mode, 0, 1)
3192 :returns: An :py:class:`~PIL.Image.Image` object.
3194 .. versionadded:: 1.1.4
3195 """
3197 _check_size(size)
3199 # may pass tuple instead of argument list
3200 if len(args) == 1 and isinstance(args[0], tuple):
3201 args = args[0]
3203 if decoder_name == "raw":
3204 if args == ():
3205 args = mode, 0, 1
3206 if args[0] in _MAPMODES:
3207 im = new(mode, (0, 0))
3208 im = im._new(core.map_buffer(data, size, decoder_name, 0, args))
3209 if mode == "P":
3210 from . import ImagePalette
3212 im.palette = ImagePalette.ImagePalette("RGB", im.im.getpalette("RGB"))
3213 im.readonly = 1
3214 return im
3216 return frombytes(mode, size, data, decoder_name, args)
3219class SupportsArrayInterface(Protocol):
3220 """
3221 An object that has an ``__array_interface__`` dictionary.
3222 """
3224 @property
3225 def __array_interface__(self) -> dict[str, Any]:
3226 raise NotImplementedError()
3229class SupportsArrowArrayInterface(Protocol):
3230 """
3231 An object that has an ``__arrow_c_array__`` method corresponding to the arrow c
3232 data interface.
3233 """
3235 def __arrow_c_array__(
3236 self, requested_schema: "PyCapsule" = None # type: ignore[name-defined] # noqa: F821, UP037
3237 ) -> tuple["PyCapsule", "PyCapsule"]: # type: ignore[name-defined] # noqa: F821, UP037
3238 raise NotImplementedError()
3241def fromarray(obj: SupportsArrayInterface, mode: str | None = None) -> Image:
3242 """
3243 Creates an image memory from an object exporting the array interface
3244 (using the buffer protocol)::
3246 from PIL import Image
3247 import numpy as np
3248 a = np.zeros((5, 5))
3249 im = Image.fromarray(a)
3251 If ``obj`` is not contiguous, then the ``tobytes`` method is called
3252 and :py:func:`~PIL.Image.frombuffer` is used.
3254 In the case of NumPy, be aware that Pillow modes do not always correspond
3255 to NumPy dtypes. Pillow modes only offer 1-bit pixels, 8-bit pixels,
3256 32-bit signed integer pixels, and 32-bit floating point pixels.
3258 Pillow images can also be converted to arrays::
3260 from PIL import Image
3261 import numpy as np
3262 im = Image.open("hopper.jpg")
3263 a = np.asarray(im)
3265 When converting Pillow images to arrays however, only pixel values are
3266 transferred. This means that P and PA mode images will lose their palette.
3268 :param obj: Object with array interface
3269 :param mode: Optional mode to use when reading ``obj``. Will be determined from
3270 type if ``None``.
3272 This will not be used to convert the data after reading, but will be used to
3273 change how the data is read::
3275 from PIL import Image
3276 import numpy as np
3277 a = np.full((1, 1), 300)
3278 im = Image.fromarray(a, mode="L")
3279 im.getpixel((0, 0)) # 44
3280 im = Image.fromarray(a, mode="RGB")
3281 im.getpixel((0, 0)) # (44, 1, 0)
3283 See: :ref:`concept-modes` for general information about modes.
3284 :returns: An image object.
3286 .. versionadded:: 1.1.6
3287 """
3288 arr = obj.__array_interface__
3289 shape = arr["shape"]
3290 ndim = len(shape)
3291 strides = arr.get("strides", None)
3292 if mode is None:
3293 try:
3294 typekey = (1, 1) + shape[2:], arr["typestr"]
3295 except KeyError as e:
3296 msg = "Cannot handle this data type"
3297 raise TypeError(msg) from e
3298 try:
3299 mode, rawmode = _fromarray_typemap[typekey]
3300 except KeyError as e:
3301 typekey_shape, typestr = typekey
3302 msg = f"Cannot handle this data type: {typekey_shape}, {typestr}"
3303 raise TypeError(msg) from e
3304 else:
3305 rawmode = mode
3306 if mode in ["1", "L", "I", "P", "F"]:
3307 ndmax = 2
3308 elif mode == "RGB":
3309 ndmax = 3
3310 else:
3311 ndmax = 4
3312 if ndim > ndmax:
3313 msg = f"Too many dimensions: {ndim} > {ndmax}."
3314 raise ValueError(msg)
3316 size = 1 if ndim == 1 else shape[1], shape[0]
3317 if strides is not None:
3318 if hasattr(obj, "tobytes"):
3319 obj = obj.tobytes()
3320 elif hasattr(obj, "tostring"):
3321 obj = obj.tostring()
3322 else:
3323 msg = "'strides' requires either tobytes() or tostring()"
3324 raise ValueError(msg)
3326 return frombuffer(mode, size, obj, "raw", rawmode, 0, 1)
3329def fromarrow(
3330 obj: SupportsArrowArrayInterface, mode: str, size: tuple[int, int]
3331) -> Image:
3332 """Creates an image with zero-copy shared memory from an object exporting
3333 the arrow_c_array interface protocol::
3335 from PIL import Image
3336 import pyarrow as pa
3337 arr = pa.array([0]*(5*5*4), type=pa.uint8())
3338 im = Image.fromarrow(arr, 'RGBA', (5, 5))
3340 If the data representation of the ``obj`` is not compatible with
3341 Pillow internal storage, a ValueError is raised.
3343 Pillow images can also be converted to Arrow objects::
3345 from PIL import Image
3346 import pyarrow as pa
3347 im = Image.open('hopper.jpg')
3348 arr = pa.array(im)
3350 As with array support, when converting Pillow images to arrays,
3351 only pixel values are transferred. This means that P and PA mode
3352 images will lose their palette.
3354 :param obj: Object with an arrow_c_array interface
3355 :param mode: Image mode.
3356 :param size: Image size. This must match the storage of the arrow object.
3357 :returns: An Image object
3359 Note that according to the Arrow spec, both the producer and the
3360 consumer should consider the exported array to be immutable, as
3361 unsynchronized updates will potentially cause inconsistent data.
3363 See: :ref:`arrow-support` for more detailed information
3365 .. versionadded:: 11.2.1
3367 """
3368 if not hasattr(obj, "__arrow_c_array__"):
3369 msg = "arrow_c_array interface not found"
3370 raise ValueError(msg)
3372 (schema_capsule, array_capsule) = obj.__arrow_c_array__()
3373 _im = core.new_arrow(mode, size, schema_capsule, array_capsule)
3374 if _im:
3375 return Image()._new(_im)
3377 msg = "new_arrow returned None without an exception"
3378 raise ValueError(msg)
3381def fromqimage(im: ImageQt.QImage) -> ImageFile.ImageFile:
3382 """Creates an image instance from a QImage image"""
3383 from . import ImageQt
3385 if not ImageQt.qt_is_installed:
3386 msg = "Qt bindings are not installed"
3387 raise ImportError(msg)
3388 return ImageQt.fromqimage(im)
3391def fromqpixmap(im: ImageQt.QPixmap) -> ImageFile.ImageFile:
3392 """Creates an image instance from a QPixmap image"""
3393 from . import ImageQt
3395 if not ImageQt.qt_is_installed:
3396 msg = "Qt bindings are not installed"
3397 raise ImportError(msg)
3398 return ImageQt.fromqpixmap(im)
3401_fromarray_typemap = {
3402 # (shape, typestr) => mode, rawmode
3403 # first two members of shape are set to one
3404 ((1, 1), "|b1"): ("1", "1;8"),
3405 ((1, 1), "|u1"): ("L", "L"),
3406 ((1, 1), "|i1"): ("I", "I;8"),
3407 ((1, 1), "<u2"): ("I", "I;16"),
3408 ((1, 1), ">u2"): ("I", "I;16B"),
3409 ((1, 1), "<i2"): ("I", "I;16S"),
3410 ((1, 1), ">i2"): ("I", "I;16BS"),
3411 ((1, 1), "<u4"): ("I", "I;32"),
3412 ((1, 1), ">u4"): ("I", "I;32B"),
3413 ((1, 1), "<i4"): ("I", "I;32S"),
3414 ((1, 1), ">i4"): ("I", "I;32BS"),
3415 ((1, 1), "<f4"): ("F", "F;32F"),
3416 ((1, 1), ">f4"): ("F", "F;32BF"),
3417 ((1, 1), "<f8"): ("F", "F;64F"),
3418 ((1, 1), ">f8"): ("F", "F;64BF"),
3419 ((1, 1, 2), "|u1"): ("LA", "LA"),
3420 ((1, 1, 3), "|u1"): ("RGB", "RGB"),
3421 ((1, 1, 4), "|u1"): ("RGBA", "RGBA"),
3422 # shortcuts:
3423 ((1, 1), f"{_ENDIAN}i4"): ("I", "I"),
3424 ((1, 1), f"{_ENDIAN}f4"): ("F", "F"),
3425}
3428def _decompression_bomb_check(size: tuple[int, int]) -> None:
3429 if MAX_IMAGE_PIXELS is None:
3430 return
3432 pixels = max(1, size[0]) * max(1, size[1])
3434 if pixels > 2 * MAX_IMAGE_PIXELS:
3435 msg = (
3436 f"Image size ({pixels} pixels) exceeds limit of {2 * MAX_IMAGE_PIXELS} "
3437 "pixels, could be decompression bomb DOS attack."
3438 )
3439 raise DecompressionBombError(msg)
3441 if pixels > MAX_IMAGE_PIXELS:
3442 warnings.warn(
3443 f"Image size ({pixels} pixels) exceeds limit of {MAX_IMAGE_PIXELS} pixels, "
3444 "could be decompression bomb DOS attack.",
3445 DecompressionBombWarning,
3446 )
3449def open(
3450 fp: StrOrBytesPath | IO[bytes],
3451 mode: Literal["r"] = "r",
3452 formats: list[str] | tuple[str, ...] | None = None,
3453) -> ImageFile.ImageFile:
3454 """
3455 Opens and identifies the given image file.
3457 This is a lazy operation; this function identifies the file, but
3458 the file remains open and the actual image data is not read from
3459 the file until you try to process the data (or call the
3460 :py:meth:`~PIL.Image.Image.load` method). See
3461 :py:func:`~PIL.Image.new`. See :ref:`file-handling`.
3463 :param fp: A filename (string), os.PathLike object or a file object.
3464 The file object must implement ``file.read``,
3465 ``file.seek``, and ``file.tell`` methods,
3466 and be opened in binary mode. The file object will also seek to zero
3467 before reading.
3468 :param mode: The mode. If given, this argument must be "r".
3469 :param formats: A list or tuple of formats to attempt to load the file in.
3470 This can be used to restrict the set of formats checked.
3471 Pass ``None`` to try all supported formats. You can print the set of
3472 available formats by running ``python3 -m PIL`` or using
3473 the :py:func:`PIL.features.pilinfo` function.
3474 :returns: An :py:class:`~PIL.Image.Image` object.
3475 :exception FileNotFoundError: If the file cannot be found.
3476 :exception PIL.UnidentifiedImageError: If the image cannot be opened and
3477 identified.
3478 :exception ValueError: If the ``mode`` is not "r", or if a ``StringIO``
3479 instance is used for ``fp``.
3480 :exception TypeError: If ``formats`` is not ``None``, a list or a tuple.
3481 """
3483 if mode != "r":
3484 msg = f"bad mode {repr(mode)}" # type: ignore[unreachable]
3485 raise ValueError(msg)
3486 elif isinstance(fp, io.StringIO):
3487 msg = ( # type: ignore[unreachable]
3488 "StringIO cannot be used to open an image. "
3489 "Binary data must be used instead."
3490 )
3491 raise ValueError(msg)
3493 if formats is None:
3494 formats = ID
3495 elif not isinstance(formats, (list, tuple)):
3496 msg = "formats must be a list or tuple" # type: ignore[unreachable]
3497 raise TypeError(msg)
3499 exclusive_fp = False
3500 filename: str | bytes = ""
3501 if is_path(fp):
3502 filename = os.fspath(fp)
3504 if filename:
3505 fp = builtins.open(filename, "rb")
3506 exclusive_fp = True
3507 else:
3508 fp = cast(IO[bytes], fp)
3510 try:
3511 fp.seek(0)
3512 except (AttributeError, io.UnsupportedOperation):
3513 fp = io.BytesIO(fp.read())
3514 exclusive_fp = True
3516 prefix = fp.read(16)
3518 preinit()
3520 warning_messages: list[str] = []
3522 def _open_core(
3523 fp: IO[bytes],
3524 filename: str | bytes,
3525 prefix: bytes,
3526 formats: list[str] | tuple[str, ...],
3527 ) -> ImageFile.ImageFile | None:
3528 for i in formats:
3529 i = i.upper()
3530 if i not in OPEN:
3531 init()
3532 try:
3533 factory, accept = OPEN[i]
3534 result = not accept or accept(prefix)
3535 if isinstance(result, str):
3536 warning_messages.append(result)
3537 elif result:
3538 fp.seek(0)
3539 im = factory(fp, filename)
3540 _decompression_bomb_check(im.size)
3541 return im
3542 except (SyntaxError, IndexError, TypeError, struct.error) as e:
3543 if WARN_POSSIBLE_FORMATS:
3544 warning_messages.append(i + " opening failed. " + str(e))
3545 except BaseException:
3546 if exclusive_fp:
3547 fp.close()
3548 raise
3549 return None
3551 im = _open_core(fp, filename, prefix, formats)
3553 if im is None and formats is ID:
3554 checked_formats = ID.copy()
3555 if init():
3556 im = _open_core(
3557 fp,
3558 filename,
3559 prefix,
3560 tuple(format for format in formats if format not in checked_formats),
3561 )
3563 if im:
3564 im._exclusive_fp = exclusive_fp
3565 return im
3567 if exclusive_fp:
3568 fp.close()
3569 for message in warning_messages:
3570 warnings.warn(message)
3571 msg = "cannot identify image file %r" % (filename if filename else fp)
3572 raise UnidentifiedImageError(msg)
3575#
3576# Image processing.
3579def alpha_composite(im1: Image, im2: Image) -> Image:
3580 """
3581 Alpha composite im2 over im1.
3583 :param im1: The first image. Must have mode RGBA.
3584 :param im2: The second image. Must have mode RGBA, and the same size as
3585 the first image.
3586 :returns: An :py:class:`~PIL.Image.Image` object.
3587 """
3589 im1.load()
3590 im2.load()
3591 return im1._new(core.alpha_composite(im1.im, im2.im))
3594def blend(im1: Image, im2: Image, alpha: float) -> Image:
3595 """
3596 Creates a new image by interpolating between two input images, using
3597 a constant alpha::
3599 out = image1 * (1.0 - alpha) + image2 * alpha
3601 :param im1: The first image.
3602 :param im2: The second image. Must have the same mode and size as
3603 the first image.
3604 :param alpha: The interpolation alpha factor. If alpha is 0.0, a
3605 copy of the first image is returned. If alpha is 1.0, a copy of
3606 the second image is returned. There are no restrictions on the
3607 alpha value. If necessary, the result is clipped to fit into
3608 the allowed output range.
3609 :returns: An :py:class:`~PIL.Image.Image` object.
3610 """
3612 im1.load()
3613 im2.load()
3614 return im1._new(core.blend(im1.im, im2.im, alpha))
3617def composite(image1: Image, image2: Image, mask: Image) -> Image:
3618 """
3619 Create composite image by blending images using a transparency mask.
3621 :param image1: The first image.
3622 :param image2: The second image. Must have the same mode and
3623 size as the first image.
3624 :param mask: A mask image. This image can have mode
3625 "1", "L", or "RGBA", and must have the same size as the
3626 other two images.
3627 """
3629 image = image2.copy()
3630 image.paste(image1, None, mask)
3631 return image
3634def eval(image: Image, *args: Callable[[int], float]) -> Image:
3635 """
3636 Applies the function (which should take one argument) to each pixel
3637 in the given image. If the image has more than one band, the same
3638 function is applied to each band. Note that the function is
3639 evaluated once for each possible pixel value, so you cannot use
3640 random components or other generators.
3642 :param image: The input image.
3643 :param function: A function object, taking one integer argument.
3644 :returns: An :py:class:`~PIL.Image.Image` object.
3645 """
3647 return image.point(args[0])
3650def merge(mode: str, bands: Sequence[Image]) -> Image:
3651 """
3652 Merge a set of single band images into a new multiband image.
3654 :param mode: The mode to use for the output image. See:
3655 :ref:`concept-modes`.
3656 :param bands: A sequence containing one single-band image for
3657 each band in the output image. All bands must have the
3658 same size.
3659 :returns: An :py:class:`~PIL.Image.Image` object.
3660 """
3662 if getmodebands(mode) != len(bands) or "*" in mode:
3663 msg = "wrong number of bands"
3664 raise ValueError(msg)
3665 for band in bands[1:]:
3666 if band.mode != getmodetype(mode):
3667 msg = "mode mismatch"
3668 raise ValueError(msg)
3669 if band.size != bands[0].size:
3670 msg = "size mismatch"
3671 raise ValueError(msg)
3672 for band in bands:
3673 band.load()
3674 return bands[0]._new(core.merge(mode, *[b.im for b in bands]))
3677# --------------------------------------------------------------------
3678# Plugin registry
3681def register_open(
3682 id: str,
3683 factory: (
3684 Callable[[IO[bytes], str | bytes], ImageFile.ImageFile]
3685 | type[ImageFile.ImageFile]
3686 ),
3687 accept: Callable[[bytes], bool | str] | None = None,
3688) -> None:
3689 """
3690 Register an image file plugin. This function should not be used
3691 in application code.
3693 :param id: An image format identifier.
3694 :param factory: An image file factory method.
3695 :param accept: An optional function that can be used to quickly
3696 reject images having another format.
3697 """
3698 id = id.upper()
3699 if id not in ID:
3700 ID.append(id)
3701 OPEN[id] = factory, accept
3704def register_mime(id: str, mimetype: str) -> None:
3705 """
3706 Registers an image MIME type by populating ``Image.MIME``. This function
3707 should not be used in application code.
3709 ``Image.MIME`` provides a mapping from image format identifiers to mime
3710 formats, but :py:meth:`~PIL.ImageFile.ImageFile.get_format_mimetype` can
3711 provide a different result for specific images.
3713 :param id: An image format identifier.
3714 :param mimetype: The image MIME type for this format.
3715 """
3716 MIME[id.upper()] = mimetype
3719def register_save(
3720 id: str, driver: Callable[[Image, IO[bytes], str | bytes], None]
3721) -> None:
3722 """
3723 Registers an image save function. This function should not be
3724 used in application code.
3726 :param id: An image format identifier.
3727 :param driver: A function to save images in this format.
3728 """
3729 SAVE[id.upper()] = driver
3732def register_save_all(
3733 id: str, driver: Callable[[Image, IO[bytes], str | bytes], None]
3734) -> None:
3735 """
3736 Registers an image function to save all the frames
3737 of a multiframe format. This function should not be
3738 used in application code.
3740 :param id: An image format identifier.
3741 :param driver: A function to save images in this format.
3742 """
3743 SAVE_ALL[id.upper()] = driver
3746def register_extension(id: str, extension: str) -> None:
3747 """
3748 Registers an image extension. This function should not be
3749 used in application code.
3751 :param id: An image format identifier.
3752 :param extension: An extension used for this format.
3753 """
3754 EXTENSION[extension.lower()] = id.upper()
3757def register_extensions(id: str, extensions: list[str]) -> None:
3758 """
3759 Registers image extensions. This function should not be
3760 used in application code.
3762 :param id: An image format identifier.
3763 :param extensions: A list of extensions used for this format.
3764 """
3765 for extension in extensions:
3766 register_extension(id, extension)
3769def registered_extensions() -> dict[str, str]:
3770 """
3771 Returns a dictionary containing all file extensions belonging
3772 to registered plugins
3773 """
3774 init()
3775 return EXTENSION
3778def register_decoder(name: str, decoder: type[ImageFile.PyDecoder]) -> None:
3779 """
3780 Registers an image decoder. This function should not be
3781 used in application code.
3783 :param name: The name of the decoder
3784 :param decoder: An ImageFile.PyDecoder object
3786 .. versionadded:: 4.1.0
3787 """
3788 DECODERS[name] = decoder
3791def register_encoder(name: str, encoder: type[ImageFile.PyEncoder]) -> None:
3792 """
3793 Registers an image encoder. This function should not be
3794 used in application code.
3796 :param name: The name of the encoder
3797 :param encoder: An ImageFile.PyEncoder object
3799 .. versionadded:: 4.1.0
3800 """
3801 ENCODERS[name] = encoder
3804# --------------------------------------------------------------------
3805# Simple display support.
3808def _show(image: Image, **options: Any) -> None:
3809 from . import ImageShow
3811 ImageShow.show(image, **options)
3814# --------------------------------------------------------------------
3815# Effects
3818def effect_mandelbrot(
3819 size: tuple[int, int], extent: tuple[float, float, float, float], quality: int
3820) -> Image:
3821 """
3822 Generate a Mandelbrot set covering the given extent.
3824 :param size: The requested size in pixels, as a 2-tuple:
3825 (width, height).
3826 :param extent: The extent to cover, as a 4-tuple:
3827 (x0, y0, x1, y1).
3828 :param quality: Quality.
3829 """
3830 return Image()._new(core.effect_mandelbrot(size, extent, quality))
3833def effect_noise(size: tuple[int, int], sigma: float) -> Image:
3834 """
3835 Generate Gaussian noise centered around 128.
3837 :param size: The requested size in pixels, as a 2-tuple:
3838 (width, height).
3839 :param sigma: Standard deviation of noise.
3840 """
3841 return Image()._new(core.effect_noise(size, sigma))
3844def linear_gradient(mode: str) -> Image:
3845 """
3846 Generate 256x256 linear gradient from black to white, top to bottom.
3848 :param mode: Input mode.
3849 """
3850 return Image()._new(core.linear_gradient(mode))
3853def radial_gradient(mode: str) -> Image:
3854 """
3855 Generate 256x256 radial gradient from black to white, centre to edge.
3857 :param mode: Input mode.
3858 """
3859 return Image()._new(core.radial_gradient(mode))
3862# --------------------------------------------------------------------
3863# Resources
3866def _apply_env_variables(env: dict[str, str] | None = None) -> None:
3867 env_dict = env if env is not None else os.environ
3869 for var_name, setter in [
3870 ("PILLOW_ALIGNMENT", core.set_alignment),
3871 ("PILLOW_BLOCK_SIZE", core.set_block_size),
3872 ("PILLOW_BLOCKS_MAX", core.set_blocks_max),
3873 ]:
3874 if var_name not in env_dict:
3875 continue
3877 var = env_dict[var_name].lower()
3879 units = 1
3880 for postfix, mul in [("k", 1024), ("m", 1024 * 1024)]:
3881 if var.endswith(postfix):
3882 units = mul
3883 var = var[: -len(postfix)]
3885 try:
3886 var_int = int(var) * units
3887 except ValueError:
3888 warnings.warn(f"{var_name} is not int")
3889 continue
3891 try:
3892 setter(var_int)
3893 except ValueError as e:
3894 warnings.warn(f"{var_name}: {e}")
3897_apply_env_variables()
3898atexit.register(core.clear_cache)
3901if TYPE_CHECKING:
3902 _ExifBase = MutableMapping[int, Any]
3903else:
3904 _ExifBase = MutableMapping
3907class Exif(_ExifBase):
3908 """
3909 This class provides read and write access to EXIF image data::
3911 from PIL import Image
3912 im = Image.open("exif.png")
3913 exif = im.getexif() # Returns an instance of this class
3915 Information can be read and written, iterated over or deleted::
3917 print(exif[274]) # 1
3918 exif[274] = 2
3919 for k, v in exif.items():
3920 print("Tag", k, "Value", v) # Tag 274 Value 2
3921 del exif[274]
3923 To access information beyond IFD0, :py:meth:`~PIL.Image.Exif.get_ifd`
3924 returns a dictionary::
3926 from PIL import ExifTags
3927 im = Image.open("exif_gps.jpg")
3928 exif = im.getexif()
3929 gps_ifd = exif.get_ifd(ExifTags.IFD.GPSInfo)
3930 print(gps_ifd)
3932 Other IFDs include ``ExifTags.IFD.Exif``, ``ExifTags.IFD.MakerNote``,
3933 ``ExifTags.IFD.Interop`` and ``ExifTags.IFD.IFD1``.
3935 :py:mod:`~PIL.ExifTags` also has enum classes to provide names for data::
3937 print(exif[ExifTags.Base.Software]) # PIL
3938 print(gps_ifd[ExifTags.GPS.GPSDateStamp]) # 1999:99:99 99:99:99
3939 """
3941 endian: str | None = None
3942 bigtiff = False
3943 _loaded = False
3945 def __init__(self) -> None:
3946 self._data: dict[int, Any] = {}
3947 self._hidden_data: dict[int, Any] = {}
3948 self._ifds: dict[int, dict[int, Any]] = {}
3949 self._info: TiffImagePlugin.ImageFileDirectory_v2 | None = None
3950 self._loaded_exif: bytes | None = None
3952 def _fixup(self, value: Any) -> Any:
3953 try:
3954 if len(value) == 1 and isinstance(value, tuple):
3955 return value[0]
3956 except Exception:
3957 pass
3958 return value
3960 def _fixup_dict(self, src_dict: dict[int, Any]) -> dict[int, Any]:
3961 # Helper function
3962 # returns a dict with any single item tuples/lists as individual values
3963 return {k: self._fixup(v) for k, v in src_dict.items()}
3965 def _get_ifd_dict(
3966 self, offset: int, group: int | None = None
3967 ) -> dict[int, Any] | None:
3968 try:
3969 # an offset pointer to the location of the nested embedded IFD.
3970 # It should be a long, but may be corrupted.
3971 self.fp.seek(offset)
3972 except (KeyError, TypeError):
3973 return None
3974 else:
3975 from . import TiffImagePlugin
3977 info = TiffImagePlugin.ImageFileDirectory_v2(self.head, group=group)
3978 info.load(self.fp)
3979 return self._fixup_dict(dict(info))
3981 def _get_head(self) -> bytes:
3982 version = b"\x2b" if self.bigtiff else b"\x2a"
3983 if self.endian == "<":
3984 head = b"II" + version + b"\x00" + o32le(8)
3985 else:
3986 head = b"MM\x00" + version + o32be(8)
3987 if self.bigtiff:
3988 head += o32le(8) if self.endian == "<" else o32be(8)
3989 head += b"\x00\x00\x00\x00"
3990 return head
3992 def load(self, data: bytes) -> None:
3993 # Extract EXIF information. This is highly experimental,
3994 # and is likely to be replaced with something better in a future
3995 # version.
3997 # The EXIF record consists of a TIFF file embedded in a JPEG
3998 # application marker (!).
3999 if data == self._loaded_exif:
4000 return
4001 self._loaded_exif = data
4002 self._data.clear()
4003 self._hidden_data.clear()
4004 self._ifds.clear()
4005 while data and data.startswith(b"Exif\x00\x00"):
4006 data = data[6:]
4007 if not data:
4008 self._info = None
4009 return
4011 self.fp: IO[bytes] = io.BytesIO(data)
4012 self.head = self.fp.read(8)
4013 # process dictionary
4014 from . import TiffImagePlugin
4016 self._info = TiffImagePlugin.ImageFileDirectory_v2(self.head)
4017 self.endian = self._info._endian
4018 self.fp.seek(self._info.next)
4019 self._info.load(self.fp)
4021 def load_from_fp(self, fp: IO[bytes], offset: int | None = None) -> None:
4022 self._loaded_exif = None
4023 self._data.clear()
4024 self._hidden_data.clear()
4025 self._ifds.clear()
4027 # process dictionary
4028 from . import TiffImagePlugin
4030 self.fp = fp
4031 if offset is not None:
4032 self.head = self._get_head()
4033 else:
4034 self.head = self.fp.read(8)
4035 self._info = TiffImagePlugin.ImageFileDirectory_v2(self.head)
4036 if self.endian is None:
4037 self.endian = self._info._endian
4038 if offset is None:
4039 offset = self._info.next
4040 self.fp.tell()
4041 self.fp.seek(offset)
4042 self._info.load(self.fp)
4044 def _get_merged_dict(self) -> dict[int, Any]:
4045 merged_dict = dict(self)
4047 # get EXIF extension
4048 if ExifTags.IFD.Exif in self:
4049 ifd = self._get_ifd_dict(self[ExifTags.IFD.Exif], ExifTags.IFD.Exif)
4050 if ifd:
4051 merged_dict.update(ifd)
4053 # GPS
4054 if ExifTags.IFD.GPSInfo in self:
4055 merged_dict[ExifTags.IFD.GPSInfo] = self._get_ifd_dict(
4056 self[ExifTags.IFD.GPSInfo], ExifTags.IFD.GPSInfo
4057 )
4059 return merged_dict
4061 def tobytes(self, offset: int = 8) -> bytes:
4062 from . import TiffImagePlugin
4064 head = self._get_head()
4065 ifd = TiffImagePlugin.ImageFileDirectory_v2(ifh=head)
4066 for tag, ifd_dict in self._ifds.items():
4067 if tag not in self:
4068 ifd[tag] = ifd_dict
4069 for tag, value in self.items():
4070 if tag in [
4071 ExifTags.IFD.Exif,
4072 ExifTags.IFD.GPSInfo,
4073 ] and not isinstance(value, dict):
4074 value = self.get_ifd(tag)
4075 if (
4076 tag == ExifTags.IFD.Exif
4077 and ExifTags.IFD.Interop in value
4078 and not isinstance(value[ExifTags.IFD.Interop], dict)
4079 ):
4080 value = value.copy()
4081 value[ExifTags.IFD.Interop] = self.get_ifd(ExifTags.IFD.Interop)
4082 ifd[tag] = value
4083 return b"Exif\x00\x00" + head + ifd.tobytes(offset)
4085 def get_ifd(self, tag: int) -> dict[int, Any]:
4086 if tag not in self._ifds:
4087 if tag == ExifTags.IFD.IFD1:
4088 if self._info is not None and self._info.next != 0:
4089 ifd = self._get_ifd_dict(self._info.next)
4090 if ifd is not None:
4091 self._ifds[tag] = ifd
4092 elif tag in [ExifTags.IFD.Exif, ExifTags.IFD.GPSInfo]:
4093 offset = self._hidden_data.get(tag, self.get(tag))
4094 if offset is not None:
4095 ifd = self._get_ifd_dict(offset, tag)
4096 if ifd is not None:
4097 self._ifds[tag] = ifd
4098 elif tag in [ExifTags.IFD.Interop, ExifTags.IFD.MakerNote]:
4099 if ExifTags.IFD.Exif not in self._ifds:
4100 self.get_ifd(ExifTags.IFD.Exif)
4101 tag_data = self._ifds[ExifTags.IFD.Exif][tag]
4102 if tag == ExifTags.IFD.MakerNote:
4103 from .TiffImagePlugin import ImageFileDirectory_v2
4105 if tag_data.startswith(b"FUJIFILM"):
4106 ifd_offset = i32le(tag_data, 8)
4107 ifd_data = tag_data[ifd_offset:]
4109 makernote = {}
4110 for i in range(struct.unpack("<H", ifd_data[:2])[0]):
4111 ifd_tag, typ, count, data = struct.unpack(
4112 "<HHL4s", ifd_data[i * 12 + 2 : (i + 1) * 12 + 2]
4113 )
4114 try:
4115 (
4116 unit_size,
4117 handler,
4118 ) = ImageFileDirectory_v2._load_dispatch[typ]
4119 except KeyError:
4120 continue
4121 size = count * unit_size
4122 if size > 4:
4123 (offset,) = struct.unpack("<L", data)
4124 data = ifd_data[offset - 12 : offset + size - 12]
4125 else:
4126 data = data[:size]
4128 if len(data) != size:
4129 warnings.warn(
4130 "Possibly corrupt EXIF MakerNote data. "
4131 f"Expecting to read {size} bytes but only got "
4132 f"{len(data)}. Skipping tag {ifd_tag}"
4133 )
4134 continue
4136 if not data:
4137 continue
4139 makernote[ifd_tag] = handler(
4140 ImageFileDirectory_v2(), data, False
4141 )
4142 self._ifds[tag] = dict(self._fixup_dict(makernote))
4143 elif self.get(0x010F) == "Nintendo":
4144 makernote = {}
4145 for i in range(struct.unpack(">H", tag_data[:2])[0]):
4146 ifd_tag, typ, count, data = struct.unpack(
4147 ">HHL4s", tag_data[i * 12 + 2 : (i + 1) * 12 + 2]
4148 )
4149 if ifd_tag == 0x1101:
4150 # CameraInfo
4151 (offset,) = struct.unpack(">L", data)
4152 self.fp.seek(offset)
4154 camerainfo: dict[str, int | bytes] = {
4155 "ModelID": self.fp.read(4)
4156 }
4158 self.fp.read(4)
4159 # Seconds since 2000
4160 camerainfo["TimeStamp"] = i32le(self.fp.read(12))
4162 self.fp.read(4)
4163 camerainfo["InternalSerialNumber"] = self.fp.read(4)
4165 self.fp.read(12)
4166 parallax = self.fp.read(4)
4167 handler = ImageFileDirectory_v2._load_dispatch[
4168 TiffTags.FLOAT
4169 ][1]
4170 camerainfo["Parallax"] = handler(
4171 ImageFileDirectory_v2(), parallax, False
4172 )[0]
4174 self.fp.read(4)
4175 camerainfo["Category"] = self.fp.read(2)
4177 makernote = {0x1101: camerainfo}
4178 self._ifds[tag] = makernote
4179 else:
4180 # Interop
4181 ifd = self._get_ifd_dict(tag_data, tag)
4182 if ifd is not None:
4183 self._ifds[tag] = ifd
4184 ifd = self._ifds.setdefault(tag, {})
4185 if tag == ExifTags.IFD.Exif and self._hidden_data:
4186 ifd = {
4187 k: v
4188 for (k, v) in ifd.items()
4189 if k not in (ExifTags.IFD.Interop, ExifTags.IFD.MakerNote)
4190 }
4191 return ifd
4193 def hide_offsets(self) -> None:
4194 for tag in (ExifTags.IFD.Exif, ExifTags.IFD.GPSInfo):
4195 if tag in self:
4196 self._hidden_data[tag] = self[tag]
4197 del self[tag]
4199 def __str__(self) -> str:
4200 if self._info is not None:
4201 # Load all keys into self._data
4202 for tag in self._info:
4203 self[tag]
4205 return str(self._data)
4207 def __len__(self) -> int:
4208 keys = set(self._data)
4209 if self._info is not None:
4210 keys.update(self._info)
4211 return len(keys)
4213 def __getitem__(self, tag: int) -> Any:
4214 if self._info is not None and tag not in self._data and tag in self._info:
4215 self._data[tag] = self._fixup(self._info[tag])
4216 del self._info[tag]
4217 return self._data[tag]
4219 def __contains__(self, tag: object) -> bool:
4220 return tag in self._data or (self._info is not None and tag in self._info)
4222 def __setitem__(self, tag: int, value: Any) -> None:
4223 if self._info is not None and tag in self._info:
4224 del self._info[tag]
4225 self._data[tag] = value
4227 def __delitem__(self, tag: int) -> None:
4228 if self._info is not None and tag in self._info:
4229 del self._info[tag]
4230 else:
4231 del self._data[tag]
4233 def __iter__(self) -> Iterator[int]:
4234 keys = set(self._data)
4235 if self._info is not None:
4236 keys.update(self._info)
4237 return iter(keys)