Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/PIL/Image.py: 44%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
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 raw image data derived from Pillow's internal
771 storage. For compressed image data (e.g. PNG, JPEG) use
772 :meth:`~.save`, with a BytesIO parameter for in-memory data.
774 :param encoder_name: What encoder to use.
776 The default is to use the standard "raw" encoder.
777 To see how this packs pixel data into the returned
778 bytes, see :file:`libImaging/Pack.c`.
780 A list of C encoders can be seen under codecs
781 section of the function array in
782 :file:`_imaging.c`. Python encoders are registered
783 within the relevant plugins.
784 :param args: Extra arguments to the encoder.
785 :returns: A :py:class:`bytes` object.
786 """
788 encoder_args: Any = args
789 if len(encoder_args) == 1 and isinstance(encoder_args[0], tuple):
790 # may pass tuple instead of argument list
791 encoder_args = encoder_args[0]
793 if encoder_name == "raw" and encoder_args == ():
794 encoder_args = self.mode
796 self.load()
798 if self.width == 0 or self.height == 0:
799 return b""
801 # unpack data
802 e = _getencoder(self.mode, encoder_name, encoder_args)
803 e.setimage(self.im)
805 from . import ImageFile
807 bufsize = max(ImageFile.MAXBLOCK, self.size[0] * 4) # see RawEncode.c
809 output = []
810 while True:
811 bytes_consumed, errcode, data = e.encode(bufsize)
812 output.append(data)
813 if errcode:
814 break
815 if errcode < 0:
816 msg = f"encoder error {errcode} in tobytes"
817 raise RuntimeError(msg)
819 return b"".join(output)
821 def tobitmap(self, name: str = "image") -> bytes:
822 """
823 Returns the image converted to an X11 bitmap.
825 .. note:: This method only works for mode "1" images.
827 :param name: The name prefix to use for the bitmap variables.
828 :returns: A string containing an X11 bitmap.
829 :raises ValueError: If the mode is not "1"
830 """
832 self.load()
833 if self.mode != "1":
834 msg = "not a bitmap"
835 raise ValueError(msg)
836 data = self.tobytes("xbm")
837 return b"".join(
838 [
839 f"#define {name}_width {self.size[0]}\n".encode("ascii"),
840 f"#define {name}_height {self.size[1]}\n".encode("ascii"),
841 f"static char {name}_bits[] = {{\n".encode("ascii"),
842 data,
843 b"};",
844 ]
845 )
847 def frombytes(
848 self,
849 data: bytes | bytearray | SupportsArrayInterface,
850 decoder_name: str = "raw",
851 *args: Any,
852 ) -> None:
853 """
854 Loads this image with pixel data from a bytes object.
856 This method is similar to the :py:func:`~PIL.Image.frombytes` function,
857 but loads data into this image instead of creating a new image object.
858 """
860 if self.width == 0 or self.height == 0:
861 return
863 decoder_args: Any = args
864 if len(decoder_args) == 1 and isinstance(decoder_args[0], tuple):
865 # may pass tuple instead of argument list
866 decoder_args = decoder_args[0]
868 # default format
869 if decoder_name == "raw" and decoder_args == ():
870 decoder_args = self.mode
872 # unpack data
873 d = _getdecoder(self.mode, decoder_name, decoder_args)
874 d.setimage(self.im)
875 s = d.decode(data)
877 if s[0] >= 0:
878 msg = "not enough image data"
879 raise ValueError(msg)
880 if s[1] != 0:
881 msg = "cannot decode image data"
882 raise ValueError(msg)
884 def load(self) -> core.PixelAccess | None:
885 """
886 Allocates storage for the image and loads the pixel data. In
887 normal cases, you don't need to call this method, since the
888 Image class automatically loads an opened image when it is
889 accessed for the first time.
891 If the file associated with the image was opened by Pillow, then this
892 method will close it. The exception to this is if the image has
893 multiple frames, in which case the file will be left open for seek
894 operations. See :ref:`file-handling` for more information.
896 :returns: An image access object.
897 :rtype: :py:class:`.PixelAccess`
898 """
899 if self._im is not None and self.palette and self.palette.dirty:
900 # realize palette
901 mode, arr = self.palette.getdata()
902 self.im.putpalette(self.palette.mode, mode, arr)
903 self.palette.dirty = 0
904 self.palette.rawmode = None
905 if "transparency" in self.info and mode in ("LA", "PA"):
906 if isinstance(self.info["transparency"], int):
907 self.im.putpalettealpha(self.info["transparency"], 0)
908 else:
909 self.im.putpalettealphas(self.info["transparency"])
910 self.palette.mode = "RGBA"
911 else:
912 self.palette.palette = self.im.getpalette(
913 self.palette.mode, self.palette.mode
914 )
916 if self._im is not None:
917 return self.im.pixel_access(self.readonly)
918 return None
920 def verify(self) -> None:
921 """
922 Verifies the contents of a file. For data read from a file, this
923 method attempts to determine if the file is broken, without
924 actually decoding the image data. If this method finds any
925 problems, it raises suitable exceptions. If you need to load
926 the image after using this method, you must reopen the image
927 file.
928 """
929 pass
931 def convert(
932 self,
933 mode: str | None = None,
934 matrix: tuple[float, ...] | None = None,
935 dither: Dither | None = None,
936 palette: Palette = Palette.WEB,
937 colors: int = 256,
938 ) -> Image:
939 """
940 Returns a converted copy of this image. For the "P" mode, this
941 method translates pixels through the palette. If mode is
942 omitted, a mode is chosen so that all information in the image
943 and the palette can be represented without a palette.
945 This supports all possible conversions between "L", "RGB" and "CMYK". The
946 ``matrix`` argument only supports "L" and "RGB".
948 When translating a color image to grayscale (mode "L"),
949 the library uses the ITU-R 601-2 luma transform::
951 L = R * 299/1000 + G * 587/1000 + B * 114/1000
953 The default method of converting a grayscale ("L") or "RGB"
954 image into a bilevel (mode "1") image uses Floyd-Steinberg
955 dither to approximate the original image luminosity levels. If
956 dither is ``None``, all values larger than 127 are set to 255 (white),
957 all other values to 0 (black). To use other thresholds, use the
958 :py:meth:`~PIL.Image.Image.point` method.
960 When converting from "RGBA" to "P" without a ``matrix`` argument,
961 this passes the operation to :py:meth:`~PIL.Image.Image.quantize`,
962 and ``dither`` and ``palette`` are ignored.
964 When converting from "PA", if an "RGBA" palette is present, the alpha
965 channel from the image will be used instead of the values from the palette.
967 :param mode: The requested mode. See: :ref:`concept-modes`.
968 :param matrix: An optional conversion matrix. If given, this
969 should be 4- or 12-tuple containing floating point values.
970 :param dither: Dithering method, used when converting from
971 mode "RGB" to "P" or from "RGB" or "L" to "1".
972 Available methods are :data:`Dither.NONE` or :data:`Dither.FLOYDSTEINBERG`
973 (default). Note that this is not used when ``matrix`` is supplied.
974 :param palette: Palette to use when converting from mode "RGB"
975 to "P". Available palettes are :data:`Palette.WEB` or
976 :data:`Palette.ADAPTIVE`.
977 :param colors: Number of colors to use for the :data:`Palette.ADAPTIVE`
978 palette. Defaults to 256.
979 :rtype: :py:class:`~PIL.Image.Image`
980 :returns: An :py:class:`~PIL.Image.Image` object.
981 """
983 if mode in ("BGR;15", "BGR;16", "BGR;24"):
984 deprecate(mode, 12)
986 self.load()
988 has_transparency = "transparency" in self.info
989 if not mode and self.mode == "P":
990 # determine default mode
991 if self.palette:
992 mode = self.palette.mode
993 else:
994 mode = "RGB"
995 if mode == "RGB" and has_transparency:
996 mode = "RGBA"
997 if not mode or (mode == self.mode and not matrix):
998 return self.copy()
1000 if matrix:
1001 # matrix conversion
1002 if mode not in ("L", "RGB"):
1003 msg = "illegal conversion"
1004 raise ValueError(msg)
1005 im = self.im.convert_matrix(mode, matrix)
1006 new_im = self._new(im)
1007 if has_transparency and self.im.bands == 3:
1008 transparency = new_im.info["transparency"]
1010 def convert_transparency(
1011 m: tuple[float, ...], v: tuple[int, int, int]
1012 ) -> int:
1013 value = m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3] * 0.5
1014 return max(0, min(255, int(value)))
1016 if mode == "L":
1017 transparency = convert_transparency(matrix, transparency)
1018 elif len(mode) == 3:
1019 transparency = tuple(
1020 convert_transparency(matrix[i * 4 : i * 4 + 4], transparency)
1021 for i in range(len(transparency))
1022 )
1023 new_im.info["transparency"] = transparency
1024 return new_im
1026 if mode == "P" and self.mode == "RGBA":
1027 return self.quantize(colors)
1029 trns = None
1030 delete_trns = False
1031 # transparency handling
1032 if has_transparency:
1033 if (self.mode in ("1", "L", "I", "I;16") and mode in ("LA", "RGBA")) or (
1034 self.mode == "RGB" and mode in ("La", "LA", "RGBa", "RGBA")
1035 ):
1036 # Use transparent conversion to promote from transparent
1037 # color to an alpha channel.
1038 new_im = self._new(
1039 self.im.convert_transparent(mode, self.info["transparency"])
1040 )
1041 del new_im.info["transparency"]
1042 return new_im
1043 elif self.mode in ("L", "RGB", "P") and mode in ("L", "RGB", "P"):
1044 t = self.info["transparency"]
1045 if isinstance(t, bytes):
1046 # Dragons. This can't be represented by a single color
1047 warnings.warn(
1048 "Palette images with Transparency expressed in bytes should be "
1049 "converted to RGBA images"
1050 )
1051 delete_trns = True
1052 else:
1053 # get the new transparency color.
1054 # use existing conversions
1055 trns_im = new(self.mode, (1, 1))
1056 if self.mode == "P":
1057 assert self.palette is not None
1058 trns_im.putpalette(self.palette, self.palette.mode)
1059 if isinstance(t, tuple):
1060 err = "Couldn't allocate a palette color for transparency"
1061 assert trns_im.palette is not None
1062 try:
1063 t = trns_im.palette.getcolor(t, self)
1064 except ValueError as e:
1065 if str(e) == "cannot allocate more than 256 colors":
1066 # If all 256 colors are in use,
1067 # then there is no need for transparency
1068 t = None
1069 else:
1070 raise ValueError(err) from e
1071 if t is None:
1072 trns = None
1073 else:
1074 trns_im.putpixel((0, 0), t)
1076 if mode in ("L", "RGB"):
1077 trns_im = trns_im.convert(mode)
1078 else:
1079 # can't just retrieve the palette number, got to do it
1080 # after quantization.
1081 trns_im = trns_im.convert("RGB")
1082 trns = trns_im.getpixel((0, 0))
1084 elif self.mode == "P" and mode in ("LA", "PA", "RGBA"):
1085 t = self.info["transparency"]
1086 delete_trns = True
1088 if isinstance(t, bytes):
1089 self.im.putpalettealphas(t)
1090 elif isinstance(t, int):
1091 self.im.putpalettealpha(t, 0)
1092 else:
1093 msg = "Transparency for P mode should be bytes or int"
1094 raise ValueError(msg)
1096 if mode == "P" and palette == Palette.ADAPTIVE:
1097 im = self.im.quantize(colors)
1098 new_im = self._new(im)
1099 from . import ImagePalette
1101 new_im.palette = ImagePalette.ImagePalette(
1102 "RGB", new_im.im.getpalette("RGB")
1103 )
1104 if delete_trns:
1105 # This could possibly happen if we requantize to fewer colors.
1106 # The transparency would be totally off in that case.
1107 del new_im.info["transparency"]
1108 if trns is not None:
1109 try:
1110 new_im.info["transparency"] = new_im.palette.getcolor(
1111 cast(tuple[int, ...], trns), # trns was converted to RGB
1112 new_im,
1113 )
1114 except Exception:
1115 # if we can't make a transparent color, don't leave the old
1116 # transparency hanging around to mess us up.
1117 del new_im.info["transparency"]
1118 warnings.warn("Couldn't allocate palette entry for transparency")
1119 return new_im
1121 if "LAB" in (self.mode, mode):
1122 im = self
1123 if mode == "LAB":
1124 if im.mode not in ("RGB", "RGBA", "RGBX"):
1125 im = im.convert("RGBA")
1126 other_mode = im.mode
1127 else:
1128 other_mode = mode
1129 if other_mode in ("RGB", "RGBA", "RGBX"):
1130 from . import ImageCms
1132 srgb = ImageCms.createProfile("sRGB")
1133 lab = ImageCms.createProfile("LAB")
1134 profiles = [lab, srgb] if im.mode == "LAB" else [srgb, lab]
1135 transform = ImageCms.buildTransform(
1136 profiles[0], profiles[1], im.mode, mode
1137 )
1138 return transform.apply(im)
1140 # colorspace conversion
1141 if dither is None:
1142 dither = Dither.FLOYDSTEINBERG
1144 try:
1145 im = self.im.convert(mode, dither)
1146 except ValueError:
1147 try:
1148 # normalize source image and try again
1149 modebase = getmodebase(self.mode)
1150 if modebase == self.mode:
1151 raise
1152 im = self.im.convert(modebase)
1153 im = im.convert(mode, dither)
1154 except KeyError as e:
1155 msg = "illegal conversion"
1156 raise ValueError(msg) from e
1158 new_im = self._new(im)
1159 if mode == "P" and palette != Palette.ADAPTIVE:
1160 from . import ImagePalette
1162 new_im.palette = ImagePalette.ImagePalette("RGB", im.getpalette("RGB"))
1163 if delete_trns:
1164 # crash fail if we leave a bytes transparency in an rgb/l mode.
1165 del new_im.info["transparency"]
1166 if trns is not None:
1167 if new_im.mode == "P" and new_im.palette:
1168 try:
1169 new_im.info["transparency"] = new_im.palette.getcolor(
1170 cast(tuple[int, ...], trns), new_im # trns was converted to RGB
1171 )
1172 except ValueError as e:
1173 del new_im.info["transparency"]
1174 if str(e) != "cannot allocate more than 256 colors":
1175 # If all 256 colors are in use,
1176 # then there is no need for transparency
1177 warnings.warn(
1178 "Couldn't allocate palette entry for transparency"
1179 )
1180 else:
1181 new_im.info["transparency"] = trns
1182 return new_im
1184 def quantize(
1185 self,
1186 colors: int = 256,
1187 method: int | None = None,
1188 kmeans: int = 0,
1189 palette: Image | None = None,
1190 dither: Dither = Dither.FLOYDSTEINBERG,
1191 ) -> Image:
1192 """
1193 Convert the image to 'P' mode with the specified number
1194 of colors.
1196 :param colors: The desired number of colors, <= 256
1197 :param method: :data:`Quantize.MEDIANCUT` (median cut),
1198 :data:`Quantize.MAXCOVERAGE` (maximum coverage),
1199 :data:`Quantize.FASTOCTREE` (fast octree),
1200 :data:`Quantize.LIBIMAGEQUANT` (libimagequant; check support
1201 using :py:func:`PIL.features.check_feature` with
1202 ``feature="libimagequant"``).
1204 By default, :data:`Quantize.MEDIANCUT` will be used.
1206 The exception to this is RGBA images. :data:`Quantize.MEDIANCUT`
1207 and :data:`Quantize.MAXCOVERAGE` do not support RGBA images, so
1208 :data:`Quantize.FASTOCTREE` is used by default instead.
1209 :param kmeans: Integer greater than or equal to zero.
1210 :param palette: Quantize to the palette of given
1211 :py:class:`PIL.Image.Image`.
1212 :param dither: Dithering method, used when converting from
1213 mode "RGB" to "P" or from "RGB" or "L" to "1".
1214 Available methods are :data:`Dither.NONE` or :data:`Dither.FLOYDSTEINBERG`
1215 (default).
1216 :returns: A new image
1217 """
1219 self.load()
1221 if method is None:
1222 # defaults:
1223 method = Quantize.MEDIANCUT
1224 if self.mode == "RGBA":
1225 method = Quantize.FASTOCTREE
1227 if self.mode == "RGBA" and method not in (
1228 Quantize.FASTOCTREE,
1229 Quantize.LIBIMAGEQUANT,
1230 ):
1231 # Caller specified an invalid mode.
1232 msg = (
1233 "Fast Octree (method == 2) and libimagequant (method == 3) "
1234 "are the only valid methods for quantizing RGBA images"
1235 )
1236 raise ValueError(msg)
1238 if palette:
1239 # use palette from reference image
1240 palette.load()
1241 if palette.mode != "P":
1242 msg = "bad mode for palette image"
1243 raise ValueError(msg)
1244 if self.mode not in {"RGB", "L"}:
1245 msg = "only RGB or L mode images can be quantized to a palette"
1246 raise ValueError(msg)
1247 im = self.im.convert("P", dither, palette.im)
1248 new_im = self._new(im)
1249 assert palette.palette is not None
1250 new_im.palette = palette.palette.copy()
1251 return new_im
1253 if kmeans < 0:
1254 msg = "kmeans must not be negative"
1255 raise ValueError(msg)
1257 im = self._new(self.im.quantize(colors, method, kmeans))
1259 from . import ImagePalette
1261 mode = im.im.getpalettemode()
1262 palette_data = im.im.getpalette(mode, mode)[: colors * len(mode)]
1263 im.palette = ImagePalette.ImagePalette(mode, palette_data)
1265 return im
1267 def copy(self) -> Image:
1268 """
1269 Copies this image. Use this method if you wish to paste things
1270 into an image, but still retain the original.
1272 :rtype: :py:class:`~PIL.Image.Image`
1273 :returns: An :py:class:`~PIL.Image.Image` object.
1274 """
1275 self.load()
1276 return self._new(self.im.copy())
1278 __copy__ = copy
1280 def crop(self, box: tuple[float, float, float, float] | None = None) -> Image:
1281 """
1282 Returns a rectangular region from this image. The box is a
1283 4-tuple defining the left, upper, right, and lower pixel
1284 coordinate. See :ref:`coordinate-system`.
1286 Note: Prior to Pillow 3.4.0, this was a lazy operation.
1288 :param box: The crop rectangle, as a (left, upper, right, lower)-tuple.
1289 :rtype: :py:class:`~PIL.Image.Image`
1290 :returns: An :py:class:`~PIL.Image.Image` object.
1291 """
1293 if box is None:
1294 return self.copy()
1296 if box[2] < box[0]:
1297 msg = "Coordinate 'right' is less than 'left'"
1298 raise ValueError(msg)
1299 elif box[3] < box[1]:
1300 msg = "Coordinate 'lower' is less than 'upper'"
1301 raise ValueError(msg)
1303 self.load()
1304 return self._new(self._crop(self.im, box))
1306 def _crop(
1307 self, im: core.ImagingCore, box: tuple[float, float, float, float]
1308 ) -> core.ImagingCore:
1309 """
1310 Returns a rectangular region from the core image object im.
1312 This is equivalent to calling im.crop((x0, y0, x1, y1)), but
1313 includes additional sanity checks.
1315 :param im: a core image object
1316 :param box: The crop rectangle, as a (left, upper, right, lower)-tuple.
1317 :returns: A core image object.
1318 """
1320 x0, y0, x1, y1 = map(int, map(round, box))
1322 absolute_values = (abs(x1 - x0), abs(y1 - y0))
1324 _decompression_bomb_check(absolute_values)
1326 return im.crop((x0, y0, x1, y1))
1328 def draft(
1329 self, mode: str | None, size: tuple[int, int] | None
1330 ) -> tuple[str, tuple[int, int, float, float]] | None:
1331 """
1332 Configures the image file loader so it returns a version of the
1333 image that as closely as possible matches the given mode and
1334 size. For example, you can use this method to convert a color
1335 JPEG to grayscale while loading it.
1337 If any changes are made, returns a tuple with the chosen ``mode`` and
1338 ``box`` with coordinates of the original image within the altered one.
1340 Note that this method modifies the :py:class:`~PIL.Image.Image` object
1341 in place. If the image has already been loaded, this method has no
1342 effect.
1344 Note: This method is not implemented for most images. It is
1345 currently implemented only for JPEG and MPO images.
1347 :param mode: The requested mode.
1348 :param size: The requested size in pixels, as a 2-tuple:
1349 (width, height).
1350 """
1351 pass
1353 def _expand(self, xmargin: int, ymargin: int | None = None) -> Image:
1354 if ymargin is None:
1355 ymargin = xmargin
1356 self.load()
1357 return self._new(self.im.expand(xmargin, ymargin))
1359 def filter(self, filter: ImageFilter.Filter | type[ImageFilter.Filter]) -> Image:
1360 """
1361 Filters this image using the given filter. For a list of
1362 available filters, see the :py:mod:`~PIL.ImageFilter` module.
1364 :param filter: Filter kernel.
1365 :returns: An :py:class:`~PIL.Image.Image` object."""
1367 from . import ImageFilter
1369 self.load()
1371 if callable(filter):
1372 filter = filter()
1373 if not hasattr(filter, "filter"):
1374 msg = "filter argument should be ImageFilter.Filter instance or class"
1375 raise TypeError(msg)
1377 multiband = isinstance(filter, ImageFilter.MultibandFilter)
1378 if self.im.bands == 1 or multiband:
1379 return self._new(filter.filter(self.im))
1381 ims = [
1382 self._new(filter.filter(self.im.getband(c))) for c in range(self.im.bands)
1383 ]
1384 return merge(self.mode, ims)
1386 def getbands(self) -> tuple[str, ...]:
1387 """
1388 Returns a tuple containing the name of each band in this image.
1389 For example, ``getbands`` on an RGB image returns ("R", "G", "B").
1391 :returns: A tuple containing band names.
1392 :rtype: tuple
1393 """
1394 return ImageMode.getmode(self.mode).bands
1396 def getbbox(self, *, alpha_only: bool = True) -> tuple[int, int, int, int] | None:
1397 """
1398 Calculates the bounding box of the non-zero regions in the
1399 image.
1401 :param alpha_only: Optional flag, defaulting to ``True``.
1402 If ``True`` and the image has an alpha channel, trim transparent pixels.
1403 Otherwise, trim pixels when all channels are zero.
1404 Keyword-only argument.
1405 :returns: The bounding box is returned as a 4-tuple defining the
1406 left, upper, right, and lower pixel coordinate. See
1407 :ref:`coordinate-system`. If the image is completely empty, this
1408 method returns None.
1410 """
1412 self.load()
1413 return self.im.getbbox(alpha_only)
1415 def getcolors(
1416 self, maxcolors: int = 256
1417 ) -> list[tuple[int, tuple[int, ...]]] | list[tuple[int, float]] | None:
1418 """
1419 Returns a list of colors used in this image.
1421 The colors will be in the image's mode. For example, an RGB image will
1422 return a tuple of (red, green, blue) color values, and a P image will
1423 return the index of the color in the palette.
1425 :param maxcolors: Maximum number of colors. If this number is
1426 exceeded, this method returns None. The default limit is
1427 256 colors.
1428 :returns: An unsorted list of (count, pixel) values.
1429 """
1431 self.load()
1432 if self.mode in ("1", "L", "P"):
1433 h = self.im.histogram()
1434 out: list[tuple[int, float]] = [(h[i], i) for i in range(256) if h[i]]
1435 if len(out) > maxcolors:
1436 return None
1437 return out
1438 return self.im.getcolors(maxcolors)
1440 def getdata(self, band: int | None = None) -> core.ImagingCore:
1441 """
1442 Returns the contents of this image as a sequence object
1443 containing pixel values. The sequence object is flattened, so
1444 that values for line one follow directly after the values of
1445 line zero, and so on.
1447 Note that the sequence object returned by this method is an
1448 internal PIL data type, which only supports certain sequence
1449 operations. To convert it to an ordinary sequence (e.g. for
1450 printing), use ``list(im.getdata())``.
1452 :param band: What band to return. The default is to return
1453 all bands. To return a single band, pass in the index
1454 value (e.g. 0 to get the "R" band from an "RGB" image).
1455 :returns: A sequence-like object.
1456 """
1458 self.load()
1459 if band is not None:
1460 return self.im.getband(band)
1461 return self.im # could be abused
1463 def getextrema(self) -> tuple[float, float] | tuple[tuple[int, int], ...]:
1464 """
1465 Gets the minimum and maximum pixel values for each band in
1466 the image.
1468 :returns: For a single-band image, a 2-tuple containing the
1469 minimum and maximum pixel value. For a multi-band image,
1470 a tuple containing one 2-tuple for each band.
1471 """
1473 self.load()
1474 if self.im.bands > 1:
1475 return tuple(self.im.getband(i).getextrema() for i in range(self.im.bands))
1476 return self.im.getextrema()
1478 def getxmp(self) -> dict[str, Any]:
1479 """
1480 Returns a dictionary containing the XMP tags.
1481 Requires defusedxml to be installed.
1483 :returns: XMP tags in a dictionary.
1484 """
1486 def get_name(tag: str) -> str:
1487 return re.sub("^{[^}]+}", "", tag)
1489 def get_value(element: Element) -> str | dict[str, Any] | None:
1490 value: dict[str, Any] = {get_name(k): v for k, v in element.attrib.items()}
1491 children = list(element)
1492 if children:
1493 for child in children:
1494 name = get_name(child.tag)
1495 child_value = get_value(child)
1496 if name in value:
1497 if not isinstance(value[name], list):
1498 value[name] = [value[name]]
1499 value[name].append(child_value)
1500 else:
1501 value[name] = child_value
1502 elif value:
1503 if element.text:
1504 value["text"] = element.text
1505 else:
1506 return element.text
1507 return value
1509 if ElementTree is None:
1510 warnings.warn("XMP data cannot be read without defusedxml dependency")
1511 return {}
1512 if "xmp" not in self.info:
1513 return {}
1514 root = ElementTree.fromstring(self.info["xmp"].rstrip(b"\x00 "))
1515 return {get_name(root.tag): get_value(root)}
1517 def getexif(self) -> Exif:
1518 """
1519 Gets EXIF data from the image.
1521 :returns: an :py:class:`~PIL.Image.Exif` object.
1522 """
1523 if self._exif is None:
1524 self._exif = Exif()
1525 elif self._exif._loaded:
1526 return self._exif
1527 self._exif._loaded = True
1529 exif_info = self.info.get("exif")
1530 if exif_info is None:
1531 if "Raw profile type exif" in self.info:
1532 exif_info = bytes.fromhex(
1533 "".join(self.info["Raw profile type exif"].split("\n")[3:])
1534 )
1535 elif hasattr(self, "tag_v2"):
1536 self._exif.bigtiff = self.tag_v2._bigtiff
1537 self._exif.endian = self.tag_v2._endian
1538 self._exif.load_from_fp(self.fp, self.tag_v2._offset)
1539 if exif_info is not None:
1540 self._exif.load(exif_info)
1542 # XMP tags
1543 if ExifTags.Base.Orientation not in self._exif:
1544 xmp_tags = self.info.get("XML:com.adobe.xmp")
1545 pattern: str | bytes = r'tiff:Orientation(="|>)([0-9])'
1546 if not xmp_tags and (xmp_tags := self.info.get("xmp")):
1547 pattern = rb'tiff:Orientation(="|>)([0-9])'
1548 if xmp_tags:
1549 match = re.search(pattern, xmp_tags)
1550 if match:
1551 self._exif[ExifTags.Base.Orientation] = int(match[2])
1553 return self._exif
1555 def _reload_exif(self) -> None:
1556 if self._exif is None or not self._exif._loaded:
1557 return
1558 self._exif._loaded = False
1559 self.getexif()
1561 def get_child_images(self) -> list[ImageFile.ImageFile]:
1562 from . import ImageFile
1564 deprecate("Image.Image.get_child_images", 13)
1565 return ImageFile.ImageFile.get_child_images(self) # type: ignore[arg-type]
1567 def getim(self) -> CapsuleType:
1568 """
1569 Returns a capsule that points to the internal image memory.
1571 :returns: A capsule object.
1572 """
1574 self.load()
1575 return self.im.ptr
1577 def getpalette(self, rawmode: str | None = "RGB") -> list[int] | None:
1578 """
1579 Returns the image palette as a list.
1581 :param rawmode: The mode in which to return the palette. ``None`` will
1582 return the palette in its current mode.
1584 .. versionadded:: 9.1.0
1586 :returns: A list of color values [r, g, b, ...], or None if the
1587 image has no palette.
1588 """
1590 self.load()
1591 try:
1592 mode = self.im.getpalettemode()
1593 except ValueError:
1594 return None # no palette
1595 if rawmode is None:
1596 rawmode = mode
1597 return list(self.im.getpalette(mode, rawmode))
1599 @property
1600 def has_transparency_data(self) -> bool:
1601 """
1602 Determine if an image has transparency data, whether in the form of an
1603 alpha channel, a palette with an alpha channel, or a "transparency" key
1604 in the info dictionary.
1606 Note the image might still appear solid, if all of the values shown
1607 within are opaque.
1609 :returns: A boolean.
1610 """
1611 if (
1612 self.mode in ("LA", "La", "PA", "RGBA", "RGBa")
1613 or "transparency" in self.info
1614 ):
1615 return True
1616 if self.mode == "P":
1617 assert self.palette is not None
1618 return self.palette.mode.endswith("A")
1619 return False
1621 def apply_transparency(self) -> None:
1622 """
1623 If a P mode image has a "transparency" key in the info dictionary,
1624 remove the key and instead apply the transparency to the palette.
1625 Otherwise, the image is unchanged.
1626 """
1627 if self.mode != "P" or "transparency" not in self.info:
1628 return
1630 from . import ImagePalette
1632 palette = self.getpalette("RGBA")
1633 assert palette is not None
1634 transparency = self.info["transparency"]
1635 if isinstance(transparency, bytes):
1636 for i, alpha in enumerate(transparency):
1637 palette[i * 4 + 3] = alpha
1638 else:
1639 palette[transparency * 4 + 3] = 0
1640 self.palette = ImagePalette.ImagePalette("RGBA", bytes(palette))
1641 self.palette.dirty = 1
1643 del self.info["transparency"]
1645 def getpixel(
1646 self, xy: tuple[int, int] | list[int]
1647 ) -> float | tuple[int, ...] | None:
1648 """
1649 Returns the pixel value at a given position.
1651 :param xy: The coordinate, given as (x, y). See
1652 :ref:`coordinate-system`.
1653 :returns: The pixel value. If the image is a multi-layer image,
1654 this method returns a tuple.
1655 """
1657 self.load()
1658 return self.im.getpixel(tuple(xy))
1660 def getprojection(self) -> tuple[list[int], list[int]]:
1661 """
1662 Get projection to x and y axes
1664 :returns: Two sequences, indicating where there are non-zero
1665 pixels along the X-axis and the Y-axis, respectively.
1666 """
1668 self.load()
1669 x, y = self.im.getprojection()
1670 return list(x), list(y)
1672 def histogram(
1673 self, mask: Image | None = None, extrema: tuple[float, float] | None = None
1674 ) -> list[int]:
1675 """
1676 Returns a histogram for the image. The histogram is returned as a
1677 list of pixel counts, one for each pixel value in the source
1678 image. Counts are grouped into 256 bins for each band, even if
1679 the image has more than 8 bits per band. If the image has more
1680 than one band, the histograms for all bands are concatenated (for
1681 example, the histogram for an "RGB" image contains 768 values).
1683 A bilevel image (mode "1") is treated as a grayscale ("L") image
1684 by this method.
1686 If a mask is provided, the method returns a histogram for those
1687 parts of the image where the mask image is non-zero. The mask
1688 image must have the same size as the image, and be either a
1689 bi-level image (mode "1") or a grayscale image ("L").
1691 :param mask: An optional mask.
1692 :param extrema: An optional tuple of manually-specified extrema.
1693 :returns: A list containing pixel counts.
1694 """
1695 self.load()
1696 if mask:
1697 mask.load()
1698 return self.im.histogram((0, 0), mask.im)
1699 if self.mode in ("I", "F"):
1700 return self.im.histogram(
1701 extrema if extrema is not None else self.getextrema()
1702 )
1703 return self.im.histogram()
1705 def entropy(
1706 self, mask: Image | None = None, extrema: tuple[float, float] | None = None
1707 ) -> float:
1708 """
1709 Calculates and returns the entropy for the image.
1711 A bilevel image (mode "1") is treated as a grayscale ("L")
1712 image by this method.
1714 If a mask is provided, the method employs the histogram for
1715 those parts of the image where the mask image is non-zero.
1716 The mask image must have the same size as the image, and be
1717 either a bi-level image (mode "1") or a grayscale image ("L").
1719 :param mask: An optional mask.
1720 :param extrema: An optional tuple of manually-specified extrema.
1721 :returns: A float value representing the image entropy
1722 """
1723 self.load()
1724 if mask:
1725 mask.load()
1726 return self.im.entropy((0, 0), mask.im)
1727 if self.mode in ("I", "F"):
1728 return self.im.entropy(
1729 extrema if extrema is not None else self.getextrema()
1730 )
1731 return self.im.entropy()
1733 def paste(
1734 self,
1735 im: Image | str | float | tuple[float, ...],
1736 box: Image | tuple[int, int, int, int] | tuple[int, int] | None = None,
1737 mask: Image | None = None,
1738 ) -> None:
1739 """
1740 Pastes another image into this image. The box argument is either
1741 a 2-tuple giving the upper left corner, a 4-tuple defining the
1742 left, upper, right, and lower pixel coordinate, or None (same as
1743 (0, 0)). See :ref:`coordinate-system`. If a 4-tuple is given, the size
1744 of the pasted image must match the size of the region.
1746 If the modes don't match, the pasted image is converted to the mode of
1747 this image (see the :py:meth:`~PIL.Image.Image.convert` method for
1748 details).
1750 Instead of an image, the source can be a integer or tuple
1751 containing pixel values. The method then fills the region
1752 with the given color. When creating RGB images, you can
1753 also use color strings as supported by the ImageColor module.
1755 If a mask is given, this method updates only the regions
1756 indicated by the mask. You can use either "1", "L", "LA", "RGBA"
1757 or "RGBa" images (if present, the alpha band is used as mask).
1758 Where the mask is 255, the given image is copied as is. Where
1759 the mask is 0, the current value is preserved. Intermediate
1760 values will mix the two images together, including their alpha
1761 channels if they have them.
1763 See :py:meth:`~PIL.Image.Image.alpha_composite` if you want to
1764 combine images with respect to their alpha channels.
1766 :param im: Source image or pixel value (integer, float or tuple).
1767 :param box: An optional 4-tuple giving the region to paste into.
1768 If a 2-tuple is used instead, it's treated as the upper left
1769 corner. If omitted or None, the source is pasted into the
1770 upper left corner.
1772 If an image is given as the second argument and there is no
1773 third, the box defaults to (0, 0), and the second argument
1774 is interpreted as a mask image.
1775 :param mask: An optional mask image.
1776 """
1778 if isinstance(box, Image):
1779 if mask is not None:
1780 msg = "If using second argument as mask, third argument must be None"
1781 raise ValueError(msg)
1782 # abbreviated paste(im, mask) syntax
1783 mask = box
1784 box = None
1786 if box is None:
1787 box = (0, 0)
1789 if len(box) == 2:
1790 # upper left corner given; get size from image or mask
1791 if isinstance(im, Image):
1792 size = im.size
1793 elif isinstance(mask, Image):
1794 size = mask.size
1795 else:
1796 # FIXME: use self.size here?
1797 msg = "cannot determine region size; use 4-item box"
1798 raise ValueError(msg)
1799 box += (box[0] + size[0], box[1] + size[1])
1801 source: core.ImagingCore | str | float | tuple[float, ...]
1802 if isinstance(im, str):
1803 from . import ImageColor
1805 source = ImageColor.getcolor(im, self.mode)
1806 elif isinstance(im, Image):
1807 im.load()
1808 if self.mode != im.mode:
1809 if self.mode != "RGB" or im.mode not in ("LA", "RGBA", "RGBa"):
1810 # should use an adapter for this!
1811 im = im.convert(self.mode)
1812 source = im.im
1813 else:
1814 source = im
1816 self._ensure_mutable()
1818 if mask:
1819 mask.load()
1820 self.im.paste(source, box, mask.im)
1821 else:
1822 self.im.paste(source, box)
1824 def alpha_composite(
1825 self, im: Image, dest: Sequence[int] = (0, 0), source: Sequence[int] = (0, 0)
1826 ) -> None:
1827 """'In-place' analog of Image.alpha_composite. Composites an image
1828 onto this image.
1830 :param im: image to composite over this one
1831 :param dest: Optional 2 tuple (left, top) specifying the upper
1832 left corner in this (destination) image.
1833 :param source: Optional 2 (left, top) tuple for the upper left
1834 corner in the overlay source image, or 4 tuple (left, top, right,
1835 bottom) for the bounds of the source rectangle
1837 Performance Note: Not currently implemented in-place in the core layer.
1838 """
1840 if not isinstance(source, (list, tuple)):
1841 msg = "Source must be a list or tuple"
1842 raise ValueError(msg)
1843 if not isinstance(dest, (list, tuple)):
1844 msg = "Destination must be a list or tuple"
1845 raise ValueError(msg)
1847 if len(source) == 4:
1848 overlay_crop_box = tuple(source)
1849 elif len(source) == 2:
1850 overlay_crop_box = tuple(source) + im.size
1851 else:
1852 msg = "Source must be a sequence of length 2 or 4"
1853 raise ValueError(msg)
1855 if not len(dest) == 2:
1856 msg = "Destination must be a sequence of length 2"
1857 raise ValueError(msg)
1858 if min(source) < 0:
1859 msg = "Source must be non-negative"
1860 raise ValueError(msg)
1862 # over image, crop if it's not the whole image.
1863 if overlay_crop_box == (0, 0) + im.size:
1864 overlay = im
1865 else:
1866 overlay = im.crop(overlay_crop_box)
1868 # target for the paste
1869 box = tuple(dest) + (dest[0] + overlay.width, dest[1] + overlay.height)
1871 # destination image. don't copy if we're using the whole image.
1872 if box == (0, 0) + self.size:
1873 background = self
1874 else:
1875 background = self.crop(box)
1877 result = alpha_composite(background, overlay)
1878 self.paste(result, box)
1880 def point(
1881 self,
1882 lut: (
1883 Sequence[float]
1884 | NumpyArray
1885 | Callable[[int], float]
1886 | Callable[[ImagePointTransform], ImagePointTransform | float]
1887 | ImagePointHandler
1888 ),
1889 mode: str | None = None,
1890 ) -> Image:
1891 """
1892 Maps this image through a lookup table or function.
1894 :param lut: A lookup table, containing 256 (or 65536 if
1895 self.mode=="I" and mode == "L") values per band in the
1896 image. A function can be used instead, it should take a
1897 single argument. The function is called once for each
1898 possible pixel value, and the resulting table is applied to
1899 all bands of the image.
1901 It may also be an :py:class:`~PIL.Image.ImagePointHandler`
1902 object::
1904 class Example(Image.ImagePointHandler):
1905 def point(self, im: Image) -> Image:
1906 # Return result
1907 :param mode: Output mode (default is same as input). This can only be used if
1908 the source image has mode "L" or "P", and the output has mode "1" or the
1909 source image mode is "I" and the output mode is "L".
1910 :returns: An :py:class:`~PIL.Image.Image` object.
1911 """
1913 self.load()
1915 if isinstance(lut, ImagePointHandler):
1916 return lut.point(self)
1918 if callable(lut):
1919 # if it isn't a list, it should be a function
1920 if self.mode in ("I", "I;16", "F"):
1921 # check if the function can be used with point_transform
1922 # UNDONE wiredfool -- I think this prevents us from ever doing
1923 # a gamma function point transform on > 8bit images.
1924 scale, offset = _getscaleoffset(lut) # type: ignore[arg-type]
1925 return self._new(self.im.point_transform(scale, offset))
1926 # for other modes, convert the function to a table
1927 flatLut = [lut(i) for i in range(256)] * self.im.bands # type: ignore[arg-type]
1928 else:
1929 flatLut = lut
1931 if self.mode == "F":
1932 # FIXME: _imaging returns a confusing error message for this case
1933 msg = "point operation not supported for this mode"
1934 raise ValueError(msg)
1936 if mode != "F":
1937 flatLut = [round(i) for i in flatLut]
1938 return self._new(self.im.point(flatLut, mode))
1940 def putalpha(self, alpha: Image | int) -> None:
1941 """
1942 Adds or replaces the alpha layer in this image. If the image
1943 does not have an alpha layer, it's converted to "LA" or "RGBA".
1944 The new layer must be either "L" or "1".
1946 :param alpha: The new alpha layer. This can either be an "L" or "1"
1947 image having the same size as this image, or an integer.
1948 """
1950 self._ensure_mutable()
1952 if self.mode not in ("LA", "PA", "RGBA"):
1953 # attempt to promote self to a matching alpha mode
1954 try:
1955 mode = getmodebase(self.mode) + "A"
1956 try:
1957 self.im.setmode(mode)
1958 except (AttributeError, ValueError) as e:
1959 # do things the hard way
1960 im = self.im.convert(mode)
1961 if im.mode not in ("LA", "PA", "RGBA"):
1962 msg = "alpha channel could not be added"
1963 raise ValueError(msg) from e # sanity check
1964 self.im = im
1965 self._mode = self.im.mode
1966 except KeyError as e:
1967 msg = "illegal image mode"
1968 raise ValueError(msg) from e
1970 if self.mode in ("LA", "PA"):
1971 band = 1
1972 else:
1973 band = 3
1975 if isinstance(alpha, Image):
1976 # alpha layer
1977 if alpha.mode not in ("1", "L"):
1978 msg = "illegal image mode"
1979 raise ValueError(msg)
1980 alpha.load()
1981 if alpha.mode == "1":
1982 alpha = alpha.convert("L")
1983 else:
1984 # constant alpha
1985 try:
1986 self.im.fillband(band, alpha)
1987 except (AttributeError, ValueError):
1988 # do things the hard way
1989 alpha = new("L", self.size, alpha)
1990 else:
1991 return
1993 self.im.putband(alpha.im, band)
1995 def putdata(
1996 self,
1997 data: Sequence[float] | Sequence[Sequence[int]] | core.ImagingCore | NumpyArray,
1998 scale: float = 1.0,
1999 offset: float = 0.0,
2000 ) -> None:
2001 """
2002 Copies pixel data from a flattened sequence object into the image. The
2003 values should start at the upper left corner (0, 0), continue to the
2004 end of the line, followed directly by the first value of the second
2005 line, and so on. Data will be read until either the image or the
2006 sequence ends. The scale and offset values are used to adjust the
2007 sequence values: **pixel = value*scale + offset**.
2009 :param data: A flattened sequence object.
2010 :param scale: An optional scale value. The default is 1.0.
2011 :param offset: An optional offset value. The default is 0.0.
2012 """
2014 self._ensure_mutable()
2016 self.im.putdata(data, scale, offset)
2018 def putpalette(
2019 self,
2020 data: ImagePalette.ImagePalette | bytes | Sequence[int],
2021 rawmode: str = "RGB",
2022 ) -> None:
2023 """
2024 Attaches a palette to this image. The image must be a "P", "PA", "L"
2025 or "LA" image.
2027 The palette sequence must contain at most 256 colors, made up of one
2028 integer value for each channel in the raw mode.
2029 For example, if the raw mode is "RGB", then it can contain at most 768
2030 values, made up of red, green and blue values for the corresponding pixel
2031 index in the 256 colors.
2032 If the raw mode is "RGBA", then it can contain at most 1024 values,
2033 containing red, green, blue and alpha values.
2035 Alternatively, an 8-bit string may be used instead of an integer sequence.
2037 :param data: A palette sequence (either a list or a string).
2038 :param rawmode: The raw mode of the palette. Either "RGB", "RGBA", or a mode
2039 that can be transformed to "RGB" or "RGBA" (e.g. "R", "BGR;15", "RGBA;L").
2040 """
2041 from . import ImagePalette
2043 if self.mode not in ("L", "LA", "P", "PA"):
2044 msg = "illegal image mode"
2045 raise ValueError(msg)
2046 if isinstance(data, ImagePalette.ImagePalette):
2047 if data.rawmode is not None:
2048 palette = ImagePalette.raw(data.rawmode, data.palette)
2049 else:
2050 palette = ImagePalette.ImagePalette(palette=data.palette)
2051 palette.dirty = 1
2052 else:
2053 if not isinstance(data, bytes):
2054 data = bytes(data)
2055 palette = ImagePalette.raw(rawmode, data)
2056 self._mode = "PA" if "A" in self.mode else "P"
2057 self.palette = palette
2058 self.palette.mode = "RGBA" if "A" in rawmode else "RGB"
2059 self.load() # install new palette
2061 def putpixel(
2062 self, xy: tuple[int, int], value: float | tuple[int, ...] | list[int]
2063 ) -> None:
2064 """
2065 Modifies the pixel at the given position. The color is given as
2066 a single numerical value for single-band images, and a tuple for
2067 multi-band images. In addition to this, RGB and RGBA tuples are
2068 accepted for P and PA images.
2070 Note that this method is relatively slow. For more extensive changes,
2071 use :py:meth:`~PIL.Image.Image.paste` or the :py:mod:`~PIL.ImageDraw`
2072 module instead.
2074 See:
2076 * :py:meth:`~PIL.Image.Image.paste`
2077 * :py:meth:`~PIL.Image.Image.putdata`
2078 * :py:mod:`~PIL.ImageDraw`
2080 :param xy: The pixel coordinate, given as (x, y). See
2081 :ref:`coordinate-system`.
2082 :param value: The pixel value.
2083 """
2085 if self.readonly:
2086 self._copy()
2087 self.load()
2089 if (
2090 self.mode in ("P", "PA")
2091 and isinstance(value, (list, tuple))
2092 and len(value) in [3, 4]
2093 ):
2094 # RGB or RGBA value for a P or PA image
2095 if self.mode == "PA":
2096 alpha = value[3] if len(value) == 4 else 255
2097 value = value[:3]
2098 assert self.palette is not None
2099 palette_index = self.palette.getcolor(tuple(value), self)
2100 value = (palette_index, alpha) if self.mode == "PA" else palette_index
2101 return self.im.putpixel(xy, value)
2103 def remap_palette(
2104 self, dest_map: list[int], source_palette: bytes | bytearray | None = None
2105 ) -> Image:
2106 """
2107 Rewrites the image to reorder the palette.
2109 :param dest_map: A list of indexes into the original palette.
2110 e.g. ``[1,0]`` would swap a two item palette, and ``list(range(256))``
2111 is the identity transform.
2112 :param source_palette: Bytes or None.
2113 :returns: An :py:class:`~PIL.Image.Image` object.
2115 """
2116 from . import ImagePalette
2118 if self.mode not in ("L", "P"):
2119 msg = "illegal image mode"
2120 raise ValueError(msg)
2122 bands = 3
2123 palette_mode = "RGB"
2124 if source_palette is None:
2125 if self.mode == "P":
2126 self.load()
2127 palette_mode = self.im.getpalettemode()
2128 if palette_mode == "RGBA":
2129 bands = 4
2130 source_palette = self.im.getpalette(palette_mode, palette_mode)
2131 else: # L-mode
2132 source_palette = bytearray(i // 3 for i in range(768))
2133 elif len(source_palette) > 768:
2134 bands = 4
2135 palette_mode = "RGBA"
2137 palette_bytes = b""
2138 new_positions = [0] * 256
2140 # pick only the used colors from the palette
2141 for i, oldPosition in enumerate(dest_map):
2142 palette_bytes += source_palette[
2143 oldPosition * bands : oldPosition * bands + bands
2144 ]
2145 new_positions[oldPosition] = i
2147 # replace the palette color id of all pixel with the new id
2149 # Palette images are [0..255], mapped through a 1 or 3
2150 # byte/color map. We need to remap the whole image
2151 # from palette 1 to palette 2. New_positions is
2152 # an array of indexes into palette 1. Palette 2 is
2153 # palette 1 with any holes removed.
2155 # We're going to leverage the convert mechanism to use the
2156 # C code to remap the image from palette 1 to palette 2,
2157 # by forcing the source image into 'L' mode and adding a
2158 # mapping 'L' mode palette, then converting back to 'L'
2159 # sans palette thus converting the image bytes, then
2160 # assigning the optimized RGB palette.
2162 # perf reference, 9500x4000 gif, w/~135 colors
2163 # 14 sec prepatch, 1 sec postpatch with optimization forced.
2165 mapping_palette = bytearray(new_positions)
2167 m_im = self.copy()
2168 m_im._mode = "P"
2170 m_im.palette = ImagePalette.ImagePalette(
2171 palette_mode, palette=mapping_palette * bands
2172 )
2173 # possibly set palette dirty, then
2174 # m_im.putpalette(mapping_palette, 'L') # converts to 'P'
2175 # or just force it.
2176 # UNDONE -- this is part of the general issue with palettes
2177 m_im.im.putpalette(palette_mode, palette_mode + ";L", m_im.palette.tobytes())
2179 m_im = m_im.convert("L")
2181 m_im.putpalette(palette_bytes, palette_mode)
2182 m_im.palette = ImagePalette.ImagePalette(palette_mode, palette=palette_bytes)
2184 if "transparency" in self.info:
2185 try:
2186 m_im.info["transparency"] = dest_map.index(self.info["transparency"])
2187 except ValueError:
2188 if "transparency" in m_im.info:
2189 del m_im.info["transparency"]
2191 return m_im
2193 def _get_safe_box(
2194 self,
2195 size: tuple[int, int],
2196 resample: Resampling,
2197 box: tuple[float, float, float, float],
2198 ) -> tuple[int, int, int, int]:
2199 """Expands the box so it includes adjacent pixels
2200 that may be used by resampling with the given resampling filter.
2201 """
2202 filter_support = _filters_support[resample] - 0.5
2203 scale_x = (box[2] - box[0]) / size[0]
2204 scale_y = (box[3] - box[1]) / size[1]
2205 support_x = filter_support * scale_x
2206 support_y = filter_support * scale_y
2208 return (
2209 max(0, int(box[0] - support_x)),
2210 max(0, int(box[1] - support_y)),
2211 min(self.size[0], math.ceil(box[2] + support_x)),
2212 min(self.size[1], math.ceil(box[3] + support_y)),
2213 )
2215 def resize(
2216 self,
2217 size: tuple[int, int] | list[int] | NumpyArray,
2218 resample: int | None = None,
2219 box: tuple[float, float, float, float] | None = None,
2220 reducing_gap: float | None = None,
2221 ) -> Image:
2222 """
2223 Returns a resized copy of this image.
2225 :param size: The requested size in pixels, as a tuple or array:
2226 (width, height).
2227 :param resample: An optional resampling filter. This can be
2228 one of :py:data:`Resampling.NEAREST`, :py:data:`Resampling.BOX`,
2229 :py:data:`Resampling.BILINEAR`, :py:data:`Resampling.HAMMING`,
2230 :py:data:`Resampling.BICUBIC` or :py:data:`Resampling.LANCZOS`.
2231 If the image has mode "1" or "P", it is always set to
2232 :py:data:`Resampling.NEAREST`. If the image mode is "BGR;15",
2233 "BGR;16" or "BGR;24", then the default filter is
2234 :py:data:`Resampling.NEAREST`. Otherwise, the default filter is
2235 :py:data:`Resampling.BICUBIC`. See: :ref:`concept-filters`.
2236 :param box: An optional 4-tuple of floats providing
2237 the source image region to be scaled.
2238 The values must be within (0, 0, width, height) rectangle.
2239 If omitted or None, the entire source is used.
2240 :param reducing_gap: Apply optimization by resizing the image
2241 in two steps. First, reducing the image by integer times
2242 using :py:meth:`~PIL.Image.Image.reduce`.
2243 Second, resizing using regular resampling. The last step
2244 changes size no less than by ``reducing_gap`` times.
2245 ``reducing_gap`` may be None (no first step is performed)
2246 or should be greater than 1.0. The bigger ``reducing_gap``,
2247 the closer the result to the fair resampling.
2248 The smaller ``reducing_gap``, the faster resizing.
2249 With ``reducing_gap`` greater or equal to 3.0, the result is
2250 indistinguishable from fair resampling in most cases.
2251 The default value is None (no optimization).
2252 :returns: An :py:class:`~PIL.Image.Image` object.
2253 """
2255 if resample is None:
2256 bgr = self.mode.startswith("BGR;")
2257 resample = Resampling.NEAREST if bgr else Resampling.BICUBIC
2258 elif resample not in (
2259 Resampling.NEAREST,
2260 Resampling.BILINEAR,
2261 Resampling.BICUBIC,
2262 Resampling.LANCZOS,
2263 Resampling.BOX,
2264 Resampling.HAMMING,
2265 ):
2266 msg = f"Unknown resampling filter ({resample})."
2268 filters = [
2269 f"{filter[1]} ({filter[0]})"
2270 for filter in (
2271 (Resampling.NEAREST, "Image.Resampling.NEAREST"),
2272 (Resampling.LANCZOS, "Image.Resampling.LANCZOS"),
2273 (Resampling.BILINEAR, "Image.Resampling.BILINEAR"),
2274 (Resampling.BICUBIC, "Image.Resampling.BICUBIC"),
2275 (Resampling.BOX, "Image.Resampling.BOX"),
2276 (Resampling.HAMMING, "Image.Resampling.HAMMING"),
2277 )
2278 ]
2279 msg += f" Use {', '.join(filters[:-1])} or {filters[-1]}"
2280 raise ValueError(msg)
2282 if reducing_gap is not None and reducing_gap < 1.0:
2283 msg = "reducing_gap must be 1.0 or greater"
2284 raise ValueError(msg)
2286 if box is None:
2287 box = (0, 0) + self.size
2289 size = tuple(size)
2290 if self.size == size and box == (0, 0) + self.size:
2291 return self.copy()
2293 if self.mode in ("1", "P"):
2294 resample = Resampling.NEAREST
2296 if self.mode in ["LA", "RGBA"] and resample != Resampling.NEAREST:
2297 im = self.convert({"LA": "La", "RGBA": "RGBa"}[self.mode])
2298 im = im.resize(size, resample, box)
2299 return im.convert(self.mode)
2301 self.load()
2303 if reducing_gap is not None and resample != Resampling.NEAREST:
2304 factor_x = int((box[2] - box[0]) / size[0] / reducing_gap) or 1
2305 factor_y = int((box[3] - box[1]) / size[1] / reducing_gap) or 1
2306 if factor_x > 1 or factor_y > 1:
2307 reduce_box = self._get_safe_box(size, cast(Resampling, resample), box)
2308 factor = (factor_x, factor_y)
2309 self = (
2310 self.reduce(factor, box=reduce_box)
2311 if callable(self.reduce)
2312 else Image.reduce(self, factor, box=reduce_box)
2313 )
2314 box = (
2315 (box[0] - reduce_box[0]) / factor_x,
2316 (box[1] - reduce_box[1]) / factor_y,
2317 (box[2] - reduce_box[0]) / factor_x,
2318 (box[3] - reduce_box[1]) / factor_y,
2319 )
2321 return self._new(self.im.resize(size, resample, box))
2323 def reduce(
2324 self,
2325 factor: int | tuple[int, int],
2326 box: tuple[int, int, int, int] | None = None,
2327 ) -> Image:
2328 """
2329 Returns a copy of the image reduced ``factor`` times.
2330 If the size of the image is not dividable by ``factor``,
2331 the resulting size will be rounded up.
2333 :param factor: A greater than 0 integer or tuple of two integers
2334 for width and height separately.
2335 :param box: An optional 4-tuple of ints providing
2336 the source image region to be reduced.
2337 The values must be within ``(0, 0, width, height)`` rectangle.
2338 If omitted or ``None``, the entire source is used.
2339 """
2340 if not isinstance(factor, (list, tuple)):
2341 factor = (factor, factor)
2343 if box is None:
2344 box = (0, 0) + self.size
2346 if factor == (1, 1) and box == (0, 0) + self.size:
2347 return self.copy()
2349 if self.mode in ["LA", "RGBA"]:
2350 im = self.convert({"LA": "La", "RGBA": "RGBa"}[self.mode])
2351 im = im.reduce(factor, box)
2352 return im.convert(self.mode)
2354 self.load()
2356 return self._new(self.im.reduce(factor, box))
2358 def rotate(
2359 self,
2360 angle: float,
2361 resample: Resampling = Resampling.NEAREST,
2362 expand: int | bool = False,
2363 center: tuple[float, float] | None = None,
2364 translate: tuple[int, int] | None = None,
2365 fillcolor: float | tuple[float, ...] | str | None = None,
2366 ) -> Image:
2367 """
2368 Returns a rotated copy of this image. This method returns a
2369 copy of this image, rotated the given number of degrees counter
2370 clockwise around its centre.
2372 :param angle: In degrees counter clockwise.
2373 :param resample: An optional resampling filter. This can be
2374 one of :py:data:`Resampling.NEAREST` (use nearest neighbour),
2375 :py:data:`Resampling.BILINEAR` (linear interpolation in a 2x2
2376 environment), or :py:data:`Resampling.BICUBIC` (cubic spline
2377 interpolation in a 4x4 environment). If omitted, or if the image has
2378 mode "1" or "P", it is set to :py:data:`Resampling.NEAREST`.
2379 See :ref:`concept-filters`.
2380 :param expand: Optional expansion flag. If true, expands the output
2381 image to make it large enough to hold the entire rotated image.
2382 If false or omitted, make the output image the same size as the
2383 input image. Note that the expand flag assumes rotation around
2384 the center and no translation.
2385 :param center: Optional center of rotation (a 2-tuple). Origin is
2386 the upper left corner. Default is the center of the image.
2387 :param translate: An optional post-rotate translation (a 2-tuple).
2388 :param fillcolor: An optional color for area outside the rotated image.
2389 :returns: An :py:class:`~PIL.Image.Image` object.
2390 """
2392 angle = angle % 360.0
2394 # Fast paths regardless of filter, as long as we're not
2395 # translating or changing the center.
2396 if not (center or translate):
2397 if angle == 0:
2398 return self.copy()
2399 if angle == 180:
2400 return self.transpose(Transpose.ROTATE_180)
2401 if angle in (90, 270) and (expand or self.width == self.height):
2402 return self.transpose(
2403 Transpose.ROTATE_90 if angle == 90 else Transpose.ROTATE_270
2404 )
2406 # Calculate the affine matrix. Note that this is the reverse
2407 # transformation (from destination image to source) because we
2408 # want to interpolate the (discrete) destination pixel from
2409 # the local area around the (floating) source pixel.
2411 # The matrix we actually want (note that it operates from the right):
2412 # (1, 0, tx) (1, 0, cx) ( cos a, sin a, 0) (1, 0, -cx)
2413 # (0, 1, ty) * (0, 1, cy) * (-sin a, cos a, 0) * (0, 1, -cy)
2414 # (0, 0, 1) (0, 0, 1) ( 0, 0, 1) (0, 0, 1)
2416 # The reverse matrix is thus:
2417 # (1, 0, cx) ( cos -a, sin -a, 0) (1, 0, -cx) (1, 0, -tx)
2418 # (0, 1, cy) * (-sin -a, cos -a, 0) * (0, 1, -cy) * (0, 1, -ty)
2419 # (0, 0, 1) ( 0, 0, 1) (0, 0, 1) (0, 0, 1)
2421 # In any case, the final translation may be updated at the end to
2422 # compensate for the expand flag.
2424 w, h = self.size
2426 if translate is None:
2427 post_trans = (0, 0)
2428 else:
2429 post_trans = translate
2430 if center is None:
2431 center = (w / 2, h / 2)
2433 angle = -math.radians(angle)
2434 matrix = [
2435 round(math.cos(angle), 15),
2436 round(math.sin(angle), 15),
2437 0.0,
2438 round(-math.sin(angle), 15),
2439 round(math.cos(angle), 15),
2440 0.0,
2441 ]
2443 def transform(x: float, y: float, matrix: list[float]) -> tuple[float, float]:
2444 (a, b, c, d, e, f) = matrix
2445 return a * x + b * y + c, d * x + e * y + f
2447 matrix[2], matrix[5] = transform(
2448 -center[0] - post_trans[0], -center[1] - post_trans[1], matrix
2449 )
2450 matrix[2] += center[0]
2451 matrix[5] += center[1]
2453 if expand:
2454 # calculate output size
2455 xx = []
2456 yy = []
2457 for x, y in ((0, 0), (w, 0), (w, h), (0, h)):
2458 transformed_x, transformed_y = transform(x, y, matrix)
2459 xx.append(transformed_x)
2460 yy.append(transformed_y)
2461 nw = math.ceil(max(xx)) - math.floor(min(xx))
2462 nh = math.ceil(max(yy)) - math.floor(min(yy))
2464 # We multiply a translation matrix from the right. Because of its
2465 # special form, this is the same as taking the image of the
2466 # translation vector as new translation vector.
2467 matrix[2], matrix[5] = transform(-(nw - w) / 2.0, -(nh - h) / 2.0, matrix)
2468 w, h = nw, nh
2470 return self.transform(
2471 (w, h), Transform.AFFINE, matrix, resample, fillcolor=fillcolor
2472 )
2474 def save(
2475 self, fp: StrOrBytesPath | IO[bytes], format: str | None = None, **params: Any
2476 ) -> None:
2477 """
2478 Saves this image under the given filename. If no format is
2479 specified, the format to use is determined from the filename
2480 extension, if possible.
2482 Keyword options can be used to provide additional instructions
2483 to the writer. If a writer doesn't recognise an option, it is
2484 silently ignored. The available options are described in the
2485 :doc:`image format documentation
2486 <../handbook/image-file-formats>` for each writer.
2488 You can use a file object instead of a filename. In this case,
2489 you must always specify the format. The file object must
2490 implement the ``seek``, ``tell``, and ``write``
2491 methods, and be opened in binary mode.
2493 :param fp: A filename (string), os.PathLike object or file object.
2494 :param format: Optional format override. If omitted, the
2495 format to use is determined from the filename extension.
2496 If a file object was used instead of a filename, this
2497 parameter should always be used.
2498 :param params: Extra parameters to the image writer. These can also be
2499 set on the image itself through ``encoderinfo``. This is useful when
2500 saving multiple images::
2502 # Saving XMP data to a single image
2503 from PIL import Image
2504 red = Image.new("RGB", (1, 1), "#f00")
2505 red.save("out.mpo", xmp=b"test")
2507 # Saving XMP data to the second frame of an image
2508 from PIL import Image
2509 black = Image.new("RGB", (1, 1))
2510 red = Image.new("RGB", (1, 1), "#f00")
2511 red.encoderinfo = {"xmp": b"test"}
2512 black.save("out.mpo", save_all=True, append_images=[red])
2513 :returns: None
2514 :exception ValueError: If the output format could not be determined
2515 from the file name. Use the format option to solve this.
2516 :exception OSError: If the file could not be written. The file
2517 may have been created, and may contain partial data.
2518 """
2520 filename: str | bytes = ""
2521 open_fp = False
2522 if is_path(fp):
2523 filename = os.fspath(fp)
2524 open_fp = True
2525 elif fp == sys.stdout:
2526 try:
2527 fp = sys.stdout.buffer
2528 except AttributeError:
2529 pass
2530 if not filename and hasattr(fp, "name") and is_path(fp.name):
2531 # only set the name for metadata purposes
2532 filename = os.fspath(fp.name)
2534 preinit()
2536 filename_ext = os.path.splitext(filename)[1].lower()
2537 ext = filename_ext.decode() if isinstance(filename_ext, bytes) else filename_ext
2539 if not format:
2540 if ext not in EXTENSION:
2541 init()
2542 try:
2543 format = EXTENSION[ext]
2544 except KeyError as e:
2545 msg = f"unknown file extension: {ext}"
2546 raise ValueError(msg) from e
2548 from . import ImageFile
2550 # may mutate self!
2551 if isinstance(self, ImageFile.ImageFile) and os.path.abspath(
2552 filename
2553 ) == os.path.abspath(self.filename):
2554 self._ensure_mutable()
2555 else:
2556 self.load()
2558 save_all = params.pop("save_all", None)
2559 self.encoderinfo = {**getattr(self, "encoderinfo", {}), **params}
2560 self.encoderconfig: tuple[Any, ...] = ()
2562 if format.upper() not in SAVE:
2563 init()
2564 if save_all or (
2565 save_all is None
2566 and params.get("append_images")
2567 and format.upper() in SAVE_ALL
2568 ):
2569 save_handler = SAVE_ALL[format.upper()]
2570 else:
2571 save_handler = SAVE[format.upper()]
2573 created = False
2574 if open_fp:
2575 created = not os.path.exists(filename)
2576 if params.get("append", False):
2577 # Open also for reading ("+"), because TIFF save_all
2578 # writer needs to go back and edit the written data.
2579 fp = builtins.open(filename, "r+b")
2580 else:
2581 fp = builtins.open(filename, "w+b")
2582 else:
2583 fp = cast(IO[bytes], fp)
2585 try:
2586 save_handler(self, fp, filename)
2587 except Exception:
2588 if open_fp:
2589 fp.close()
2590 if created:
2591 try:
2592 os.remove(filename)
2593 except PermissionError:
2594 pass
2595 raise
2596 finally:
2597 try:
2598 del self.encoderinfo
2599 except AttributeError:
2600 pass
2601 if open_fp:
2602 fp.close()
2604 def seek(self, frame: int) -> None:
2605 """
2606 Seeks to the given frame in this sequence file. If you seek
2607 beyond the end of the sequence, the method raises an
2608 ``EOFError`` exception. When a sequence file is opened, the
2609 library automatically seeks to frame 0.
2611 See :py:meth:`~PIL.Image.Image.tell`.
2613 If defined, :attr:`~PIL.Image.Image.n_frames` refers to the
2614 number of available frames.
2616 :param frame: Frame number, starting at 0.
2617 :exception EOFError: If the call attempts to seek beyond the end
2618 of the sequence.
2619 """
2621 # overridden by file handlers
2622 if frame != 0:
2623 msg = "no more images in file"
2624 raise EOFError(msg)
2626 def show(self, title: str | None = None) -> None:
2627 """
2628 Displays this image. This method is mainly intended for debugging purposes.
2630 This method calls :py:func:`PIL.ImageShow.show` internally. You can use
2631 :py:func:`PIL.ImageShow.register` to override its default behaviour.
2633 The image is first saved to a temporary file. By default, it will be in
2634 PNG format.
2636 On Unix, the image is then opened using the **xdg-open**, **display**,
2637 **gm**, **eog** or **xv** utility, depending on which one can be found.
2639 On macOS, the image is opened with the native Preview application.
2641 On Windows, the image is opened with the standard PNG display utility.
2643 :param title: Optional title to use for the image window, where possible.
2644 """
2646 _show(self, title=title)
2648 def split(self) -> tuple[Image, ...]:
2649 """
2650 Split this image into individual bands. This method returns a
2651 tuple of individual image bands from an image. For example,
2652 splitting an "RGB" image creates three new images each
2653 containing a copy of one of the original bands (red, green,
2654 blue).
2656 If you need only one band, :py:meth:`~PIL.Image.Image.getchannel`
2657 method can be more convenient and faster.
2659 :returns: A tuple containing bands.
2660 """
2662 self.load()
2663 if self.im.bands == 1:
2664 return (self.copy(),)
2665 return tuple(map(self._new, self.im.split()))
2667 def getchannel(self, channel: int | str) -> Image:
2668 """
2669 Returns an image containing a single channel of the source image.
2671 :param channel: What channel to return. Could be index
2672 (0 for "R" channel of "RGB") or channel name
2673 ("A" for alpha channel of "RGBA").
2674 :returns: An image in "L" mode.
2676 .. versionadded:: 4.3.0
2677 """
2678 self.load()
2680 if isinstance(channel, str):
2681 try:
2682 channel = self.getbands().index(channel)
2683 except ValueError as e:
2684 msg = f'The image has no channel "{channel}"'
2685 raise ValueError(msg) from e
2687 return self._new(self.im.getband(channel))
2689 def tell(self) -> int:
2690 """
2691 Returns the current frame number. See :py:meth:`~PIL.Image.Image.seek`.
2693 If defined, :attr:`~PIL.Image.Image.n_frames` refers to the
2694 number of available frames.
2696 :returns: Frame number, starting with 0.
2697 """
2698 return 0
2700 def thumbnail(
2701 self,
2702 size: tuple[float, float],
2703 resample: Resampling = Resampling.BICUBIC,
2704 reducing_gap: float | None = 2.0,
2705 ) -> None:
2706 """
2707 Make this image into a thumbnail. This method modifies the
2708 image to contain a thumbnail version of itself, no larger than
2709 the given size. This method calculates an appropriate thumbnail
2710 size to preserve the aspect of the image, calls the
2711 :py:meth:`~PIL.Image.Image.draft` method to configure the file reader
2712 (where applicable), and finally resizes the image.
2714 Note that this function modifies the :py:class:`~PIL.Image.Image`
2715 object in place. If you need to use the full resolution image as well,
2716 apply this method to a :py:meth:`~PIL.Image.Image.copy` of the original
2717 image.
2719 :param size: The requested size in pixels, as a 2-tuple:
2720 (width, height).
2721 :param resample: Optional resampling filter. This can be one
2722 of :py:data:`Resampling.NEAREST`, :py:data:`Resampling.BOX`,
2723 :py:data:`Resampling.BILINEAR`, :py:data:`Resampling.HAMMING`,
2724 :py:data:`Resampling.BICUBIC` or :py:data:`Resampling.LANCZOS`.
2725 If omitted, it defaults to :py:data:`Resampling.BICUBIC`.
2726 (was :py:data:`Resampling.NEAREST` prior to version 2.5.0).
2727 See: :ref:`concept-filters`.
2728 :param reducing_gap: Apply optimization by resizing the image
2729 in two steps. First, reducing the image by integer times
2730 using :py:meth:`~PIL.Image.Image.reduce` or
2731 :py:meth:`~PIL.Image.Image.draft` for JPEG images.
2732 Second, resizing using regular resampling. The last step
2733 changes size no less than by ``reducing_gap`` times.
2734 ``reducing_gap`` may be None (no first step is performed)
2735 or should be greater than 1.0. The bigger ``reducing_gap``,
2736 the closer the result to the fair resampling.
2737 The smaller ``reducing_gap``, the faster resizing.
2738 With ``reducing_gap`` greater or equal to 3.0, the result is
2739 indistinguishable from fair resampling in most cases.
2740 The default value is 2.0 (very close to fair resampling
2741 while still being faster in many cases).
2742 :returns: None
2743 """
2745 provided_size = tuple(map(math.floor, size))
2747 def preserve_aspect_ratio() -> tuple[int, int] | None:
2748 def round_aspect(number: float, key: Callable[[int], float]) -> int:
2749 return max(min(math.floor(number), math.ceil(number), key=key), 1)
2751 x, y = provided_size
2752 if x >= self.width and y >= self.height:
2753 return None
2755 aspect = self.width / self.height
2756 if x / y >= aspect:
2757 x = round_aspect(y * aspect, key=lambda n: abs(aspect - n / y))
2758 else:
2759 y = round_aspect(
2760 x / aspect, key=lambda n: 0 if n == 0 else abs(aspect - x / n)
2761 )
2762 return x, y
2764 preserved_size = preserve_aspect_ratio()
2765 if preserved_size is None:
2766 return
2767 final_size = preserved_size
2769 box = None
2770 if reducing_gap is not None:
2771 res = self.draft(
2772 None, (int(size[0] * reducing_gap), int(size[1] * reducing_gap))
2773 )
2774 if res is not None:
2775 box = res[1]
2777 if self.size != final_size:
2778 im = self.resize(final_size, resample, box=box, reducing_gap=reducing_gap)
2780 self.im = im.im
2781 self._size = final_size
2782 self._mode = self.im.mode
2784 self.readonly = 0
2786 # FIXME: the different transform methods need further explanation
2787 # instead of bloating the method docs, add a separate chapter.
2788 def transform(
2789 self,
2790 size: tuple[int, int],
2791 method: Transform | ImageTransformHandler | SupportsGetData,
2792 data: Sequence[Any] | None = None,
2793 resample: int = Resampling.NEAREST,
2794 fill: int = 1,
2795 fillcolor: float | tuple[float, ...] | str | None = None,
2796 ) -> Image:
2797 """
2798 Transforms this image. This method creates a new image with the
2799 given size, and the same mode as the original, and copies data
2800 to the new image using the given transform.
2802 :param size: The output size in pixels, as a 2-tuple:
2803 (width, height).
2804 :param method: The transformation method. This is one of
2805 :py:data:`Transform.EXTENT` (cut out a rectangular subregion),
2806 :py:data:`Transform.AFFINE` (affine transform),
2807 :py:data:`Transform.PERSPECTIVE` (perspective transform),
2808 :py:data:`Transform.QUAD` (map a quadrilateral to a rectangle), or
2809 :py:data:`Transform.MESH` (map a number of source quadrilaterals
2810 in one operation).
2812 It may also be an :py:class:`~PIL.Image.ImageTransformHandler`
2813 object::
2815 class Example(Image.ImageTransformHandler):
2816 def transform(self, size, data, resample, fill=1):
2817 # Return result
2819 Implementations of :py:class:`~PIL.Image.ImageTransformHandler`
2820 for some of the :py:class:`Transform` methods are provided
2821 in :py:mod:`~PIL.ImageTransform`.
2823 It may also be an object with a ``method.getdata`` method
2824 that returns a tuple supplying new ``method`` and ``data`` values::
2826 class Example:
2827 def getdata(self):
2828 method = Image.Transform.EXTENT
2829 data = (0, 0, 100, 100)
2830 return method, data
2831 :param data: Extra data to the transformation method.
2832 :param resample: Optional resampling filter. It can be one of
2833 :py:data:`Resampling.NEAREST` (use nearest neighbour),
2834 :py:data:`Resampling.BILINEAR` (linear interpolation in a 2x2
2835 environment), or :py:data:`Resampling.BICUBIC` (cubic spline
2836 interpolation in a 4x4 environment). If omitted, or if the image
2837 has mode "1" or "P", it is set to :py:data:`Resampling.NEAREST`.
2838 See: :ref:`concept-filters`.
2839 :param fill: If ``method`` is an
2840 :py:class:`~PIL.Image.ImageTransformHandler` object, this is one of
2841 the arguments passed to it. Otherwise, it is unused.
2842 :param fillcolor: Optional fill color for the area outside the
2843 transform in the output image.
2844 :returns: An :py:class:`~PIL.Image.Image` object.
2845 """
2847 if self.mode in ("LA", "RGBA") and resample != Resampling.NEAREST:
2848 return (
2849 self.convert({"LA": "La", "RGBA": "RGBa"}[self.mode])
2850 .transform(size, method, data, resample, fill, fillcolor)
2851 .convert(self.mode)
2852 )
2854 if isinstance(method, ImageTransformHandler):
2855 return method.transform(size, self, resample=resample, fill=fill)
2857 if hasattr(method, "getdata"):
2858 # compatibility w. old-style transform objects
2859 method, data = method.getdata()
2861 if data is None:
2862 msg = "missing method data"
2863 raise ValueError(msg)
2865 im = new(self.mode, size, fillcolor)
2866 if self.mode == "P" and self.palette:
2867 im.palette = self.palette.copy()
2868 im.info = self.info.copy()
2869 if method == Transform.MESH:
2870 # list of quads
2871 for box, quad in data:
2872 im.__transformer(
2873 box, self, Transform.QUAD, quad, resample, fillcolor is None
2874 )
2875 else:
2876 im.__transformer(
2877 (0, 0) + size, self, method, data, resample, fillcolor is None
2878 )
2880 return im
2882 def __transformer(
2883 self,
2884 box: tuple[int, int, int, int],
2885 image: Image,
2886 method: Transform,
2887 data: Sequence[float],
2888 resample: int = Resampling.NEAREST,
2889 fill: bool = True,
2890 ) -> None:
2891 w = box[2] - box[0]
2892 h = box[3] - box[1]
2894 if method == Transform.AFFINE:
2895 data = data[:6]
2897 elif method == Transform.EXTENT:
2898 # convert extent to an affine transform
2899 x0, y0, x1, y1 = data
2900 xs = (x1 - x0) / w
2901 ys = (y1 - y0) / h
2902 method = Transform.AFFINE
2903 data = (xs, 0, x0, 0, ys, y0)
2905 elif method == Transform.PERSPECTIVE:
2906 data = data[:8]
2908 elif method == Transform.QUAD:
2909 # quadrilateral warp. data specifies the four corners
2910 # given as NW, SW, SE, and NE.
2911 nw = data[:2]
2912 sw = data[2:4]
2913 se = data[4:6]
2914 ne = data[6:8]
2915 x0, y0 = nw
2916 As = 1.0 / w
2917 At = 1.0 / h
2918 data = (
2919 x0,
2920 (ne[0] - x0) * As,
2921 (sw[0] - x0) * At,
2922 (se[0] - sw[0] - ne[0] + x0) * As * At,
2923 y0,
2924 (ne[1] - y0) * As,
2925 (sw[1] - y0) * At,
2926 (se[1] - sw[1] - ne[1] + y0) * As * At,
2927 )
2929 else:
2930 msg = "unknown transformation method"
2931 raise ValueError(msg)
2933 if resample not in (
2934 Resampling.NEAREST,
2935 Resampling.BILINEAR,
2936 Resampling.BICUBIC,
2937 ):
2938 if resample in (Resampling.BOX, Resampling.HAMMING, Resampling.LANCZOS):
2939 unusable: dict[int, str] = {
2940 Resampling.BOX: "Image.Resampling.BOX",
2941 Resampling.HAMMING: "Image.Resampling.HAMMING",
2942 Resampling.LANCZOS: "Image.Resampling.LANCZOS",
2943 }
2944 msg = unusable[resample] + f" ({resample}) cannot be used."
2945 else:
2946 msg = f"Unknown resampling filter ({resample})."
2948 filters = [
2949 f"{filter[1]} ({filter[0]})"
2950 for filter in (
2951 (Resampling.NEAREST, "Image.Resampling.NEAREST"),
2952 (Resampling.BILINEAR, "Image.Resampling.BILINEAR"),
2953 (Resampling.BICUBIC, "Image.Resampling.BICUBIC"),
2954 )
2955 ]
2956 msg += f" Use {', '.join(filters[:-1])} or {filters[-1]}"
2957 raise ValueError(msg)
2959 image.load()
2961 self.load()
2963 if image.mode in ("1", "P"):
2964 resample = Resampling.NEAREST
2966 self.im.transform(box, image.im, method, data, resample, fill)
2968 def transpose(self, method: Transpose) -> Image:
2969 """
2970 Transpose image (flip or rotate in 90 degree steps)
2972 :param method: One of :py:data:`Transpose.FLIP_LEFT_RIGHT`,
2973 :py:data:`Transpose.FLIP_TOP_BOTTOM`, :py:data:`Transpose.ROTATE_90`,
2974 :py:data:`Transpose.ROTATE_180`, :py:data:`Transpose.ROTATE_270`,
2975 :py:data:`Transpose.TRANSPOSE` or :py:data:`Transpose.TRANSVERSE`.
2976 :returns: Returns a flipped or rotated copy of this image.
2977 """
2979 self.load()
2980 return self._new(self.im.transpose(method))
2982 def effect_spread(self, distance: int) -> Image:
2983 """
2984 Randomly spread pixels in an image.
2986 :param distance: Distance to spread pixels.
2987 """
2988 self.load()
2989 return self._new(self.im.effect_spread(distance))
2991 def toqimage(self) -> ImageQt.ImageQt:
2992 """Returns a QImage copy of this image"""
2993 from . import ImageQt
2995 if not ImageQt.qt_is_installed:
2996 msg = "Qt bindings are not installed"
2997 raise ImportError(msg)
2998 return ImageQt.toqimage(self)
3000 def toqpixmap(self) -> ImageQt.QPixmap:
3001 """Returns a QPixmap copy of this image"""
3002 from . import ImageQt
3004 if not ImageQt.qt_is_installed:
3005 msg = "Qt bindings are not installed"
3006 raise ImportError(msg)
3007 return ImageQt.toqpixmap(self)
3010# --------------------------------------------------------------------
3011# Abstract handlers.
3014class ImagePointHandler(abc.ABC):
3015 """
3016 Used as a mixin by point transforms
3017 (for use with :py:meth:`~PIL.Image.Image.point`)
3018 """
3020 @abc.abstractmethod
3021 def point(self, im: Image) -> Image:
3022 pass
3025class ImageTransformHandler(abc.ABC):
3026 """
3027 Used as a mixin by geometry transforms
3028 (for use with :py:meth:`~PIL.Image.Image.transform`)
3029 """
3031 @abc.abstractmethod
3032 def transform(
3033 self,
3034 size: tuple[int, int],
3035 image: Image,
3036 **options: Any,
3037 ) -> Image:
3038 pass
3041# --------------------------------------------------------------------
3042# Factories
3045def _check_size(size: Any) -> None:
3046 """
3047 Common check to enforce type and sanity check on size tuples
3049 :param size: Should be a 2 tuple of (width, height)
3050 :returns: None, or raises a ValueError
3051 """
3053 if not isinstance(size, (list, tuple)):
3054 msg = "Size must be a list or tuple"
3055 raise ValueError(msg)
3056 if len(size) != 2:
3057 msg = "Size must be a sequence of length 2"
3058 raise ValueError(msg)
3059 if size[0] < 0 or size[1] < 0:
3060 msg = "Width and height must be >= 0"
3061 raise ValueError(msg)
3064def new(
3065 mode: str,
3066 size: tuple[int, int] | list[int],
3067 color: float | tuple[float, ...] | str | None = 0,
3068) -> Image:
3069 """
3070 Creates a new image with the given mode and size.
3072 :param mode: The mode to use for the new image. See:
3073 :ref:`concept-modes`.
3074 :param size: A 2-tuple, containing (width, height) in pixels.
3075 :param color: What color to use for the image. Default is black.
3076 If given, this should be a single integer or floating point value
3077 for single-band modes, and a tuple for multi-band modes (one value
3078 per band). When creating RGB or HSV images, you can also use color
3079 strings as supported by the ImageColor module. If the color is
3080 None, the image is not initialised.
3081 :returns: An :py:class:`~PIL.Image.Image` object.
3082 """
3084 if mode in ("BGR;15", "BGR;16", "BGR;24"):
3085 deprecate(mode, 12)
3087 _check_size(size)
3089 if color is None:
3090 # don't initialize
3091 return Image()._new(core.new(mode, size))
3093 if isinstance(color, str):
3094 # css3-style specifier
3096 from . import ImageColor
3098 color = ImageColor.getcolor(color, mode)
3100 im = Image()
3101 if (
3102 mode == "P"
3103 and isinstance(color, (list, tuple))
3104 and all(isinstance(i, int) for i in color)
3105 ):
3106 color_ints: tuple[int, ...] = cast(tuple[int, ...], tuple(color))
3107 if len(color_ints) == 3 or len(color_ints) == 4:
3108 # RGB or RGBA value for a P image
3109 from . import ImagePalette
3111 im.palette = ImagePalette.ImagePalette()
3112 color = im.palette.getcolor(color_ints)
3113 return im._new(core.fill(mode, size, color))
3116def frombytes(
3117 mode: str,
3118 size: tuple[int, int],
3119 data: bytes | bytearray | SupportsArrayInterface,
3120 decoder_name: str = "raw",
3121 *args: Any,
3122) -> Image:
3123 """
3124 Creates a copy of an image memory from pixel data in a buffer.
3126 In its simplest form, this function takes three arguments
3127 (mode, size, and unpacked pixel data).
3129 You can also use any pixel decoder supported by PIL. For more
3130 information on available decoders, see the section
3131 :ref:`Writing Your Own File Codec <file-codecs>`.
3133 Note that this function decodes pixel data only, not entire images.
3134 If you have an entire image in a string, wrap it in a
3135 :py:class:`~io.BytesIO` object, and use :py:func:`~PIL.Image.open` to load
3136 it.
3138 :param mode: The image mode. See: :ref:`concept-modes`.
3139 :param size: The image size.
3140 :param data: A byte buffer containing raw data for the given mode.
3141 :param decoder_name: What decoder to use.
3142 :param args: Additional parameters for the given decoder.
3143 :returns: An :py:class:`~PIL.Image.Image` object.
3144 """
3146 _check_size(size)
3148 im = new(mode, size)
3149 if im.width != 0 and im.height != 0:
3150 decoder_args: Any = args
3151 if len(decoder_args) == 1 and isinstance(decoder_args[0], tuple):
3152 # may pass tuple instead of argument list
3153 decoder_args = decoder_args[0]
3155 if decoder_name == "raw" and decoder_args == ():
3156 decoder_args = mode
3158 im.frombytes(data, decoder_name, decoder_args)
3159 return im
3162def frombuffer(
3163 mode: str,
3164 size: tuple[int, int],
3165 data: bytes | SupportsArrayInterface,
3166 decoder_name: str = "raw",
3167 *args: Any,
3168) -> Image:
3169 """
3170 Creates an image memory referencing pixel data in a byte buffer.
3172 This function is similar to :py:func:`~PIL.Image.frombytes`, but uses data
3173 in the byte buffer, where possible. This means that changes to the
3174 original buffer object are reflected in this image). Not all modes can
3175 share memory; supported modes include "L", "RGBX", "RGBA", and "CMYK".
3177 Note that this function decodes pixel data only, not entire images.
3178 If you have an entire image file in a string, wrap it in a
3179 :py:class:`~io.BytesIO` object, and use :py:func:`~PIL.Image.open` to load it.
3181 The default parameters used for the "raw" decoder differs from that used for
3182 :py:func:`~PIL.Image.frombytes`. This is a bug, and will probably be fixed in a
3183 future release. The current release issues a warning if you do this; to disable
3184 the warning, you should provide the full set of parameters. See below for details.
3186 :param mode: The image mode. See: :ref:`concept-modes`.
3187 :param size: The image size.
3188 :param data: A bytes or other buffer object containing raw
3189 data for the given mode.
3190 :param decoder_name: What decoder to use.
3191 :param args: Additional parameters for the given decoder. For the
3192 default encoder ("raw"), it's recommended that you provide the
3193 full set of parameters::
3195 frombuffer(mode, size, data, "raw", mode, 0, 1)
3197 :returns: An :py:class:`~PIL.Image.Image` object.
3199 .. versionadded:: 1.1.4
3200 """
3202 _check_size(size)
3204 # may pass tuple instead of argument list
3205 if len(args) == 1 and isinstance(args[0], tuple):
3206 args = args[0]
3208 if decoder_name == "raw":
3209 if args == ():
3210 args = mode, 0, 1
3211 if args[0] in _MAPMODES:
3212 im = new(mode, (0, 0))
3213 im = im._new(core.map_buffer(data, size, decoder_name, 0, args))
3214 if mode == "P":
3215 from . import ImagePalette
3217 im.palette = ImagePalette.ImagePalette("RGB", im.im.getpalette("RGB"))
3218 im.readonly = 1
3219 return im
3221 return frombytes(mode, size, data, decoder_name, args)
3224class SupportsArrayInterface(Protocol):
3225 """
3226 An object that has an ``__array_interface__`` dictionary.
3227 """
3229 @property
3230 def __array_interface__(self) -> dict[str, Any]:
3231 raise NotImplementedError()
3234class SupportsArrowArrayInterface(Protocol):
3235 """
3236 An object that has an ``__arrow_c_array__`` method corresponding to the arrow c
3237 data interface.
3238 """
3240 def __arrow_c_array__(
3241 self, requested_schema: "PyCapsule" = None # type: ignore[name-defined] # noqa: F821, UP037
3242 ) -> tuple["PyCapsule", "PyCapsule"]: # type: ignore[name-defined] # noqa: F821, UP037
3243 raise NotImplementedError()
3246def fromarray(obj: SupportsArrayInterface, mode: str | None = None) -> Image:
3247 """
3248 Creates an image memory from an object exporting the array interface
3249 (using the buffer protocol)::
3251 from PIL import Image
3252 import numpy as np
3253 a = np.zeros((5, 5))
3254 im = Image.fromarray(a)
3256 If ``obj`` is not contiguous, then the ``tobytes`` method is called
3257 and :py:func:`~PIL.Image.frombuffer` is used.
3259 In the case of NumPy, be aware that Pillow modes do not always correspond
3260 to NumPy dtypes. Pillow modes only offer 1-bit pixels, 8-bit pixels,
3261 32-bit signed integer pixels, and 32-bit floating point pixels.
3263 Pillow images can also be converted to arrays::
3265 from PIL import Image
3266 import numpy as np
3267 im = Image.open("hopper.jpg")
3268 a = np.asarray(im)
3270 When converting Pillow images to arrays however, only pixel values are
3271 transferred. This means that P and PA mode images will lose their palette.
3273 :param obj: Object with array interface
3274 :param mode: Optional mode to use when reading ``obj``. Will be determined from
3275 type if ``None``.
3277 This will not be used to convert the data after reading, but will be used to
3278 change how the data is read::
3280 from PIL import Image
3281 import numpy as np
3282 a = np.full((1, 1), 300)
3283 im = Image.fromarray(a, mode="L")
3284 im.getpixel((0, 0)) # 44
3285 im = Image.fromarray(a, mode="RGB")
3286 im.getpixel((0, 0)) # (44, 1, 0)
3288 See: :ref:`concept-modes` for general information about modes.
3289 :returns: An image object.
3291 .. versionadded:: 1.1.6
3292 """
3293 arr = obj.__array_interface__
3294 shape = arr["shape"]
3295 ndim = len(shape)
3296 strides = arr.get("strides", None)
3297 if mode is None:
3298 try:
3299 typekey = (1, 1) + shape[2:], arr["typestr"]
3300 except KeyError as e:
3301 msg = "Cannot handle this data type"
3302 raise TypeError(msg) from e
3303 try:
3304 mode, rawmode = _fromarray_typemap[typekey]
3305 except KeyError as e:
3306 typekey_shape, typestr = typekey
3307 msg = f"Cannot handle this data type: {typekey_shape}, {typestr}"
3308 raise TypeError(msg) from e
3309 else:
3310 rawmode = mode
3311 if mode in ["1", "L", "I", "P", "F"]:
3312 ndmax = 2
3313 elif mode == "RGB":
3314 ndmax = 3
3315 else:
3316 ndmax = 4
3317 if ndim > ndmax:
3318 msg = f"Too many dimensions: {ndim} > {ndmax}."
3319 raise ValueError(msg)
3321 size = 1 if ndim == 1 else shape[1], shape[0]
3322 if strides is not None:
3323 if hasattr(obj, "tobytes"):
3324 obj = obj.tobytes()
3325 elif hasattr(obj, "tostring"):
3326 obj = obj.tostring()
3327 else:
3328 msg = "'strides' requires either tobytes() or tostring()"
3329 raise ValueError(msg)
3331 return frombuffer(mode, size, obj, "raw", rawmode, 0, 1)
3334def fromarrow(
3335 obj: SupportsArrowArrayInterface, mode: str, size: tuple[int, int]
3336) -> Image:
3337 """Creates an image with zero-copy shared memory from an object exporting
3338 the arrow_c_array interface protocol::
3340 from PIL import Image
3341 import pyarrow as pa
3342 arr = pa.array([0]*(5*5*4), type=pa.uint8())
3343 im = Image.fromarrow(arr, 'RGBA', (5, 5))
3345 If the data representation of the ``obj`` is not compatible with
3346 Pillow internal storage, a ValueError is raised.
3348 Pillow images can also be converted to Arrow objects::
3350 from PIL import Image
3351 import pyarrow as pa
3352 im = Image.open('hopper.jpg')
3353 arr = pa.array(im)
3355 As with array support, when converting Pillow images to arrays,
3356 only pixel values are transferred. This means that P and PA mode
3357 images will lose their palette.
3359 :param obj: Object with an arrow_c_array interface
3360 :param mode: Image mode.
3361 :param size: Image size. This must match the storage of the arrow object.
3362 :returns: An Image object
3364 Note that according to the Arrow spec, both the producer and the
3365 consumer should consider the exported array to be immutable, as
3366 unsynchronized updates will potentially cause inconsistent data.
3368 See: :ref:`arrow-support` for more detailed information
3370 .. versionadded:: 11.2.1
3372 """
3373 if not hasattr(obj, "__arrow_c_array__"):
3374 msg = "arrow_c_array interface not found"
3375 raise ValueError(msg)
3377 (schema_capsule, array_capsule) = obj.__arrow_c_array__()
3378 _im = core.new_arrow(mode, size, schema_capsule, array_capsule)
3379 if _im:
3380 return Image()._new(_im)
3382 msg = "new_arrow returned None without an exception"
3383 raise ValueError(msg)
3386def fromqimage(im: ImageQt.QImage) -> ImageFile.ImageFile:
3387 """Creates an image instance from a QImage image"""
3388 from . import ImageQt
3390 if not ImageQt.qt_is_installed:
3391 msg = "Qt bindings are not installed"
3392 raise ImportError(msg)
3393 return ImageQt.fromqimage(im)
3396def fromqpixmap(im: ImageQt.QPixmap) -> ImageFile.ImageFile:
3397 """Creates an image instance from a QPixmap image"""
3398 from . import ImageQt
3400 if not ImageQt.qt_is_installed:
3401 msg = "Qt bindings are not installed"
3402 raise ImportError(msg)
3403 return ImageQt.fromqpixmap(im)
3406_fromarray_typemap = {
3407 # (shape, typestr) => mode, rawmode
3408 # first two members of shape are set to one
3409 ((1, 1), "|b1"): ("1", "1;8"),
3410 ((1, 1), "|u1"): ("L", "L"),
3411 ((1, 1), "|i1"): ("I", "I;8"),
3412 ((1, 1), "<u2"): ("I", "I;16"),
3413 ((1, 1), ">u2"): ("I", "I;16B"),
3414 ((1, 1), "<i2"): ("I", "I;16S"),
3415 ((1, 1), ">i2"): ("I", "I;16BS"),
3416 ((1, 1), "<u4"): ("I", "I;32"),
3417 ((1, 1), ">u4"): ("I", "I;32B"),
3418 ((1, 1), "<i4"): ("I", "I;32S"),
3419 ((1, 1), ">i4"): ("I", "I;32BS"),
3420 ((1, 1), "<f4"): ("F", "F;32F"),
3421 ((1, 1), ">f4"): ("F", "F;32BF"),
3422 ((1, 1), "<f8"): ("F", "F;64F"),
3423 ((1, 1), ">f8"): ("F", "F;64BF"),
3424 ((1, 1, 2), "|u1"): ("LA", "LA"),
3425 ((1, 1, 3), "|u1"): ("RGB", "RGB"),
3426 ((1, 1, 4), "|u1"): ("RGBA", "RGBA"),
3427 # shortcuts:
3428 ((1, 1), f"{_ENDIAN}i4"): ("I", "I"),
3429 ((1, 1), f"{_ENDIAN}f4"): ("F", "F"),
3430}
3433def _decompression_bomb_check(size: tuple[int, int]) -> None:
3434 if MAX_IMAGE_PIXELS is None:
3435 return
3437 pixels = max(1, size[0]) * max(1, size[1])
3439 if pixels > 2 * MAX_IMAGE_PIXELS:
3440 msg = (
3441 f"Image size ({pixels} pixels) exceeds limit of {2 * MAX_IMAGE_PIXELS} "
3442 "pixels, could be decompression bomb DOS attack."
3443 )
3444 raise DecompressionBombError(msg)
3446 if pixels > MAX_IMAGE_PIXELS:
3447 warnings.warn(
3448 f"Image size ({pixels} pixels) exceeds limit of {MAX_IMAGE_PIXELS} pixels, "
3449 "could be decompression bomb DOS attack.",
3450 DecompressionBombWarning,
3451 )
3454def open(
3455 fp: StrOrBytesPath | IO[bytes],
3456 mode: Literal["r"] = "r",
3457 formats: list[str] | tuple[str, ...] | None = None,
3458) -> ImageFile.ImageFile:
3459 """
3460 Opens and identifies the given image file.
3462 This is a lazy operation; this function identifies the file, but
3463 the file remains open and the actual image data is not read from
3464 the file until you try to process the data (or call the
3465 :py:meth:`~PIL.Image.Image.load` method). See
3466 :py:func:`~PIL.Image.new`. See :ref:`file-handling`.
3468 :param fp: A filename (string), os.PathLike object or a file object.
3469 The file object must implement ``file.read``,
3470 ``file.seek``, and ``file.tell`` methods,
3471 and be opened in binary mode. The file object will also seek to zero
3472 before reading.
3473 :param mode: The mode. If given, this argument must be "r".
3474 :param formats: A list or tuple of formats to attempt to load the file in.
3475 This can be used to restrict the set of formats checked.
3476 Pass ``None`` to try all supported formats. You can print the set of
3477 available formats by running ``python3 -m PIL`` or using
3478 the :py:func:`PIL.features.pilinfo` function.
3479 :returns: An :py:class:`~PIL.Image.Image` object.
3480 :exception FileNotFoundError: If the file cannot be found.
3481 :exception PIL.UnidentifiedImageError: If the image cannot be opened and
3482 identified.
3483 :exception ValueError: If the ``mode`` is not "r", or if a ``StringIO``
3484 instance is used for ``fp``.
3485 :exception TypeError: If ``formats`` is not ``None``, a list or a tuple.
3486 """
3488 if mode != "r":
3489 msg = f"bad mode {repr(mode)}" # type: ignore[unreachable]
3490 raise ValueError(msg)
3491 elif isinstance(fp, io.StringIO):
3492 msg = ( # type: ignore[unreachable]
3493 "StringIO cannot be used to open an image. "
3494 "Binary data must be used instead."
3495 )
3496 raise ValueError(msg)
3498 if formats is None:
3499 formats = ID
3500 elif not isinstance(formats, (list, tuple)):
3501 msg = "formats must be a list or tuple" # type: ignore[unreachable]
3502 raise TypeError(msg)
3504 exclusive_fp = False
3505 filename: str | bytes = ""
3506 if is_path(fp):
3507 filename = os.fspath(fp)
3509 if filename:
3510 fp = builtins.open(filename, "rb")
3511 exclusive_fp = True
3512 else:
3513 fp = cast(IO[bytes], fp)
3515 try:
3516 fp.seek(0)
3517 except (AttributeError, io.UnsupportedOperation):
3518 fp = io.BytesIO(fp.read())
3519 exclusive_fp = True
3521 prefix = fp.read(16)
3523 preinit()
3525 warning_messages: list[str] = []
3527 def _open_core(
3528 fp: IO[bytes],
3529 filename: str | bytes,
3530 prefix: bytes,
3531 formats: list[str] | tuple[str, ...],
3532 ) -> ImageFile.ImageFile | None:
3533 for i in formats:
3534 i = i.upper()
3535 if i not in OPEN:
3536 init()
3537 try:
3538 factory, accept = OPEN[i]
3539 result = not accept or accept(prefix)
3540 if isinstance(result, str):
3541 warning_messages.append(result)
3542 elif result:
3543 fp.seek(0)
3544 im = factory(fp, filename)
3545 _decompression_bomb_check(im.size)
3546 return im
3547 except (SyntaxError, IndexError, TypeError, struct.error) as e:
3548 if WARN_POSSIBLE_FORMATS:
3549 warning_messages.append(i + " opening failed. " + str(e))
3550 except BaseException:
3551 if exclusive_fp:
3552 fp.close()
3553 raise
3554 return None
3556 im = _open_core(fp, filename, prefix, formats)
3558 if im is None and formats is ID:
3559 checked_formats = ID.copy()
3560 if init():
3561 im = _open_core(
3562 fp,
3563 filename,
3564 prefix,
3565 tuple(format for format in formats if format not in checked_formats),
3566 )
3568 if im:
3569 im._exclusive_fp = exclusive_fp
3570 return im
3572 if exclusive_fp:
3573 fp.close()
3574 for message in warning_messages:
3575 warnings.warn(message)
3576 msg = "cannot identify image file %r" % (filename if filename else fp)
3577 raise UnidentifiedImageError(msg)
3580#
3581# Image processing.
3584def alpha_composite(im1: Image, im2: Image) -> Image:
3585 """
3586 Alpha composite im2 over im1.
3588 :param im1: The first image. Must have mode RGBA.
3589 :param im2: The second image. Must have mode RGBA, and the same size as
3590 the first image.
3591 :returns: An :py:class:`~PIL.Image.Image` object.
3592 """
3594 im1.load()
3595 im2.load()
3596 return im1._new(core.alpha_composite(im1.im, im2.im))
3599def blend(im1: Image, im2: Image, alpha: float) -> Image:
3600 """
3601 Creates a new image by interpolating between two input images, using
3602 a constant alpha::
3604 out = image1 * (1.0 - alpha) + image2 * alpha
3606 :param im1: The first image.
3607 :param im2: The second image. Must have the same mode and size as
3608 the first image.
3609 :param alpha: The interpolation alpha factor. If alpha is 0.0, a
3610 copy of the first image is returned. If alpha is 1.0, a copy of
3611 the second image is returned. There are no restrictions on the
3612 alpha value. If necessary, the result is clipped to fit into
3613 the allowed output range.
3614 :returns: An :py:class:`~PIL.Image.Image` object.
3615 """
3617 im1.load()
3618 im2.load()
3619 return im1._new(core.blend(im1.im, im2.im, alpha))
3622def composite(image1: Image, image2: Image, mask: Image) -> Image:
3623 """
3624 Create composite image by blending images using a transparency mask.
3626 :param image1: The first image.
3627 :param image2: The second image. Must have the same mode and
3628 size as the first image.
3629 :param mask: A mask image. This image can have mode
3630 "1", "L", or "RGBA", and must have the same size as the
3631 other two images.
3632 """
3634 image = image2.copy()
3635 image.paste(image1, None, mask)
3636 return image
3639def eval(image: Image, *args: Callable[[int], float]) -> Image:
3640 """
3641 Applies the function (which should take one argument) to each pixel
3642 in the given image. If the image has more than one band, the same
3643 function is applied to each band. Note that the function is
3644 evaluated once for each possible pixel value, so you cannot use
3645 random components or other generators.
3647 :param image: The input image.
3648 :param function: A function object, taking one integer argument.
3649 :returns: An :py:class:`~PIL.Image.Image` object.
3650 """
3652 return image.point(args[0])
3655def merge(mode: str, bands: Sequence[Image]) -> Image:
3656 """
3657 Merge a set of single band images into a new multiband image.
3659 :param mode: The mode to use for the output image. See:
3660 :ref:`concept-modes`.
3661 :param bands: A sequence containing one single-band image for
3662 each band in the output image. All bands must have the
3663 same size.
3664 :returns: An :py:class:`~PIL.Image.Image` object.
3665 """
3667 if getmodebands(mode) != len(bands) or "*" in mode:
3668 msg = "wrong number of bands"
3669 raise ValueError(msg)
3670 for band in bands[1:]:
3671 if band.mode != getmodetype(mode):
3672 msg = "mode mismatch"
3673 raise ValueError(msg)
3674 if band.size != bands[0].size:
3675 msg = "size mismatch"
3676 raise ValueError(msg)
3677 for band in bands:
3678 band.load()
3679 return bands[0]._new(core.merge(mode, *[b.im for b in bands]))
3682# --------------------------------------------------------------------
3683# Plugin registry
3686def register_open(
3687 id: str,
3688 factory: (
3689 Callable[[IO[bytes], str | bytes], ImageFile.ImageFile]
3690 | type[ImageFile.ImageFile]
3691 ),
3692 accept: Callable[[bytes], bool | str] | None = None,
3693) -> None:
3694 """
3695 Register an image file plugin. This function should not be used
3696 in application code.
3698 :param id: An image format identifier.
3699 :param factory: An image file factory method.
3700 :param accept: An optional function that can be used to quickly
3701 reject images having another format.
3702 """
3703 id = id.upper()
3704 if id not in ID:
3705 ID.append(id)
3706 OPEN[id] = factory, accept
3709def register_mime(id: str, mimetype: str) -> None:
3710 """
3711 Registers an image MIME type by populating ``Image.MIME``. This function
3712 should not be used in application code.
3714 ``Image.MIME`` provides a mapping from image format identifiers to mime
3715 formats, but :py:meth:`~PIL.ImageFile.ImageFile.get_format_mimetype` can
3716 provide a different result for specific images.
3718 :param id: An image format identifier.
3719 :param mimetype: The image MIME type for this format.
3720 """
3721 MIME[id.upper()] = mimetype
3724def register_save(
3725 id: str, driver: Callable[[Image, IO[bytes], str | bytes], None]
3726) -> None:
3727 """
3728 Registers an image save function. This function should not be
3729 used in application code.
3731 :param id: An image format identifier.
3732 :param driver: A function to save images in this format.
3733 """
3734 SAVE[id.upper()] = driver
3737def register_save_all(
3738 id: str, driver: Callable[[Image, IO[bytes], str | bytes], None]
3739) -> None:
3740 """
3741 Registers an image function to save all the frames
3742 of a multiframe format. This function should not be
3743 used in application code.
3745 :param id: An image format identifier.
3746 :param driver: A function to save images in this format.
3747 """
3748 SAVE_ALL[id.upper()] = driver
3751def register_extension(id: str, extension: str) -> None:
3752 """
3753 Registers an image extension. This function should not be
3754 used in application code.
3756 :param id: An image format identifier.
3757 :param extension: An extension used for this format.
3758 """
3759 EXTENSION[extension.lower()] = id.upper()
3762def register_extensions(id: str, extensions: list[str]) -> None:
3763 """
3764 Registers image extensions. This function should not be
3765 used in application code.
3767 :param id: An image format identifier.
3768 :param extensions: A list of extensions used for this format.
3769 """
3770 for extension in extensions:
3771 register_extension(id, extension)
3774def registered_extensions() -> dict[str, str]:
3775 """
3776 Returns a dictionary containing all file extensions belonging
3777 to registered plugins
3778 """
3779 init()
3780 return EXTENSION
3783def register_decoder(name: str, decoder: type[ImageFile.PyDecoder]) -> None:
3784 """
3785 Registers an image decoder. This function should not be
3786 used in application code.
3788 :param name: The name of the decoder
3789 :param decoder: An ImageFile.PyDecoder object
3791 .. versionadded:: 4.1.0
3792 """
3793 DECODERS[name] = decoder
3796def register_encoder(name: str, encoder: type[ImageFile.PyEncoder]) -> None:
3797 """
3798 Registers an image encoder. This function should not be
3799 used in application code.
3801 :param name: The name of the encoder
3802 :param encoder: An ImageFile.PyEncoder object
3804 .. versionadded:: 4.1.0
3805 """
3806 ENCODERS[name] = encoder
3809# --------------------------------------------------------------------
3810# Simple display support.
3813def _show(image: Image, **options: Any) -> None:
3814 from . import ImageShow
3816 ImageShow.show(image, **options)
3819# --------------------------------------------------------------------
3820# Effects
3823def effect_mandelbrot(
3824 size: tuple[int, int], extent: tuple[float, float, float, float], quality: int
3825) -> Image:
3826 """
3827 Generate a Mandelbrot set covering the given extent.
3829 :param size: The requested size in pixels, as a 2-tuple:
3830 (width, height).
3831 :param extent: The extent to cover, as a 4-tuple:
3832 (x0, y0, x1, y1).
3833 :param quality: Quality.
3834 """
3835 return Image()._new(core.effect_mandelbrot(size, extent, quality))
3838def effect_noise(size: tuple[int, int], sigma: float) -> Image:
3839 """
3840 Generate Gaussian noise centered around 128.
3842 :param size: The requested size in pixels, as a 2-tuple:
3843 (width, height).
3844 :param sigma: Standard deviation of noise.
3845 """
3846 return Image()._new(core.effect_noise(size, sigma))
3849def linear_gradient(mode: str) -> Image:
3850 """
3851 Generate 256x256 linear gradient from black to white, top to bottom.
3853 :param mode: Input mode.
3854 """
3855 return Image()._new(core.linear_gradient(mode))
3858def radial_gradient(mode: str) -> Image:
3859 """
3860 Generate 256x256 radial gradient from black to white, centre to edge.
3862 :param mode: Input mode.
3863 """
3864 return Image()._new(core.radial_gradient(mode))
3867# --------------------------------------------------------------------
3868# Resources
3871def _apply_env_variables(env: dict[str, str] | None = None) -> None:
3872 env_dict = env if env is not None else os.environ
3874 for var_name, setter in [
3875 ("PILLOW_ALIGNMENT", core.set_alignment),
3876 ("PILLOW_BLOCK_SIZE", core.set_block_size),
3877 ("PILLOW_BLOCKS_MAX", core.set_blocks_max),
3878 ]:
3879 if var_name not in env_dict:
3880 continue
3882 var = env_dict[var_name].lower()
3884 units = 1
3885 for postfix, mul in [("k", 1024), ("m", 1024 * 1024)]:
3886 if var.endswith(postfix):
3887 units = mul
3888 var = var[: -len(postfix)]
3890 try:
3891 var_int = int(var) * units
3892 except ValueError:
3893 warnings.warn(f"{var_name} is not int")
3894 continue
3896 try:
3897 setter(var_int)
3898 except ValueError as e:
3899 warnings.warn(f"{var_name}: {e}")
3902_apply_env_variables()
3903atexit.register(core.clear_cache)
3906if TYPE_CHECKING:
3907 _ExifBase = MutableMapping[int, Any]
3908else:
3909 _ExifBase = MutableMapping
3912class Exif(_ExifBase):
3913 """
3914 This class provides read and write access to EXIF image data::
3916 from PIL import Image
3917 im = Image.open("exif.png")
3918 exif = im.getexif() # Returns an instance of this class
3920 Information can be read and written, iterated over or deleted::
3922 print(exif[274]) # 1
3923 exif[274] = 2
3924 for k, v in exif.items():
3925 print("Tag", k, "Value", v) # Tag 274 Value 2
3926 del exif[274]
3928 To access information beyond IFD0, :py:meth:`~PIL.Image.Exif.get_ifd`
3929 returns a dictionary::
3931 from PIL import ExifTags
3932 im = Image.open("exif_gps.jpg")
3933 exif = im.getexif()
3934 gps_ifd = exif.get_ifd(ExifTags.IFD.GPSInfo)
3935 print(gps_ifd)
3937 Other IFDs include ``ExifTags.IFD.Exif``, ``ExifTags.IFD.MakerNote``,
3938 ``ExifTags.IFD.Interop`` and ``ExifTags.IFD.IFD1``.
3940 :py:mod:`~PIL.ExifTags` also has enum classes to provide names for data::
3942 print(exif[ExifTags.Base.Software]) # PIL
3943 print(gps_ifd[ExifTags.GPS.GPSDateStamp]) # 1999:99:99 99:99:99
3944 """
3946 endian: str | None = None
3947 bigtiff = False
3948 _loaded = False
3950 def __init__(self) -> None:
3951 self._data: dict[int, Any] = {}
3952 self._hidden_data: dict[int, Any] = {}
3953 self._ifds: dict[int, dict[int, Any]] = {}
3954 self._info: TiffImagePlugin.ImageFileDirectory_v2 | None = None
3955 self._loaded_exif: bytes | None = None
3957 def _fixup(self, value: Any) -> Any:
3958 try:
3959 if len(value) == 1 and isinstance(value, tuple):
3960 return value[0]
3961 except Exception:
3962 pass
3963 return value
3965 def _fixup_dict(self, src_dict: dict[int, Any]) -> dict[int, Any]:
3966 # Helper function
3967 # returns a dict with any single item tuples/lists as individual values
3968 return {k: self._fixup(v) for k, v in src_dict.items()}
3970 def _get_ifd_dict(
3971 self, offset: int, group: int | None = None
3972 ) -> dict[int, Any] | None:
3973 try:
3974 # an offset pointer to the location of the nested embedded IFD.
3975 # It should be a long, but may be corrupted.
3976 self.fp.seek(offset)
3977 except (KeyError, TypeError):
3978 return None
3979 else:
3980 from . import TiffImagePlugin
3982 info = TiffImagePlugin.ImageFileDirectory_v2(self.head, group=group)
3983 info.load(self.fp)
3984 return self._fixup_dict(dict(info))
3986 def _get_head(self) -> bytes:
3987 version = b"\x2b" if self.bigtiff else b"\x2a"
3988 if self.endian == "<":
3989 head = b"II" + version + b"\x00" + o32le(8)
3990 else:
3991 head = b"MM\x00" + version + o32be(8)
3992 if self.bigtiff:
3993 head += o32le(8) if self.endian == "<" else o32be(8)
3994 head += b"\x00\x00\x00\x00"
3995 return head
3997 def load(self, data: bytes) -> None:
3998 # Extract EXIF information. This is highly experimental,
3999 # and is likely to be replaced with something better in a future
4000 # version.
4002 # The EXIF record consists of a TIFF file embedded in a JPEG
4003 # application marker (!).
4004 if data == self._loaded_exif:
4005 return
4006 self._loaded_exif = data
4007 self._data.clear()
4008 self._hidden_data.clear()
4009 self._ifds.clear()
4010 while data and data.startswith(b"Exif\x00\x00"):
4011 data = data[6:]
4012 if not data:
4013 self._info = None
4014 return
4016 self.fp: IO[bytes] = io.BytesIO(data)
4017 self.head = self.fp.read(8)
4018 # process dictionary
4019 from . import TiffImagePlugin
4021 self._info = TiffImagePlugin.ImageFileDirectory_v2(self.head)
4022 self.endian = self._info._endian
4023 self.fp.seek(self._info.next)
4024 self._info.load(self.fp)
4026 def load_from_fp(self, fp: IO[bytes], offset: int | None = None) -> None:
4027 self._loaded_exif = None
4028 self._data.clear()
4029 self._hidden_data.clear()
4030 self._ifds.clear()
4032 # process dictionary
4033 from . import TiffImagePlugin
4035 self.fp = fp
4036 if offset is not None:
4037 self.head = self._get_head()
4038 else:
4039 self.head = self.fp.read(8)
4040 self._info = TiffImagePlugin.ImageFileDirectory_v2(self.head)
4041 if self.endian is None:
4042 self.endian = self._info._endian
4043 if offset is None:
4044 offset = self._info.next
4045 self.fp.tell()
4046 self.fp.seek(offset)
4047 self._info.load(self.fp)
4049 def _get_merged_dict(self) -> dict[int, Any]:
4050 merged_dict = dict(self)
4052 # get EXIF extension
4053 if ExifTags.IFD.Exif in self:
4054 ifd = self._get_ifd_dict(self[ExifTags.IFD.Exif], ExifTags.IFD.Exif)
4055 if ifd:
4056 merged_dict.update(ifd)
4058 # GPS
4059 if ExifTags.IFD.GPSInfo in self:
4060 merged_dict[ExifTags.IFD.GPSInfo] = self._get_ifd_dict(
4061 self[ExifTags.IFD.GPSInfo], ExifTags.IFD.GPSInfo
4062 )
4064 return merged_dict
4066 def tobytes(self, offset: int = 8) -> bytes:
4067 from . import TiffImagePlugin
4069 head = self._get_head()
4070 ifd = TiffImagePlugin.ImageFileDirectory_v2(ifh=head)
4071 for tag, ifd_dict in self._ifds.items():
4072 if tag not in self:
4073 ifd[tag] = ifd_dict
4074 for tag, value in self.items():
4075 if tag in [
4076 ExifTags.IFD.Exif,
4077 ExifTags.IFD.GPSInfo,
4078 ] and not isinstance(value, dict):
4079 value = self.get_ifd(tag)
4080 if (
4081 tag == ExifTags.IFD.Exif
4082 and ExifTags.IFD.Interop in value
4083 and not isinstance(value[ExifTags.IFD.Interop], dict)
4084 ):
4085 value = value.copy()
4086 value[ExifTags.IFD.Interop] = self.get_ifd(ExifTags.IFD.Interop)
4087 ifd[tag] = value
4088 return b"Exif\x00\x00" + head + ifd.tobytes(offset)
4090 def get_ifd(self, tag: int) -> dict[int, Any]:
4091 if tag not in self._ifds:
4092 if tag == ExifTags.IFD.IFD1:
4093 if self._info is not None and self._info.next != 0:
4094 ifd = self._get_ifd_dict(self._info.next)
4095 if ifd is not None:
4096 self._ifds[tag] = ifd
4097 elif tag in [ExifTags.IFD.Exif, ExifTags.IFD.GPSInfo]:
4098 offset = self._hidden_data.get(tag, self.get(tag))
4099 if offset is not None:
4100 ifd = self._get_ifd_dict(offset, tag)
4101 if ifd is not None:
4102 self._ifds[tag] = ifd
4103 elif tag in [ExifTags.IFD.Interop, ExifTags.IFD.MakerNote]:
4104 if ExifTags.IFD.Exif not in self._ifds:
4105 self.get_ifd(ExifTags.IFD.Exif)
4106 tag_data = self._ifds[ExifTags.IFD.Exif][tag]
4107 if tag == ExifTags.IFD.MakerNote:
4108 from .TiffImagePlugin import ImageFileDirectory_v2
4110 if tag_data.startswith(b"FUJIFILM"):
4111 ifd_offset = i32le(tag_data, 8)
4112 ifd_data = tag_data[ifd_offset:]
4114 makernote = {}
4115 for i in range(struct.unpack("<H", ifd_data[:2])[0]):
4116 ifd_tag, typ, count, data = struct.unpack(
4117 "<HHL4s", ifd_data[i * 12 + 2 : (i + 1) * 12 + 2]
4118 )
4119 try:
4120 (
4121 unit_size,
4122 handler,
4123 ) = ImageFileDirectory_v2._load_dispatch[typ]
4124 except KeyError:
4125 continue
4126 size = count * unit_size
4127 if size > 4:
4128 (offset,) = struct.unpack("<L", data)
4129 data = ifd_data[offset - 12 : offset + size - 12]
4130 else:
4131 data = data[:size]
4133 if len(data) != size:
4134 warnings.warn(
4135 "Possibly corrupt EXIF MakerNote data. "
4136 f"Expecting to read {size} bytes but only got "
4137 f"{len(data)}. Skipping tag {ifd_tag}"
4138 )
4139 continue
4141 if not data:
4142 continue
4144 makernote[ifd_tag] = handler(
4145 ImageFileDirectory_v2(), data, False
4146 )
4147 self._ifds[tag] = dict(self._fixup_dict(makernote))
4148 elif self.get(0x010F) == "Nintendo":
4149 makernote = {}
4150 for i in range(struct.unpack(">H", tag_data[:2])[0]):
4151 ifd_tag, typ, count, data = struct.unpack(
4152 ">HHL4s", tag_data[i * 12 + 2 : (i + 1) * 12 + 2]
4153 )
4154 if ifd_tag == 0x1101:
4155 # CameraInfo
4156 (offset,) = struct.unpack(">L", data)
4157 self.fp.seek(offset)
4159 camerainfo: dict[str, int | bytes] = {
4160 "ModelID": self.fp.read(4)
4161 }
4163 self.fp.read(4)
4164 # Seconds since 2000
4165 camerainfo["TimeStamp"] = i32le(self.fp.read(12))
4167 self.fp.read(4)
4168 camerainfo["InternalSerialNumber"] = self.fp.read(4)
4170 self.fp.read(12)
4171 parallax = self.fp.read(4)
4172 handler = ImageFileDirectory_v2._load_dispatch[
4173 TiffTags.FLOAT
4174 ][1]
4175 camerainfo["Parallax"] = handler(
4176 ImageFileDirectory_v2(), parallax, False
4177 )[0]
4179 self.fp.read(4)
4180 camerainfo["Category"] = self.fp.read(2)
4182 makernote = {0x1101: camerainfo}
4183 self._ifds[tag] = makernote
4184 else:
4185 # Interop
4186 ifd = self._get_ifd_dict(tag_data, tag)
4187 if ifd is not None:
4188 self._ifds[tag] = ifd
4189 ifd = self._ifds.setdefault(tag, {})
4190 if tag == ExifTags.IFD.Exif and self._hidden_data:
4191 ifd = {
4192 k: v
4193 for (k, v) in ifd.items()
4194 if k not in (ExifTags.IFD.Interop, ExifTags.IFD.MakerNote)
4195 }
4196 return ifd
4198 def hide_offsets(self) -> None:
4199 for tag in (ExifTags.IFD.Exif, ExifTags.IFD.GPSInfo):
4200 if tag in self:
4201 self._hidden_data[tag] = self[tag]
4202 del self[tag]
4204 def __str__(self) -> str:
4205 if self._info is not None:
4206 # Load all keys into self._data
4207 for tag in self._info:
4208 self[tag]
4210 return str(self._data)
4212 def __len__(self) -> int:
4213 keys = set(self._data)
4214 if self._info is not None:
4215 keys.update(self._info)
4216 return len(keys)
4218 def __getitem__(self, tag: int) -> Any:
4219 if self._info is not None and tag not in self._data and tag in self._info:
4220 self._data[tag] = self._fixup(self._info[tag])
4221 del self._info[tag]
4222 return self._data[tag]
4224 def __contains__(self, tag: object) -> bool:
4225 return tag in self._data or (self._info is not None and tag in self._info)
4227 def __setitem__(self, tag: int, value: Any) -> None:
4228 if self._info is not None and tag in self._info:
4229 del self._info[tag]
4230 self._data[tag] = value
4232 def __delitem__(self, tag: int) -> None:
4233 if self._info is not None and tag in self._info:
4234 del self._info[tag]
4235 else:
4236 del self._data[tag]
4238 def __iter__(self) -> Iterator[int]:
4239 keys = set(self._data)
4240 if self._info is not None:
4241 keys.update(self._info)
4242 return iter(keys)