Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/PIL/Image.py: 17%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
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 (
45 IO,
46 TYPE_CHECKING,
47 Any,
48 Literal,
49 Protocol,
50 cast,
51)
53# VERSION was removed in Pillow 6.0.0.
54# PILLOW_VERSION was removed in Pillow 9.0.0.
55# Use __version__ instead.
56from . import (
57 ExifTags,
58 ImageMode,
59 TiffTags,
60 UnidentifiedImageError,
61 __version__,
62 _plugins,
63)
64from ._binary import i32le, o32be, o32le
65from ._deprecate import deprecate
66from ._util import DeferredError, is_path
68ElementTree: ModuleType | None
69try:
70 from defusedxml import ElementTree
71except ImportError:
72 ElementTree = None
74logger = logging.getLogger(__name__)
77class DecompressionBombWarning(RuntimeWarning):
78 pass
81class DecompressionBombError(Exception):
82 pass
85WARN_POSSIBLE_FORMATS: bool = False
87# Limit to around a quarter gigabyte for a 24-bit (3 bpp) image
88MAX_IMAGE_PIXELS: int | None = int(1024 * 1024 * 1024 // 4 // 3)
91try:
92 # If the _imaging C module is not present, Pillow will not load.
93 # Note that other modules should not refer to _imaging directly;
94 # import Image and use the Image.core variable instead.
95 # Also note that Image.core is not a publicly documented interface,
96 # and should be considered private and subject to change.
97 from . import _imaging as core
99 if __version__ != getattr(core, "PILLOW_VERSION", None):
100 msg = (
101 "The _imaging extension was built for another version of Pillow or PIL:\n"
102 f"Core version: {getattr(core, 'PILLOW_VERSION', None)}\n"
103 f"Pillow version: {__version__}"
104 )
105 raise ImportError(msg)
107except ImportError as v:
108 core = DeferredError.new(ImportError("The _imaging C module is not installed."))
109 # Explanations for ways that we know we might have an import error
110 if str(v).startswith("Module use of python"):
111 # The _imaging C module is present, but not compiled for
112 # the right version (windows only). Print a warning, if
113 # possible.
114 warnings.warn(
115 "The _imaging extension was built for another version of Python.",
116 RuntimeWarning,
117 )
118 elif str(v).startswith("The _imaging extension"):
119 warnings.warn(str(v), RuntimeWarning)
120 # Fail here anyway. Don't let people run with a mostly broken Pillow.
121 # see docs/porting.rst
122 raise
125def isImageType(t: Any) -> TypeGuard[Image]:
126 """
127 Checks if an object is an image object.
129 .. warning::
131 This function is for internal use only.
133 :param t: object to check if it's an image
134 :returns: True if the object is an image
135 """
136 deprecate("Image.isImageType(im)", 12, "isinstance(im, Image.Image)")
137 return hasattr(t, "im")
140#
141# Constants
144# transpose
145class Transpose(IntEnum):
146 FLIP_LEFT_RIGHT = 0
147 FLIP_TOP_BOTTOM = 1
148 ROTATE_90 = 2
149 ROTATE_180 = 3
150 ROTATE_270 = 4
151 TRANSPOSE = 5
152 TRANSVERSE = 6
155# transforms (also defined in Imaging.h)
156class Transform(IntEnum):
157 AFFINE = 0
158 EXTENT = 1
159 PERSPECTIVE = 2
160 QUAD = 3
161 MESH = 4
164# resampling filters (also defined in Imaging.h)
165class Resampling(IntEnum):
166 NEAREST = 0
167 BOX = 4
168 BILINEAR = 2
169 HAMMING = 5
170 BICUBIC = 3
171 LANCZOS = 1
174_filters_support = {
175 Resampling.BOX: 0.5,
176 Resampling.BILINEAR: 1.0,
177 Resampling.HAMMING: 1.0,
178 Resampling.BICUBIC: 2.0,
179 Resampling.LANCZOS: 3.0,
180}
183# dithers
184class Dither(IntEnum):
185 NONE = 0
186 ORDERED = 1 # Not yet implemented
187 RASTERIZE = 2 # Not yet implemented
188 FLOYDSTEINBERG = 3 # default
191# palettes/quantizers
192class Palette(IntEnum):
193 WEB = 0
194 ADAPTIVE = 1
197class Quantize(IntEnum):
198 MEDIANCUT = 0
199 MAXCOVERAGE = 1
200 FASTOCTREE = 2
201 LIBIMAGEQUANT = 3
204module = sys.modules[__name__]
205for enum in (Transpose, Transform, Resampling, Dither, Palette, Quantize):
206 for item in enum:
207 setattr(module, item.name, item.value)
210if hasattr(core, "DEFAULT_STRATEGY"):
211 DEFAULT_STRATEGY = core.DEFAULT_STRATEGY
212 FILTERED = core.FILTERED
213 HUFFMAN_ONLY = core.HUFFMAN_ONLY
214 RLE = core.RLE
215 FIXED = core.FIXED
218# --------------------------------------------------------------------
219# Registries
221if TYPE_CHECKING:
222 import mmap
223 from xml.etree.ElementTree import Element
225 from IPython.lib.pretty import PrettyPrinter
227 from . import ImageFile, ImageFilter, ImagePalette, ImageQt, TiffImagePlugin
228 from ._typing import CapsuleType, NumpyArray, StrOrBytesPath, TypeGuard
229ID: list[str] = []
230OPEN: dict[
231 str,
232 tuple[
233 Callable[[IO[bytes], str | bytes], ImageFile.ImageFile],
234 Callable[[bytes], bool | str] | None,
235 ],
236] = {}
237MIME: dict[str, str] = {}
238SAVE: dict[str, Callable[[Image, IO[bytes], str | bytes], None]] = {}
239SAVE_ALL: dict[str, Callable[[Image, IO[bytes], str | bytes], None]] = {}
240EXTENSION: dict[str, str] = {}
241DECODERS: dict[str, type[ImageFile.PyDecoder]] = {}
242ENCODERS: dict[str, type[ImageFile.PyEncoder]] = {}
244# --------------------------------------------------------------------
245# Modes
247_ENDIAN = "<" if sys.byteorder == "little" else ">"
250def _conv_type_shape(im: Image) -> tuple[tuple[int, ...], str]:
251 m = ImageMode.getmode(im.mode)
252 shape: tuple[int, ...] = (im.height, im.width)
253 extra = len(m.bands)
254 if extra != 1:
255 shape += (extra,)
256 return shape, m.typestr
259MODES = [
260 "1",
261 "CMYK",
262 "F",
263 "HSV",
264 "I",
265 "I;16",
266 "I;16B",
267 "I;16L",
268 "I;16N",
269 "L",
270 "LA",
271 "La",
272 "LAB",
273 "P",
274 "PA",
275 "RGB",
276 "RGBA",
277 "RGBa",
278 "RGBX",
279 "YCbCr",
280]
282# raw modes that may be memory mapped. NOTE: if you change this, you
283# may have to modify the stride calculation in map.c too!
284_MAPMODES = ("L", "P", "RGBX", "RGBA", "CMYK", "I;16", "I;16L", "I;16B")
287def getmodebase(mode: str) -> str:
288 """
289 Gets the "base" mode for given mode. This function returns "L" for
290 images that contain grayscale data, and "RGB" for images that
291 contain color data.
293 :param mode: Input mode.
294 :returns: "L" or "RGB".
295 :exception KeyError: If the input mode was not a standard mode.
296 """
297 return ImageMode.getmode(mode).basemode
300def getmodetype(mode: str) -> str:
301 """
302 Gets the storage type mode. Given a mode, this function returns a
303 single-layer mode suitable for storing individual bands.
305 :param mode: Input mode.
306 :returns: "L", "I", or "F".
307 :exception KeyError: If the input mode was not a standard mode.
308 """
309 return ImageMode.getmode(mode).basetype
312def getmodebandnames(mode: str) -> tuple[str, ...]:
313 """
314 Gets a list of individual band names. Given a mode, this function returns
315 a tuple containing the names of individual bands (use
316 :py:method:`~PIL.Image.getmodetype` to get the mode used to store each
317 individual band.
319 :param mode: Input mode.
320 :returns: A tuple containing band names. The length of the tuple
321 gives the number of bands in an image of the given mode.
322 :exception KeyError: If the input mode was not a standard mode.
323 """
324 return ImageMode.getmode(mode).bands
327def getmodebands(mode: str) -> int:
328 """
329 Gets the number of individual bands for this mode.
331 :param mode: Input mode.
332 :returns: The number of bands in this mode.
333 :exception KeyError: If the input mode was not a standard mode.
334 """
335 return len(ImageMode.getmode(mode).bands)
338# --------------------------------------------------------------------
339# Helpers
341_initialized = 0
344def preinit() -> None:
345 """
346 Explicitly loads BMP, GIF, JPEG, PPM and PPM file format drivers.
348 It is called when opening or saving images.
349 """
351 global _initialized
352 if _initialized >= 1:
353 return
355 try:
356 from . import BmpImagePlugin
358 assert BmpImagePlugin
359 except ImportError:
360 pass
361 try:
362 from . import GifImagePlugin
364 assert GifImagePlugin
365 except ImportError:
366 pass
367 try:
368 from . import JpegImagePlugin
370 assert JpegImagePlugin
371 except ImportError:
372 pass
373 try:
374 from . import PpmImagePlugin
376 assert PpmImagePlugin
377 except ImportError:
378 pass
379 try:
380 from . import PngImagePlugin
382 assert PngImagePlugin
383 except ImportError:
384 pass
386 _initialized = 1
389def init() -> bool:
390 """
391 Explicitly initializes the Python Imaging Library. This function
392 loads all available file format drivers.
394 It is called when opening or saving images if :py:meth:`~preinit()` is
395 insufficient, and by :py:meth:`~PIL.features.pilinfo`.
396 """
398 global _initialized
399 if _initialized >= 2:
400 return False
402 parent_name = __name__.rpartition(".")[0]
403 for plugin in _plugins:
404 try:
405 logger.debug("Importing %s", plugin)
406 __import__(f"{parent_name}.{plugin}", globals(), locals(), [])
407 except ImportError as e:
408 logger.debug("Image: failed to import %s: %s", plugin, e)
410 if OPEN or SAVE:
411 _initialized = 2
412 return True
413 return False
416# --------------------------------------------------------------------
417# Codec factories (used by tobytes/frombytes and ImageFile.load)
420def _getdecoder(
421 mode: str, decoder_name: str, args: Any, extra: tuple[Any, ...] = ()
422) -> core.ImagingDecoder | ImageFile.PyDecoder:
423 # tweak arguments
424 if args is None:
425 args = ()
426 elif not isinstance(args, tuple):
427 args = (args,)
429 try:
430 decoder = DECODERS[decoder_name]
431 except KeyError:
432 pass
433 else:
434 return decoder(mode, *args + extra)
436 try:
437 # get decoder
438 decoder = getattr(core, f"{decoder_name}_decoder")
439 except AttributeError as e:
440 msg = f"decoder {decoder_name} not available"
441 raise OSError(msg) from e
442 return decoder(mode, *args + extra)
445def _getencoder(
446 mode: str, encoder_name: str, args: Any, extra: tuple[Any, ...] = ()
447) -> core.ImagingEncoder | ImageFile.PyEncoder:
448 # tweak arguments
449 if args is None:
450 args = ()
451 elif not isinstance(args, tuple):
452 args = (args,)
454 try:
455 encoder = ENCODERS[encoder_name]
456 except KeyError:
457 pass
458 else:
459 return encoder(mode, *args + extra)
461 try:
462 # get encoder
463 encoder = getattr(core, f"{encoder_name}_encoder")
464 except AttributeError as e:
465 msg = f"encoder {encoder_name} not available"
466 raise OSError(msg) from e
467 return encoder(mode, *args + extra)
470# --------------------------------------------------------------------
471# Simple expression analyzer
474class ImagePointTransform:
475 """
476 Used with :py:meth:`~PIL.Image.Image.point` for single band images with more than
477 8 bits, this represents an affine transformation, where the value is multiplied by
478 ``scale`` and ``offset`` is added.
479 """
481 def __init__(self, scale: float, offset: float) -> None:
482 self.scale = scale
483 self.offset = offset
485 def __neg__(self) -> ImagePointTransform:
486 return ImagePointTransform(-self.scale, -self.offset)
488 def __add__(self, other: ImagePointTransform | float) -> ImagePointTransform:
489 if isinstance(other, ImagePointTransform):
490 return ImagePointTransform(
491 self.scale + other.scale, self.offset + other.offset
492 )
493 return ImagePointTransform(self.scale, self.offset + other)
495 __radd__ = __add__
497 def __sub__(self, other: ImagePointTransform | float) -> ImagePointTransform:
498 return self + -other
500 def __rsub__(self, other: ImagePointTransform | float) -> ImagePointTransform:
501 return other + -self
503 def __mul__(self, other: ImagePointTransform | float) -> ImagePointTransform:
504 if isinstance(other, ImagePointTransform):
505 return NotImplemented
506 return ImagePointTransform(self.scale * other, self.offset * other)
508 __rmul__ = __mul__
510 def __truediv__(self, other: ImagePointTransform | float) -> ImagePointTransform:
511 if isinstance(other, ImagePointTransform):
512 return NotImplemented
513 return ImagePointTransform(self.scale / other, self.offset / other)
516def _getscaleoffset(
517 expr: Callable[[ImagePointTransform], ImagePointTransform | float]
518) -> tuple[float, float]:
519 a = expr(ImagePointTransform(1, 0))
520 return (a.scale, a.offset) if isinstance(a, ImagePointTransform) else (0, a)
523# --------------------------------------------------------------------
524# Implementation wrapper
527class SupportsGetData(Protocol):
528 def getdata(
529 self,
530 ) -> tuple[Transform, Sequence[int]]: ...
533class Image:
534 """
535 This class represents an image object. To create
536 :py:class:`~PIL.Image.Image` objects, use the appropriate factory
537 functions. There's hardly ever any reason to call the Image constructor
538 directly.
540 * :py:func:`~PIL.Image.open`
541 * :py:func:`~PIL.Image.new`
542 * :py:func:`~PIL.Image.frombytes`
543 """
545 format: str | None = None
546 format_description: str | None = None
547 _close_exclusive_fp_after_loading = True
549 def __init__(self) -> None:
550 # FIXME: take "new" parameters / other image?
551 # FIXME: turn mode and size into delegating properties?
552 self._im: core.ImagingCore | DeferredError | None = None
553 self._mode = ""
554 self._size = (0, 0)
555 self.palette: ImagePalette.ImagePalette | None = None
556 self.info: dict[str | tuple[int, int], Any] = {}
557 self.readonly = 0
558 self._exif: Exif | None = None
560 @property
561 def im(self) -> core.ImagingCore:
562 if isinstance(self._im, DeferredError):
563 raise self._im.ex
564 assert self._im is not None
565 return self._im
567 @im.setter
568 def im(self, im: core.ImagingCore) -> None:
569 self._im = im
571 @property
572 def width(self) -> int:
573 return self.size[0]
575 @property
576 def height(self) -> int:
577 return self.size[1]
579 @property
580 def size(self) -> tuple[int, int]:
581 return self._size
583 @property
584 def mode(self) -> str:
585 return self._mode
587 def _new(self, im: core.ImagingCore) -> Image:
588 new = Image()
589 new.im = im
590 new._mode = im.mode
591 new._size = im.size
592 if im.mode in ("P", "PA"):
593 if self.palette:
594 new.palette = self.palette.copy()
595 else:
596 from . import ImagePalette
598 new.palette = ImagePalette.ImagePalette()
599 new.info = self.info.copy()
600 return new
602 # Context manager support
603 def __enter__(self):
604 return self
606 def _close_fp(self):
607 if getattr(self, "_fp", False):
608 if self._fp != self.fp:
609 self._fp.close()
610 self._fp = DeferredError(ValueError("Operation on closed image"))
611 if self.fp:
612 self.fp.close()
614 def __exit__(self, *args):
615 if hasattr(self, "fp"):
616 if getattr(self, "_exclusive_fp", False):
617 self._close_fp()
618 self.fp = None
620 def close(self) -> None:
621 """
622 Closes the file pointer, if possible.
624 This operation will destroy the image core and release its memory.
625 The image data will be unusable afterward.
627 This function is required to close images that have multiple frames or
628 have not had their file read and closed by the
629 :py:meth:`~PIL.Image.Image.load` method. See :ref:`file-handling` for
630 more information.
631 """
632 if hasattr(self, "fp"):
633 try:
634 self._close_fp()
635 self.fp = None
636 except Exception as msg:
637 logger.debug("Error closing: %s", msg)
639 if getattr(self, "map", None):
640 self.map: mmap.mmap | None = None
642 # Instead of simply setting to None, we're setting up a
643 # deferred error that will better explain that the core image
644 # object is gone.
645 self._im = DeferredError(ValueError("Operation on closed image"))
647 def _copy(self) -> None:
648 self.load()
649 self.im = self.im.copy()
650 self.readonly = 0
652 def _ensure_mutable(self) -> None:
653 if self.readonly:
654 self._copy()
655 else:
656 self.load()
658 def _dump(
659 self, file: str | None = None, format: str | None = None, **options: Any
660 ) -> str:
661 suffix = ""
662 if format:
663 suffix = f".{format}"
665 if not file:
666 f, filename = tempfile.mkstemp(suffix)
667 os.close(f)
668 else:
669 filename = file
670 if not filename.endswith(suffix):
671 filename = filename + suffix
673 self.load()
675 if not format or format == "PPM":
676 self.im.save_ppm(filename)
677 else:
678 self.save(filename, format, **options)
680 return filename
682 def __eq__(self, other: object) -> bool:
683 if self.__class__ is not other.__class__:
684 return False
685 assert isinstance(other, Image)
686 return (
687 self.mode == other.mode
688 and self.size == other.size
689 and self.info == other.info
690 and self.getpalette() == other.getpalette()
691 and self.tobytes() == other.tobytes()
692 )
694 def __repr__(self) -> str:
695 return (
696 f"<{self.__class__.__module__}.{self.__class__.__name__} "
697 f"image mode={self.mode} size={self.size[0]}x{self.size[1]} "
698 f"at 0x{id(self):X}>"
699 )
701 def _repr_pretty_(self, p: PrettyPrinter, cycle: bool) -> None:
702 """IPython plain text display support"""
704 # Same as __repr__ but without unpredictable id(self),
705 # to keep Jupyter notebook `text/plain` output stable.
706 p.text(
707 f"<{self.__class__.__module__}.{self.__class__.__name__} "
708 f"image mode={self.mode} size={self.size[0]}x{self.size[1]}>"
709 )
711 def _repr_image(self, image_format: str, **kwargs: Any) -> bytes | None:
712 """Helper function for iPython display hook.
714 :param image_format: Image format.
715 :returns: image as bytes, saved into the given format.
716 """
717 b = io.BytesIO()
718 try:
719 self.save(b, image_format, **kwargs)
720 except Exception:
721 return None
722 return b.getvalue()
724 def _repr_png_(self) -> bytes | None:
725 """iPython display hook support for PNG format.
727 :returns: PNG version of the image as bytes
728 """
729 return self._repr_image("PNG", compress_level=1)
731 def _repr_jpeg_(self) -> bytes | None:
732 """iPython display hook support for JPEG format.
734 :returns: JPEG version of the image as bytes
735 """
736 return self._repr_image("JPEG")
738 @property
739 def __array_interface__(self) -> dict[str, str | bytes | int | tuple[int, ...]]:
740 # numpy array interface support
741 new: dict[str, str | bytes | int | tuple[int, ...]] = {"version": 3}
742 if self.mode == "1":
743 # Binary images need to be extended from bits to bytes
744 # See: https://github.com/python-pillow/Pillow/issues/350
745 new["data"] = self.tobytes("raw", "L")
746 else:
747 new["data"] = self.tobytes()
748 new["shape"], new["typestr"] = _conv_type_shape(self)
749 return new
751 def __getstate__(self) -> list[Any]:
752 im_data = self.tobytes() # load image first
753 return [self.info, self.mode, self.size, self.getpalette(), im_data]
755 def __setstate__(self, state: list[Any]) -> None:
756 Image.__init__(self)
757 info, mode, size, palette, data = state[:5]
758 self.info = info
759 self._mode = mode
760 self._size = size
761 self.im = core.new(mode, size)
762 if mode in ("L", "LA", "P", "PA") and palette:
763 self.putpalette(palette)
764 self.frombytes(data)
766 def tobytes(self, encoder_name: str = "raw", *args: Any) -> bytes:
767 """
768 Return image as a bytes object.
770 .. warning::
772 This method returns the raw image data from the internal
773 storage. For compressed image data (e.g. PNG, JPEG) use
774 :meth:`~.save`, with a BytesIO parameter for in-memory
775 data.
777 :param encoder_name: What encoder to use. The default is to
778 use the standard "raw" encoder.
780 A list of C encoders can be seen under
781 codecs section of the function array in
782 :file:`_imaging.c`. Python encoders are
783 registered within the relevant plugins.
784 :param args: Extra arguments to the encoder.
785 :returns: A :py:class:`bytes` object.
786 """
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 bufsize = max(65536, self.size[0] * 4) # see RawEncode.c
807 output = []
808 while True:
809 bytes_consumed, errcode, data = e.encode(bufsize)
810 output.append(data)
811 if errcode:
812 break
813 if errcode < 0:
814 msg = f"encoder error {errcode} in tobytes"
815 raise RuntimeError(msg)
817 return b"".join(output)
819 def tobitmap(self, name: str = "image") -> bytes:
820 """
821 Returns the image converted to an X11 bitmap.
823 .. note:: This method only works for mode "1" images.
825 :param name: The name prefix to use for the bitmap variables.
826 :returns: A string containing an X11 bitmap.
827 :raises ValueError: If the mode is not "1"
828 """
830 self.load()
831 if self.mode != "1":
832 msg = "not a bitmap"
833 raise ValueError(msg)
834 data = self.tobytes("xbm")
835 return b"".join(
836 [
837 f"#define {name}_width {self.size[0]}\n".encode("ascii"),
838 f"#define {name}_height {self.size[1]}\n".encode("ascii"),
839 f"static char {name}_bits[] = {{\n".encode("ascii"),
840 data,
841 b"};",
842 ]
843 )
845 def frombytes(
846 self,
847 data: bytes | bytearray | SupportsArrayInterface,
848 decoder_name: str = "raw",
849 *args: Any,
850 ) -> None:
851 """
852 Loads this image with pixel data from a bytes object.
854 This method is similar to the :py:func:`~PIL.Image.frombytes` function,
855 but loads data into this image instead of creating a new image object.
856 """
858 if self.width == 0 or self.height == 0:
859 return
861 decoder_args: Any = args
862 if len(decoder_args) == 1 and isinstance(decoder_args[0], tuple):
863 # may pass tuple instead of argument list
864 decoder_args = decoder_args[0]
866 # default format
867 if decoder_name == "raw" and decoder_args == ():
868 decoder_args = self.mode
870 # unpack data
871 d = _getdecoder(self.mode, decoder_name, decoder_args)
872 d.setimage(self.im)
873 s = d.decode(data)
875 if s[0] >= 0:
876 msg = "not enough image data"
877 raise ValueError(msg)
878 if s[1] != 0:
879 msg = "cannot decode image data"
880 raise ValueError(msg)
882 def load(self) -> core.PixelAccess | None:
883 """
884 Allocates storage for the image and loads the pixel data. In
885 normal cases, you don't need to call this method, since the
886 Image class automatically loads an opened image when it is
887 accessed for the first time.
889 If the file associated with the image was opened by Pillow, then this
890 method will close it. The exception to this is if the image has
891 multiple frames, in which case the file will be left open for seek
892 operations. See :ref:`file-handling` for more information.
894 :returns: An image access object.
895 :rtype: :py:class:`.PixelAccess`
896 """
897 if self._im is not None and self.palette and self.palette.dirty:
898 # realize palette
899 mode, arr = self.palette.getdata()
900 self.im.putpalette(self.palette.mode, mode, arr)
901 self.palette.dirty = 0
902 self.palette.rawmode = None
903 if "transparency" in self.info and mode in ("LA", "PA"):
904 if isinstance(self.info["transparency"], int):
905 self.im.putpalettealpha(self.info["transparency"], 0)
906 else:
907 self.im.putpalettealphas(self.info["transparency"])
908 self.palette.mode = "RGBA"
909 else:
910 self.palette.palette = self.im.getpalette(
911 self.palette.mode, self.palette.mode
912 )
914 if self._im is not None:
915 return self.im.pixel_access(self.readonly)
916 return None
918 def verify(self) -> None:
919 """
920 Verifies the contents of a file. For data read from a file, this
921 method attempts to determine if the file is broken, without
922 actually decoding the image data. If this method finds any
923 problems, it raises suitable exceptions. If you need to load
924 the image after using this method, you must reopen the image
925 file.
926 """
927 pass
929 def convert(
930 self,
931 mode: str | None = None,
932 matrix: tuple[float, ...] | None = None,
933 dither: Dither | None = None,
934 palette: Palette = Palette.WEB,
935 colors: int = 256,
936 ) -> Image:
937 """
938 Returns a converted copy of this image. For the "P" mode, this
939 method translates pixels through the palette. If mode is
940 omitted, a mode is chosen so that all information in the image
941 and the palette can be represented without a palette.
943 This supports all possible conversions between "L", "RGB" and "CMYK". The
944 ``matrix`` argument only supports "L" and "RGB".
946 When translating a color image to grayscale (mode "L"),
947 the library uses the ITU-R 601-2 luma transform::
949 L = R * 299/1000 + G * 587/1000 + B * 114/1000
951 The default method of converting a grayscale ("L") or "RGB"
952 image into a bilevel (mode "1") image uses Floyd-Steinberg
953 dither to approximate the original image luminosity levels. If
954 dither is ``None``, all values larger than 127 are set to 255 (white),
955 all other values to 0 (black). To use other thresholds, use the
956 :py:meth:`~PIL.Image.Image.point` method.
958 When converting from "RGBA" to "P" without a ``matrix`` argument,
959 this passes the operation to :py:meth:`~PIL.Image.Image.quantize`,
960 and ``dither`` and ``palette`` are ignored.
962 When converting from "PA", if an "RGBA" palette is present, the alpha
963 channel from the image will be used instead of the values from the palette.
965 :param mode: The requested mode. See: :ref:`concept-modes`.
966 :param matrix: An optional conversion matrix. If given, this
967 should be 4- or 12-tuple containing floating point values.
968 :param dither: Dithering method, used when converting from
969 mode "RGB" to "P" or from "RGB" or "L" to "1".
970 Available methods are :data:`Dither.NONE` or :data:`Dither.FLOYDSTEINBERG`
971 (default). Note that this is not used when ``matrix`` is supplied.
972 :param palette: Palette to use when converting from mode "RGB"
973 to "P". Available palettes are :data:`Palette.WEB` or
974 :data:`Palette.ADAPTIVE`.
975 :param colors: Number of colors to use for the :data:`Palette.ADAPTIVE`
976 palette. Defaults to 256.
977 :rtype: :py:class:`~PIL.Image.Image`
978 :returns: An :py:class:`~PIL.Image.Image` object.
979 """
981 if mode in ("BGR;15", "BGR;16", "BGR;24"):
982 deprecate(mode, 12)
984 self.load()
986 has_transparency = "transparency" in self.info
987 if not mode and self.mode == "P":
988 # determine default mode
989 if self.palette:
990 mode = self.palette.mode
991 else:
992 mode = "RGB"
993 if mode == "RGB" and has_transparency:
994 mode = "RGBA"
995 if not mode or (mode == self.mode and not matrix):
996 return self.copy()
998 if matrix:
999 # matrix conversion
1000 if mode not in ("L", "RGB"):
1001 msg = "illegal conversion"
1002 raise ValueError(msg)
1003 im = self.im.convert_matrix(mode, matrix)
1004 new_im = self._new(im)
1005 if has_transparency and self.im.bands == 3:
1006 transparency = new_im.info["transparency"]
1008 def convert_transparency(
1009 m: tuple[float, ...], v: tuple[int, int, int]
1010 ) -> int:
1011 value = m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3] * 0.5
1012 return max(0, min(255, int(value)))
1014 if mode == "L":
1015 transparency = convert_transparency(matrix, transparency)
1016 elif len(mode) == 3:
1017 transparency = tuple(
1018 convert_transparency(matrix[i * 4 : i * 4 + 4], transparency)
1019 for i in range(0, len(transparency))
1020 )
1021 new_im.info["transparency"] = transparency
1022 return new_im
1024 if mode == "P" and self.mode == "RGBA":
1025 return self.quantize(colors)
1027 trns = None
1028 delete_trns = False
1029 # transparency handling
1030 if has_transparency:
1031 if (self.mode in ("1", "L", "I", "I;16") and mode in ("LA", "RGBA")) or (
1032 self.mode == "RGB" and mode in ("La", "LA", "RGBa", "RGBA")
1033 ):
1034 # Use transparent conversion to promote from transparent
1035 # color to an alpha channel.
1036 new_im = self._new(
1037 self.im.convert_transparent(mode, self.info["transparency"])
1038 )
1039 del new_im.info["transparency"]
1040 return new_im
1041 elif self.mode in ("L", "RGB", "P") and mode in ("L", "RGB", "P"):
1042 t = self.info["transparency"]
1043 if isinstance(t, bytes):
1044 # Dragons. This can't be represented by a single color
1045 warnings.warn(
1046 "Palette images with Transparency expressed in bytes should be "
1047 "converted to RGBA images"
1048 )
1049 delete_trns = True
1050 else:
1051 # get the new transparency color.
1052 # use existing conversions
1053 trns_im = new(self.mode, (1, 1))
1054 if self.mode == "P":
1055 assert self.palette is not None
1056 trns_im.putpalette(self.palette, self.palette.mode)
1057 if isinstance(t, tuple):
1058 err = "Couldn't allocate a palette color for transparency"
1059 assert trns_im.palette is not None
1060 try:
1061 t = trns_im.palette.getcolor(t, self)
1062 except ValueError as e:
1063 if str(e) == "cannot allocate more than 256 colors":
1064 # If all 256 colors are in use,
1065 # then there is no need for transparency
1066 t = None
1067 else:
1068 raise ValueError(err) from e
1069 if t is None:
1070 trns = None
1071 else:
1072 trns_im.putpixel((0, 0), t)
1074 if mode in ("L", "RGB"):
1075 trns_im = trns_im.convert(mode)
1076 else:
1077 # can't just retrieve the palette number, got to do it
1078 # after quantization.
1079 trns_im = trns_im.convert("RGB")
1080 trns = trns_im.getpixel((0, 0))
1082 elif self.mode == "P" and mode in ("LA", "PA", "RGBA"):
1083 t = self.info["transparency"]
1084 delete_trns = True
1086 if isinstance(t, bytes):
1087 self.im.putpalettealphas(t)
1088 elif isinstance(t, int):
1089 self.im.putpalettealpha(t, 0)
1090 else:
1091 msg = "Transparency for P mode should be bytes or int"
1092 raise ValueError(msg)
1094 if mode == "P" and palette == Palette.ADAPTIVE:
1095 im = self.im.quantize(colors)
1096 new_im = self._new(im)
1097 from . import ImagePalette
1099 new_im.palette = ImagePalette.ImagePalette(
1100 "RGB", new_im.im.getpalette("RGB")
1101 )
1102 if delete_trns:
1103 # This could possibly happen if we requantize to fewer colors.
1104 # The transparency would be totally off in that case.
1105 del new_im.info["transparency"]
1106 if trns is not None:
1107 try:
1108 new_im.info["transparency"] = new_im.palette.getcolor(
1109 cast(tuple[int, ...], trns), # trns was converted to RGB
1110 new_im,
1111 )
1112 except Exception:
1113 # if we can't make a transparent color, don't leave the old
1114 # transparency hanging around to mess us up.
1115 del new_im.info["transparency"]
1116 warnings.warn("Couldn't allocate palette entry for transparency")
1117 return new_im
1119 if "LAB" in (self.mode, mode):
1120 im = self
1121 if mode == "LAB":
1122 if im.mode not in ("RGB", "RGBA", "RGBX"):
1123 im = im.convert("RGBA")
1124 other_mode = im.mode
1125 else:
1126 other_mode = mode
1127 if other_mode in ("RGB", "RGBA", "RGBX"):
1128 from . import ImageCms
1130 srgb = ImageCms.createProfile("sRGB")
1131 lab = ImageCms.createProfile("LAB")
1132 profiles = [lab, srgb] if im.mode == "LAB" else [srgb, lab]
1133 transform = ImageCms.buildTransform(
1134 profiles[0], profiles[1], im.mode, mode
1135 )
1136 return transform.apply(im)
1138 # colorspace conversion
1139 if dither is None:
1140 dither = Dither.FLOYDSTEINBERG
1142 try:
1143 im = self.im.convert(mode, dither)
1144 except ValueError:
1145 try:
1146 # normalize source image and try again
1147 modebase = getmodebase(self.mode)
1148 if modebase == self.mode:
1149 raise
1150 im = self.im.convert(modebase)
1151 im = im.convert(mode, dither)
1152 except KeyError as e:
1153 msg = "illegal conversion"
1154 raise ValueError(msg) from e
1156 new_im = self._new(im)
1157 if mode == "P" and palette != Palette.ADAPTIVE:
1158 from . import ImagePalette
1160 new_im.palette = ImagePalette.ImagePalette("RGB", im.getpalette("RGB"))
1161 if delete_trns:
1162 # crash fail if we leave a bytes transparency in an rgb/l mode.
1163 del new_im.info["transparency"]
1164 if trns is not None:
1165 if new_im.mode == "P" and new_im.palette:
1166 try:
1167 new_im.info["transparency"] = new_im.palette.getcolor(
1168 cast(tuple[int, ...], trns), new_im # trns was converted to RGB
1169 )
1170 except ValueError as e:
1171 del new_im.info["transparency"]
1172 if str(e) != "cannot allocate more than 256 colors":
1173 # If all 256 colors are in use,
1174 # then there is no need for transparency
1175 warnings.warn(
1176 "Couldn't allocate palette entry for transparency"
1177 )
1178 else:
1179 new_im.info["transparency"] = trns
1180 return new_im
1182 def quantize(
1183 self,
1184 colors: int = 256,
1185 method: int | None = None,
1186 kmeans: int = 0,
1187 palette: Image | None = None,
1188 dither: Dither = Dither.FLOYDSTEINBERG,
1189 ) -> Image:
1190 """
1191 Convert the image to 'P' mode with the specified number
1192 of colors.
1194 :param colors: The desired number of colors, <= 256
1195 :param method: :data:`Quantize.MEDIANCUT` (median cut),
1196 :data:`Quantize.MAXCOVERAGE` (maximum coverage),
1197 :data:`Quantize.FASTOCTREE` (fast octree),
1198 :data:`Quantize.LIBIMAGEQUANT` (libimagequant; check support
1199 using :py:func:`PIL.features.check_feature` with
1200 ``feature="libimagequant"``).
1202 By default, :data:`Quantize.MEDIANCUT` will be used.
1204 The exception to this is RGBA images. :data:`Quantize.MEDIANCUT`
1205 and :data:`Quantize.MAXCOVERAGE` do not support RGBA images, so
1206 :data:`Quantize.FASTOCTREE` is used by default instead.
1207 :param kmeans: Integer greater than or equal to zero.
1208 :param palette: Quantize to the palette of given
1209 :py:class:`PIL.Image.Image`.
1210 :param dither: Dithering method, used when converting from
1211 mode "RGB" to "P" or from "RGB" or "L" to "1".
1212 Available methods are :data:`Dither.NONE` or :data:`Dither.FLOYDSTEINBERG`
1213 (default).
1214 :returns: A new image
1215 """
1217 self.load()
1219 if method is None:
1220 # defaults:
1221 method = Quantize.MEDIANCUT
1222 if self.mode == "RGBA":
1223 method = Quantize.FASTOCTREE
1225 if self.mode == "RGBA" and method not in (
1226 Quantize.FASTOCTREE,
1227 Quantize.LIBIMAGEQUANT,
1228 ):
1229 # Caller specified an invalid mode.
1230 msg = (
1231 "Fast Octree (method == 2) and libimagequant (method == 3) "
1232 "are the only valid methods for quantizing RGBA images"
1233 )
1234 raise ValueError(msg)
1236 if palette:
1237 # use palette from reference image
1238 palette.load()
1239 if palette.mode != "P":
1240 msg = "bad mode for palette image"
1241 raise ValueError(msg)
1242 if self.mode not in {"RGB", "L"}:
1243 msg = "only RGB or L mode images can be quantized to a palette"
1244 raise ValueError(msg)
1245 im = self.im.convert("P", dither, palette.im)
1246 new_im = self._new(im)
1247 assert palette.palette is not None
1248 new_im.palette = palette.palette.copy()
1249 return new_im
1251 if kmeans < 0:
1252 msg = "kmeans must not be negative"
1253 raise ValueError(msg)
1255 im = self._new(self.im.quantize(colors, method, kmeans))
1257 from . import ImagePalette
1259 mode = im.im.getpalettemode()
1260 palette_data = im.im.getpalette(mode, mode)[: colors * len(mode)]
1261 im.palette = ImagePalette.ImagePalette(mode, palette_data)
1263 return im
1265 def copy(self) -> Image:
1266 """
1267 Copies this image. Use this method if you wish to paste things
1268 into an image, but still retain the original.
1270 :rtype: :py:class:`~PIL.Image.Image`
1271 :returns: An :py:class:`~PIL.Image.Image` object.
1272 """
1273 self.load()
1274 return self._new(self.im.copy())
1276 __copy__ = copy
1278 def crop(self, box: tuple[float, float, float, float] | None = None) -> Image:
1279 """
1280 Returns a rectangular region from this image. The box is a
1281 4-tuple defining the left, upper, right, and lower pixel
1282 coordinate. See :ref:`coordinate-system`.
1284 Note: Prior to Pillow 3.4.0, this was a lazy operation.
1286 :param box: The crop rectangle, as a (left, upper, right, lower)-tuple.
1287 :rtype: :py:class:`~PIL.Image.Image`
1288 :returns: An :py:class:`~PIL.Image.Image` object.
1289 """
1291 if box is None:
1292 return self.copy()
1294 if box[2] < box[0]:
1295 msg = "Coordinate 'right' is less than 'left'"
1296 raise ValueError(msg)
1297 elif box[3] < box[1]:
1298 msg = "Coordinate 'lower' is less than 'upper'"
1299 raise ValueError(msg)
1301 self.load()
1302 return self._new(self._crop(self.im, box))
1304 def _crop(
1305 self, im: core.ImagingCore, box: tuple[float, float, float, float]
1306 ) -> core.ImagingCore:
1307 """
1308 Returns a rectangular region from the core image object im.
1310 This is equivalent to calling im.crop((x0, y0, x1, y1)), but
1311 includes additional sanity checks.
1313 :param im: a core image object
1314 :param box: The crop rectangle, as a (left, upper, right, lower)-tuple.
1315 :returns: A core image object.
1316 """
1318 x0, y0, x1, y1 = map(int, map(round, box))
1320 absolute_values = (abs(x1 - x0), abs(y1 - y0))
1322 _decompression_bomb_check(absolute_values)
1324 return im.crop((x0, y0, x1, y1))
1326 def draft(
1327 self, mode: str | None, size: tuple[int, int] | None
1328 ) -> tuple[str, tuple[int, int, float, float]] | None:
1329 """
1330 Configures the image file loader so it returns a version of the
1331 image that as closely as possible matches the given mode and
1332 size. For example, you can use this method to convert a color
1333 JPEG to grayscale while loading it.
1335 If any changes are made, returns a tuple with the chosen ``mode`` and
1336 ``box`` with coordinates of the original image within the altered one.
1338 Note that this method modifies the :py:class:`~PIL.Image.Image` object
1339 in place. If the image has already been loaded, this method has no
1340 effect.
1342 Note: This method is not implemented for most images. It is
1343 currently implemented only for JPEG and MPO images.
1345 :param mode: The requested mode.
1346 :param size: The requested size in pixels, as a 2-tuple:
1347 (width, height).
1348 """
1349 pass
1351 def _expand(self, xmargin: int, ymargin: int | None = None) -> Image:
1352 if ymargin is None:
1353 ymargin = xmargin
1354 self.load()
1355 return self._new(self.im.expand(xmargin, ymargin))
1357 def filter(self, filter: ImageFilter.Filter | type[ImageFilter.Filter]) -> Image:
1358 """
1359 Filters this image using the given filter. For a list of
1360 available filters, see the :py:mod:`~PIL.ImageFilter` module.
1362 :param filter: Filter kernel.
1363 :returns: An :py:class:`~PIL.Image.Image` object."""
1365 from . import ImageFilter
1367 self.load()
1369 if callable(filter):
1370 filter = filter()
1371 if not hasattr(filter, "filter"):
1372 msg = "filter argument should be ImageFilter.Filter instance or class"
1373 raise TypeError(msg)
1375 multiband = isinstance(filter, ImageFilter.MultibandFilter)
1376 if self.im.bands == 1 or multiband:
1377 return self._new(filter.filter(self.im))
1379 ims = [
1380 self._new(filter.filter(self.im.getband(c))) for c in range(self.im.bands)
1381 ]
1382 return merge(self.mode, ims)
1384 def getbands(self) -> tuple[str, ...]:
1385 """
1386 Returns a tuple containing the name of each band in this image.
1387 For example, ``getbands`` on an RGB image returns ("R", "G", "B").
1389 :returns: A tuple containing band names.
1390 :rtype: tuple
1391 """
1392 return ImageMode.getmode(self.mode).bands
1394 def getbbox(self, *, alpha_only: bool = True) -> tuple[int, int, int, int] | None:
1395 """
1396 Calculates the bounding box of the non-zero regions in the
1397 image.
1399 :param alpha_only: Optional flag, defaulting to ``True``.
1400 If ``True`` and the image has an alpha channel, trim transparent pixels.
1401 Otherwise, trim pixels when all channels are zero.
1402 Keyword-only argument.
1403 :returns: The bounding box is returned as a 4-tuple defining the
1404 left, upper, right, and lower pixel coordinate. See
1405 :ref:`coordinate-system`. If the image is completely empty, this
1406 method returns None.
1408 """
1410 self.load()
1411 return self.im.getbbox(alpha_only)
1413 def getcolors(
1414 self, maxcolors: int = 256
1415 ) -> list[tuple[int, tuple[int, ...]]] | list[tuple[int, float]] | None:
1416 """
1417 Returns a list of colors used in this image.
1419 The colors will be in the image's mode. For example, an RGB image will
1420 return a tuple of (red, green, blue) color values, and a P image will
1421 return the index of the color in the palette.
1423 :param maxcolors: Maximum number of colors. If this number is
1424 exceeded, this method returns None. The default limit is
1425 256 colors.
1426 :returns: An unsorted list of (count, pixel) values.
1427 """
1429 self.load()
1430 if self.mode in ("1", "L", "P"):
1431 h = self.im.histogram()
1432 out: list[tuple[int, float]] = [(h[i], i) for i in range(256) if h[i]]
1433 if len(out) > maxcolors:
1434 return None
1435 return out
1436 return self.im.getcolors(maxcolors)
1438 def getdata(self, band: int | None = None) -> core.ImagingCore:
1439 """
1440 Returns the contents of this image as a sequence object
1441 containing pixel values. The sequence object is flattened, so
1442 that values for line one follow directly after the values of
1443 line zero, and so on.
1445 Note that the sequence object returned by this method is an
1446 internal PIL data type, which only supports certain sequence
1447 operations. To convert it to an ordinary sequence (e.g. for
1448 printing), use ``list(im.getdata())``.
1450 :param band: What band to return. The default is to return
1451 all bands. To return a single band, pass in the index
1452 value (e.g. 0 to get the "R" band from an "RGB" image).
1453 :returns: A sequence-like object.
1454 """
1456 self.load()
1457 if band is not None:
1458 return self.im.getband(band)
1459 return self.im # could be abused
1461 def getextrema(self) -> tuple[float, float] | tuple[tuple[int, int], ...]:
1462 """
1463 Gets the minimum and maximum pixel values for each band in
1464 the image.
1466 :returns: For a single-band image, a 2-tuple containing the
1467 minimum and maximum pixel value. For a multi-band image,
1468 a tuple containing one 2-tuple for each band.
1469 """
1471 self.load()
1472 if self.im.bands > 1:
1473 return tuple(self.im.getband(i).getextrema() for i in range(self.im.bands))
1474 return self.im.getextrema()
1476 def getxmp(self) -> dict[str, Any]:
1477 """
1478 Returns a dictionary containing the XMP tags.
1479 Requires defusedxml to be installed.
1481 :returns: XMP tags in a dictionary.
1482 """
1484 def get_name(tag: str) -> str:
1485 return re.sub("^{[^}]+}", "", tag)
1487 def get_value(element: Element) -> str | dict[str, Any] | None:
1488 value: dict[str, Any] = {get_name(k): v for k, v in element.attrib.items()}
1489 children = list(element)
1490 if children:
1491 for child in children:
1492 name = get_name(child.tag)
1493 child_value = get_value(child)
1494 if name in value:
1495 if not isinstance(value[name], list):
1496 value[name] = [value[name]]
1497 value[name].append(child_value)
1498 else:
1499 value[name] = child_value
1500 elif value:
1501 if element.text:
1502 value["text"] = element.text
1503 else:
1504 return element.text
1505 return value
1507 if ElementTree is None:
1508 warnings.warn("XMP data cannot be read without defusedxml dependency")
1509 return {}
1510 if "xmp" not in self.info:
1511 return {}
1512 root = ElementTree.fromstring(self.info["xmp"].rstrip(b"\x00"))
1513 return {get_name(root.tag): get_value(root)}
1515 def getexif(self) -> Exif:
1516 """
1517 Gets EXIF data from the image.
1519 :returns: an :py:class:`~PIL.Image.Exif` object.
1520 """
1521 if self._exif is None:
1522 self._exif = Exif()
1523 elif self._exif._loaded:
1524 return self._exif
1525 self._exif._loaded = True
1527 exif_info = self.info.get("exif")
1528 if exif_info is None:
1529 if "Raw profile type exif" in self.info:
1530 exif_info = bytes.fromhex(
1531 "".join(self.info["Raw profile type exif"].split("\n")[3:])
1532 )
1533 elif hasattr(self, "tag_v2"):
1534 self._exif.bigtiff = self.tag_v2._bigtiff
1535 self._exif.endian = self.tag_v2._endian
1536 self._exif.load_from_fp(self.fp, self.tag_v2._offset)
1537 if exif_info is not None:
1538 self._exif.load(exif_info)
1540 # XMP tags
1541 if ExifTags.Base.Orientation not in self._exif:
1542 xmp_tags = self.info.get("XML:com.adobe.xmp")
1543 if xmp_tags:
1544 match = re.search(r'tiff:Orientation(="|>)([0-9])', xmp_tags)
1545 if match:
1546 self._exif[ExifTags.Base.Orientation] = int(match[2])
1548 return self._exif
1550 def _reload_exif(self) -> None:
1551 if self._exif is None or not self._exif._loaded:
1552 return
1553 self._exif._loaded = False
1554 self.getexif()
1556 def get_child_images(self) -> list[ImageFile.ImageFile]:
1557 child_images = []
1558 exif = self.getexif()
1559 ifds = []
1560 if ExifTags.Base.SubIFDs in exif:
1561 subifd_offsets = exif[ExifTags.Base.SubIFDs]
1562 if subifd_offsets:
1563 if not isinstance(subifd_offsets, tuple):
1564 subifd_offsets = (subifd_offsets,)
1565 for subifd_offset in subifd_offsets:
1566 ifds.append((exif._get_ifd_dict(subifd_offset), subifd_offset))
1567 ifd1 = exif.get_ifd(ExifTags.IFD.IFD1)
1568 if ifd1 and ifd1.get(ExifTags.Base.JpegIFOffset):
1569 assert exif._info is not None
1570 ifds.append((ifd1, exif._info.next))
1572 offset = None
1573 for ifd, ifd_offset in ifds:
1574 current_offset = self.fp.tell()
1575 if offset is None:
1576 offset = current_offset
1578 fp = self.fp
1579 if ifd is not None:
1580 thumbnail_offset = ifd.get(ExifTags.Base.JpegIFOffset)
1581 if thumbnail_offset is not None:
1582 thumbnail_offset += getattr(self, "_exif_offset", 0)
1583 self.fp.seek(thumbnail_offset)
1584 data = self.fp.read(ifd.get(ExifTags.Base.JpegIFByteCount))
1585 fp = io.BytesIO(data)
1587 with open(fp) as im:
1588 from . import TiffImagePlugin
1590 if thumbnail_offset is None and isinstance(
1591 im, TiffImagePlugin.TiffImageFile
1592 ):
1593 im._frame_pos = [ifd_offset]
1594 im._seek(0)
1595 im.load()
1596 child_images.append(im)
1598 if offset is not None:
1599 self.fp.seek(offset)
1600 return child_images
1602 def getim(self) -> CapsuleType:
1603 """
1604 Returns a capsule that points to the internal image memory.
1606 :returns: A capsule object.
1607 """
1609 self.load()
1610 return self.im.ptr
1612 def getpalette(self, rawmode: str | None = "RGB") -> list[int] | None:
1613 """
1614 Returns the image palette as a list.
1616 :param rawmode: The mode in which to return the palette. ``None`` will
1617 return the palette in its current mode.
1619 .. versionadded:: 9.1.0
1621 :returns: A list of color values [r, g, b, ...], or None if the
1622 image has no palette.
1623 """
1625 self.load()
1626 try:
1627 mode = self.im.getpalettemode()
1628 except ValueError:
1629 return None # no palette
1630 if rawmode is None:
1631 rawmode = mode
1632 return list(self.im.getpalette(mode, rawmode))
1634 @property
1635 def has_transparency_data(self) -> bool:
1636 """
1637 Determine if an image has transparency data, whether in the form of an
1638 alpha channel, a palette with an alpha channel, or a "transparency" key
1639 in the info dictionary.
1641 Note the image might still appear solid, if all of the values shown
1642 within are opaque.
1644 :returns: A boolean.
1645 """
1646 if (
1647 self.mode in ("LA", "La", "PA", "RGBA", "RGBa")
1648 or "transparency" in self.info
1649 ):
1650 return True
1651 if self.mode == "P":
1652 assert self.palette is not None
1653 return self.palette.mode.endswith("A")
1654 return False
1656 def apply_transparency(self) -> None:
1657 """
1658 If a P mode image has a "transparency" key in the info dictionary,
1659 remove the key and instead apply the transparency to the palette.
1660 Otherwise, the image is unchanged.
1661 """
1662 if self.mode != "P" or "transparency" not in self.info:
1663 return
1665 from . import ImagePalette
1667 palette = self.getpalette("RGBA")
1668 assert palette is not None
1669 transparency = self.info["transparency"]
1670 if isinstance(transparency, bytes):
1671 for i, alpha in enumerate(transparency):
1672 palette[i * 4 + 3] = alpha
1673 else:
1674 palette[transparency * 4 + 3] = 0
1675 self.palette = ImagePalette.ImagePalette("RGBA", bytes(palette))
1676 self.palette.dirty = 1
1678 del self.info["transparency"]
1680 def getpixel(
1681 self, xy: tuple[int, int] | list[int]
1682 ) -> float | tuple[int, ...] | None:
1683 """
1684 Returns the pixel value at a given position.
1686 :param xy: The coordinate, given as (x, y). See
1687 :ref:`coordinate-system`.
1688 :returns: The pixel value. If the image is a multi-layer image,
1689 this method returns a tuple.
1690 """
1692 self.load()
1693 return self.im.getpixel(tuple(xy))
1695 def getprojection(self) -> tuple[list[int], list[int]]:
1696 """
1697 Get projection to x and y axes
1699 :returns: Two sequences, indicating where there are non-zero
1700 pixels along the X-axis and the Y-axis, respectively.
1701 """
1703 self.load()
1704 x, y = self.im.getprojection()
1705 return list(x), list(y)
1707 def histogram(
1708 self, mask: Image | None = None, extrema: tuple[float, float] | None = None
1709 ) -> list[int]:
1710 """
1711 Returns a histogram for the image. The histogram is returned as a
1712 list of pixel counts, one for each pixel value in the source
1713 image. Counts are grouped into 256 bins for each band, even if
1714 the image has more than 8 bits per band. If the image has more
1715 than one band, the histograms for all bands are concatenated (for
1716 example, the histogram for an "RGB" image contains 768 values).
1718 A bilevel image (mode "1") is treated as a grayscale ("L") image
1719 by this method.
1721 If a mask is provided, the method returns a histogram for those
1722 parts of the image where the mask image is non-zero. The mask
1723 image must have the same size as the image, and be either a
1724 bi-level image (mode "1") or a grayscale image ("L").
1726 :param mask: An optional mask.
1727 :param extrema: An optional tuple of manually-specified extrema.
1728 :returns: A list containing pixel counts.
1729 """
1730 self.load()
1731 if mask:
1732 mask.load()
1733 return self.im.histogram((0, 0), mask.im)
1734 if self.mode in ("I", "F"):
1735 return self.im.histogram(
1736 extrema if extrema is not None else self.getextrema()
1737 )
1738 return self.im.histogram()
1740 def entropy(
1741 self, mask: Image | None = None, extrema: tuple[float, float] | None = None
1742 ) -> float:
1743 """
1744 Calculates and returns the entropy for the image.
1746 A bilevel image (mode "1") is treated as a grayscale ("L")
1747 image by this method.
1749 If a mask is provided, the method employs the histogram for
1750 those parts of the image where the mask image is non-zero.
1751 The mask image must have the same size as the image, and be
1752 either a bi-level image (mode "1") or a grayscale image ("L").
1754 :param mask: An optional mask.
1755 :param extrema: An optional tuple of manually-specified extrema.
1756 :returns: A float value representing the image entropy
1757 """
1758 self.load()
1759 if mask:
1760 mask.load()
1761 return self.im.entropy((0, 0), mask.im)
1762 if self.mode in ("I", "F"):
1763 return self.im.entropy(
1764 extrema if extrema is not None else self.getextrema()
1765 )
1766 return self.im.entropy()
1768 def paste(
1769 self,
1770 im: Image | str | float | tuple[float, ...],
1771 box: Image | tuple[int, int, int, int] | tuple[int, int] | None = None,
1772 mask: Image | None = None,
1773 ) -> None:
1774 """
1775 Pastes another image into this image. The box argument is either
1776 a 2-tuple giving the upper left corner, a 4-tuple defining the
1777 left, upper, right, and lower pixel coordinate, or None (same as
1778 (0, 0)). See :ref:`coordinate-system`. If a 4-tuple is given, the size
1779 of the pasted image must match the size of the region.
1781 If the modes don't match, the pasted image is converted to the mode of
1782 this image (see the :py:meth:`~PIL.Image.Image.convert` method for
1783 details).
1785 Instead of an image, the source can be a integer or tuple
1786 containing pixel values. The method then fills the region
1787 with the given color. When creating RGB images, you can
1788 also use color strings as supported by the ImageColor module.
1790 If a mask is given, this method updates only the regions
1791 indicated by the mask. You can use either "1", "L", "LA", "RGBA"
1792 or "RGBa" images (if present, the alpha band is used as mask).
1793 Where the mask is 255, the given image is copied as is. Where
1794 the mask is 0, the current value is preserved. Intermediate
1795 values will mix the two images together, including their alpha
1796 channels if they have them.
1798 See :py:meth:`~PIL.Image.Image.alpha_composite` if you want to
1799 combine images with respect to their alpha channels.
1801 :param im: Source image or pixel value (integer, float or tuple).
1802 :param box: An optional 4-tuple giving the region to paste into.
1803 If a 2-tuple is used instead, it's treated as the upper left
1804 corner. If omitted or None, the source is pasted into the
1805 upper left corner.
1807 If an image is given as the second argument and there is no
1808 third, the box defaults to (0, 0), and the second argument
1809 is interpreted as a mask image.
1810 :param mask: An optional mask image.
1811 """
1813 if isinstance(box, Image):
1814 if mask is not None:
1815 msg = "If using second argument as mask, third argument must be None"
1816 raise ValueError(msg)
1817 # abbreviated paste(im, mask) syntax
1818 mask = box
1819 box = None
1821 if box is None:
1822 box = (0, 0)
1824 if len(box) == 2:
1825 # upper left corner given; get size from image or mask
1826 if isinstance(im, Image):
1827 size = im.size
1828 elif isinstance(mask, Image):
1829 size = mask.size
1830 else:
1831 # FIXME: use self.size here?
1832 msg = "cannot determine region size; use 4-item box"
1833 raise ValueError(msg)
1834 box += (box[0] + size[0], box[1] + size[1])
1836 source: core.ImagingCore | str | float | tuple[float, ...]
1837 if isinstance(im, str):
1838 from . import ImageColor
1840 source = ImageColor.getcolor(im, self.mode)
1841 elif isinstance(im, Image):
1842 im.load()
1843 if self.mode != im.mode:
1844 if self.mode != "RGB" or im.mode not in ("LA", "RGBA", "RGBa"):
1845 # should use an adapter for this!
1846 im = im.convert(self.mode)
1847 source = im.im
1848 else:
1849 source = im
1851 self._ensure_mutable()
1853 if mask:
1854 mask.load()
1855 self.im.paste(source, box, mask.im)
1856 else:
1857 self.im.paste(source, box)
1859 def alpha_composite(
1860 self, im: Image, dest: Sequence[int] = (0, 0), source: Sequence[int] = (0, 0)
1861 ) -> None:
1862 """'In-place' analog of Image.alpha_composite. Composites an image
1863 onto this image.
1865 :param im: image to composite over this one
1866 :param dest: Optional 2 tuple (left, top) specifying the upper
1867 left corner in this (destination) image.
1868 :param source: Optional 2 (left, top) tuple for the upper left
1869 corner in the overlay source image, or 4 tuple (left, top, right,
1870 bottom) for the bounds of the source rectangle
1872 Performance Note: Not currently implemented in-place in the core layer.
1873 """
1875 if not isinstance(source, (list, tuple)):
1876 msg = "Source must be a list or tuple"
1877 raise ValueError(msg)
1878 if not isinstance(dest, (list, tuple)):
1879 msg = "Destination must be a list or tuple"
1880 raise ValueError(msg)
1882 if len(source) == 4:
1883 overlay_crop_box = tuple(source)
1884 elif len(source) == 2:
1885 overlay_crop_box = tuple(source) + im.size
1886 else:
1887 msg = "Source must be a sequence of length 2 or 4"
1888 raise ValueError(msg)
1890 if not len(dest) == 2:
1891 msg = "Destination must be a sequence of length 2"
1892 raise ValueError(msg)
1893 if min(source) < 0:
1894 msg = "Source must be non-negative"
1895 raise ValueError(msg)
1897 # over image, crop if it's not the whole image.
1898 if overlay_crop_box == (0, 0) + im.size:
1899 overlay = im
1900 else:
1901 overlay = im.crop(overlay_crop_box)
1903 # target for the paste
1904 box = tuple(dest) + (dest[0] + overlay.width, dest[1] + overlay.height)
1906 # destination image. don't copy if we're using the whole image.
1907 if box == (0, 0) + self.size:
1908 background = self
1909 else:
1910 background = self.crop(box)
1912 result = alpha_composite(background, overlay)
1913 self.paste(result, box)
1915 def point(
1916 self,
1917 lut: (
1918 Sequence[float]
1919 | NumpyArray
1920 | Callable[[int], float]
1921 | Callable[[ImagePointTransform], ImagePointTransform | float]
1922 | ImagePointHandler
1923 ),
1924 mode: str | None = None,
1925 ) -> Image:
1926 """
1927 Maps this image through a lookup table or function.
1929 :param lut: A lookup table, containing 256 (or 65536 if
1930 self.mode=="I" and mode == "L") values per band in the
1931 image. A function can be used instead, it should take a
1932 single argument. The function is called once for each
1933 possible pixel value, and the resulting table is applied to
1934 all bands of the image.
1936 It may also be an :py:class:`~PIL.Image.ImagePointHandler`
1937 object::
1939 class Example(Image.ImagePointHandler):
1940 def point(self, im: Image) -> Image:
1941 # Return result
1942 :param mode: Output mode (default is same as input). This can only be used if
1943 the source image has mode "L" or "P", and the output has mode "1" or the
1944 source image mode is "I" and the output mode is "L".
1945 :returns: An :py:class:`~PIL.Image.Image` object.
1946 """
1948 self.load()
1950 if isinstance(lut, ImagePointHandler):
1951 return lut.point(self)
1953 if callable(lut):
1954 # if it isn't a list, it should be a function
1955 if self.mode in ("I", "I;16", "F"):
1956 # check if the function can be used with point_transform
1957 # UNDONE wiredfool -- I think this prevents us from ever doing
1958 # a gamma function point transform on > 8bit images.
1959 scale, offset = _getscaleoffset(lut) # type: ignore[arg-type]
1960 return self._new(self.im.point_transform(scale, offset))
1961 # for other modes, convert the function to a table
1962 flatLut = [lut(i) for i in range(256)] * self.im.bands # type: ignore[arg-type]
1963 else:
1964 flatLut = lut
1966 if self.mode == "F":
1967 # FIXME: _imaging returns a confusing error message for this case
1968 msg = "point operation not supported for this mode"
1969 raise ValueError(msg)
1971 if mode != "F":
1972 flatLut = [round(i) for i in flatLut]
1973 return self._new(self.im.point(flatLut, mode))
1975 def putalpha(self, alpha: Image | int) -> None:
1976 """
1977 Adds or replaces the alpha layer in this image. If the image
1978 does not have an alpha layer, it's converted to "LA" or "RGBA".
1979 The new layer must be either "L" or "1".
1981 :param alpha: The new alpha layer. This can either be an "L" or "1"
1982 image having the same size as this image, or an integer.
1983 """
1985 self._ensure_mutable()
1987 if self.mode not in ("LA", "PA", "RGBA"):
1988 # attempt to promote self to a matching alpha mode
1989 try:
1990 mode = getmodebase(self.mode) + "A"
1991 try:
1992 self.im.setmode(mode)
1993 except (AttributeError, ValueError) as e:
1994 # do things the hard way
1995 im = self.im.convert(mode)
1996 if im.mode not in ("LA", "PA", "RGBA"):
1997 msg = "alpha channel could not be added"
1998 raise ValueError(msg) from e # sanity check
1999 self.im = im
2000 self._mode = self.im.mode
2001 except KeyError as e:
2002 msg = "illegal image mode"
2003 raise ValueError(msg) from e
2005 if self.mode in ("LA", "PA"):
2006 band = 1
2007 else:
2008 band = 3
2010 if isinstance(alpha, Image):
2011 # alpha layer
2012 if alpha.mode not in ("1", "L"):
2013 msg = "illegal image mode"
2014 raise ValueError(msg)
2015 alpha.load()
2016 if alpha.mode == "1":
2017 alpha = alpha.convert("L")
2018 else:
2019 # constant alpha
2020 try:
2021 self.im.fillband(band, alpha)
2022 except (AttributeError, ValueError):
2023 # do things the hard way
2024 alpha = new("L", self.size, alpha)
2025 else:
2026 return
2028 self.im.putband(alpha.im, band)
2030 def putdata(
2031 self,
2032 data: Sequence[float] | Sequence[Sequence[int]] | core.ImagingCore | NumpyArray,
2033 scale: float = 1.0,
2034 offset: float = 0.0,
2035 ) -> None:
2036 """
2037 Copies pixel data from a flattened sequence object into the image. The
2038 values should start at the upper left corner (0, 0), continue to the
2039 end of the line, followed directly by the first value of the second
2040 line, and so on. Data will be read until either the image or the
2041 sequence ends. The scale and offset values are used to adjust the
2042 sequence values: **pixel = value*scale + offset**.
2044 :param data: A flattened sequence object.
2045 :param scale: An optional scale value. The default is 1.0.
2046 :param offset: An optional offset value. The default is 0.0.
2047 """
2049 self._ensure_mutable()
2051 self.im.putdata(data, scale, offset)
2053 def putpalette(
2054 self,
2055 data: ImagePalette.ImagePalette | bytes | Sequence[int],
2056 rawmode: str = "RGB",
2057 ) -> None:
2058 """
2059 Attaches a palette to this image. The image must be a "P", "PA", "L"
2060 or "LA" image.
2062 The palette sequence must contain at most 256 colors, made up of one
2063 integer value for each channel in the raw mode.
2064 For example, if the raw mode is "RGB", then it can contain at most 768
2065 values, made up of red, green and blue values for the corresponding pixel
2066 index in the 256 colors.
2067 If the raw mode is "RGBA", then it can contain at most 1024 values,
2068 containing red, green, blue and alpha values.
2070 Alternatively, an 8-bit string may be used instead of an integer sequence.
2072 :param data: A palette sequence (either a list or a string).
2073 :param rawmode: The raw mode of the palette. Either "RGB", "RGBA", or a mode
2074 that can be transformed to "RGB" or "RGBA" (e.g. "R", "BGR;15", "RGBA;L").
2075 """
2076 from . import ImagePalette
2078 if self.mode not in ("L", "LA", "P", "PA"):
2079 msg = "illegal image mode"
2080 raise ValueError(msg)
2081 if isinstance(data, ImagePalette.ImagePalette):
2082 if data.rawmode is not None:
2083 palette = ImagePalette.raw(data.rawmode, data.palette)
2084 else:
2085 palette = ImagePalette.ImagePalette(palette=data.palette)
2086 palette.dirty = 1
2087 else:
2088 if not isinstance(data, bytes):
2089 data = bytes(data)
2090 palette = ImagePalette.raw(rawmode, data)
2091 self._mode = "PA" if "A" in self.mode else "P"
2092 self.palette = palette
2093 self.palette.mode = "RGBA" if "A" in rawmode else "RGB"
2094 self.load() # install new palette
2096 def putpixel(
2097 self, xy: tuple[int, int], value: float | tuple[int, ...] | list[int]
2098 ) -> None:
2099 """
2100 Modifies the pixel at the given position. The color is given as
2101 a single numerical value for single-band images, and a tuple for
2102 multi-band images. In addition to this, RGB and RGBA tuples are
2103 accepted for P and PA images.
2105 Note that this method is relatively slow. For more extensive changes,
2106 use :py:meth:`~PIL.Image.Image.paste` or the :py:mod:`~PIL.ImageDraw`
2107 module instead.
2109 See:
2111 * :py:meth:`~PIL.Image.Image.paste`
2112 * :py:meth:`~PIL.Image.Image.putdata`
2113 * :py:mod:`~PIL.ImageDraw`
2115 :param xy: The pixel coordinate, given as (x, y). See
2116 :ref:`coordinate-system`.
2117 :param value: The pixel value.
2118 """
2120 if self.readonly:
2121 self._copy()
2122 self.load()
2124 if (
2125 self.mode in ("P", "PA")
2126 and isinstance(value, (list, tuple))
2127 and len(value) in [3, 4]
2128 ):
2129 # RGB or RGBA value for a P or PA image
2130 if self.mode == "PA":
2131 alpha = value[3] if len(value) == 4 else 255
2132 value = value[:3]
2133 assert self.palette is not None
2134 palette_index = self.palette.getcolor(tuple(value), self)
2135 value = (palette_index, alpha) if self.mode == "PA" else palette_index
2136 return self.im.putpixel(xy, value)
2138 def remap_palette(
2139 self, dest_map: list[int], source_palette: bytes | bytearray | None = None
2140 ) -> Image:
2141 """
2142 Rewrites the image to reorder the palette.
2144 :param dest_map: A list of indexes into the original palette.
2145 e.g. ``[1,0]`` would swap a two item palette, and ``list(range(256))``
2146 is the identity transform.
2147 :param source_palette: Bytes or None.
2148 :returns: An :py:class:`~PIL.Image.Image` object.
2150 """
2151 from . import ImagePalette
2153 if self.mode not in ("L", "P"):
2154 msg = "illegal image mode"
2155 raise ValueError(msg)
2157 bands = 3
2158 palette_mode = "RGB"
2159 if source_palette is None:
2160 if self.mode == "P":
2161 self.load()
2162 palette_mode = self.im.getpalettemode()
2163 if palette_mode == "RGBA":
2164 bands = 4
2165 source_palette = self.im.getpalette(palette_mode, palette_mode)
2166 else: # L-mode
2167 source_palette = bytearray(i // 3 for i in range(768))
2168 elif len(source_palette) > 768:
2169 bands = 4
2170 palette_mode = "RGBA"
2172 palette_bytes = b""
2173 new_positions = [0] * 256
2175 # pick only the used colors from the palette
2176 for i, oldPosition in enumerate(dest_map):
2177 palette_bytes += source_palette[
2178 oldPosition * bands : oldPosition * bands + bands
2179 ]
2180 new_positions[oldPosition] = i
2182 # replace the palette color id of all pixel with the new id
2184 # Palette images are [0..255], mapped through a 1 or 3
2185 # byte/color map. We need to remap the whole image
2186 # from palette 1 to palette 2. New_positions is
2187 # an array of indexes into palette 1. Palette 2 is
2188 # palette 1 with any holes removed.
2190 # We're going to leverage the convert mechanism to use the
2191 # C code to remap the image from palette 1 to palette 2,
2192 # by forcing the source image into 'L' mode and adding a
2193 # mapping 'L' mode palette, then converting back to 'L'
2194 # sans palette thus converting the image bytes, then
2195 # assigning the optimized RGB palette.
2197 # perf reference, 9500x4000 gif, w/~135 colors
2198 # 14 sec prepatch, 1 sec postpatch with optimization forced.
2200 mapping_palette = bytearray(new_positions)
2202 m_im = self.copy()
2203 m_im._mode = "P"
2205 m_im.palette = ImagePalette.ImagePalette(
2206 palette_mode, palette=mapping_palette * bands
2207 )
2208 # possibly set palette dirty, then
2209 # m_im.putpalette(mapping_palette, 'L') # converts to 'P'
2210 # or just force it.
2211 # UNDONE -- this is part of the general issue with palettes
2212 m_im.im.putpalette(palette_mode, palette_mode + ";L", m_im.palette.tobytes())
2214 m_im = m_im.convert("L")
2216 m_im.putpalette(palette_bytes, palette_mode)
2217 m_im.palette = ImagePalette.ImagePalette(palette_mode, palette=palette_bytes)
2219 if "transparency" in self.info:
2220 try:
2221 m_im.info["transparency"] = dest_map.index(self.info["transparency"])
2222 except ValueError:
2223 if "transparency" in m_im.info:
2224 del m_im.info["transparency"]
2226 return m_im
2228 def _get_safe_box(
2229 self,
2230 size: tuple[int, int],
2231 resample: Resampling,
2232 box: tuple[float, float, float, float],
2233 ) -> tuple[int, int, int, int]:
2234 """Expands the box so it includes adjacent pixels
2235 that may be used by resampling with the given resampling filter.
2236 """
2237 filter_support = _filters_support[resample] - 0.5
2238 scale_x = (box[2] - box[0]) / size[0]
2239 scale_y = (box[3] - box[1]) / size[1]
2240 support_x = filter_support * scale_x
2241 support_y = filter_support * scale_y
2243 return (
2244 max(0, int(box[0] - support_x)),
2245 max(0, int(box[1] - support_y)),
2246 min(self.size[0], math.ceil(box[2] + support_x)),
2247 min(self.size[1], math.ceil(box[3] + support_y)),
2248 )
2250 def resize(
2251 self,
2252 size: tuple[int, int] | list[int] | NumpyArray,
2253 resample: int | None = None,
2254 box: tuple[float, float, float, float] | None = None,
2255 reducing_gap: float | None = None,
2256 ) -> Image:
2257 """
2258 Returns a resized copy of this image.
2260 :param size: The requested size in pixels, as a tuple or array:
2261 (width, height).
2262 :param resample: An optional resampling filter. This can be
2263 one of :py:data:`Resampling.NEAREST`, :py:data:`Resampling.BOX`,
2264 :py:data:`Resampling.BILINEAR`, :py:data:`Resampling.HAMMING`,
2265 :py:data:`Resampling.BICUBIC` or :py:data:`Resampling.LANCZOS`.
2266 If the image has mode "1" or "P", it is always set to
2267 :py:data:`Resampling.NEAREST`. If the image mode is "BGR;15",
2268 "BGR;16" or "BGR;24", then the default filter is
2269 :py:data:`Resampling.NEAREST`. Otherwise, the default filter is
2270 :py:data:`Resampling.BICUBIC`. See: :ref:`concept-filters`.
2271 :param box: An optional 4-tuple of floats providing
2272 the source image region to be scaled.
2273 The values must be within (0, 0, width, height) rectangle.
2274 If omitted or None, the entire source is used.
2275 :param reducing_gap: Apply optimization by resizing the image
2276 in two steps. First, reducing the image by integer times
2277 using :py:meth:`~PIL.Image.Image.reduce`.
2278 Second, resizing using regular resampling. The last step
2279 changes size no less than by ``reducing_gap`` times.
2280 ``reducing_gap`` may be None (no first step is performed)
2281 or should be greater than 1.0. The bigger ``reducing_gap``,
2282 the closer the result to the fair resampling.
2283 The smaller ``reducing_gap``, the faster resizing.
2284 With ``reducing_gap`` greater or equal to 3.0, the result is
2285 indistinguishable from fair resampling in most cases.
2286 The default value is None (no optimization).
2287 :returns: An :py:class:`~PIL.Image.Image` object.
2288 """
2290 if resample is None:
2291 bgr = self.mode.startswith("BGR;")
2292 resample = Resampling.NEAREST if bgr else Resampling.BICUBIC
2293 elif resample not in (
2294 Resampling.NEAREST,
2295 Resampling.BILINEAR,
2296 Resampling.BICUBIC,
2297 Resampling.LANCZOS,
2298 Resampling.BOX,
2299 Resampling.HAMMING,
2300 ):
2301 msg = f"Unknown resampling filter ({resample})."
2303 filters = [
2304 f"{filter[1]} ({filter[0]})"
2305 for filter in (
2306 (Resampling.NEAREST, "Image.Resampling.NEAREST"),
2307 (Resampling.LANCZOS, "Image.Resampling.LANCZOS"),
2308 (Resampling.BILINEAR, "Image.Resampling.BILINEAR"),
2309 (Resampling.BICUBIC, "Image.Resampling.BICUBIC"),
2310 (Resampling.BOX, "Image.Resampling.BOX"),
2311 (Resampling.HAMMING, "Image.Resampling.HAMMING"),
2312 )
2313 ]
2314 msg += f" Use {', '.join(filters[:-1])} or {filters[-1]}"
2315 raise ValueError(msg)
2317 if reducing_gap is not None and reducing_gap < 1.0:
2318 msg = "reducing_gap must be 1.0 or greater"
2319 raise ValueError(msg)
2321 if box is None:
2322 box = (0, 0) + self.size
2324 size = tuple(size)
2325 if self.size == size and box == (0, 0) + self.size:
2326 return self.copy()
2328 if self.mode in ("1", "P"):
2329 resample = Resampling.NEAREST
2331 if self.mode in ["LA", "RGBA"] and resample != Resampling.NEAREST:
2332 im = self.convert({"LA": "La", "RGBA": "RGBa"}[self.mode])
2333 im = im.resize(size, resample, box)
2334 return im.convert(self.mode)
2336 self.load()
2338 if reducing_gap is not None and resample != Resampling.NEAREST:
2339 factor_x = int((box[2] - box[0]) / size[0] / reducing_gap) or 1
2340 factor_y = int((box[3] - box[1]) / size[1] / reducing_gap) or 1
2341 if factor_x > 1 or factor_y > 1:
2342 reduce_box = self._get_safe_box(size, cast(Resampling, resample), box)
2343 factor = (factor_x, factor_y)
2344 self = (
2345 self.reduce(factor, box=reduce_box)
2346 if callable(self.reduce)
2347 else Image.reduce(self, factor, box=reduce_box)
2348 )
2349 box = (
2350 (box[0] - reduce_box[0]) / factor_x,
2351 (box[1] - reduce_box[1]) / factor_y,
2352 (box[2] - reduce_box[0]) / factor_x,
2353 (box[3] - reduce_box[1]) / factor_y,
2354 )
2356 return self._new(self.im.resize(size, resample, box))
2358 def reduce(
2359 self,
2360 factor: int | tuple[int, int],
2361 box: tuple[int, int, int, int] | None = None,
2362 ) -> Image:
2363 """
2364 Returns a copy of the image reduced ``factor`` times.
2365 If the size of the image is not dividable by ``factor``,
2366 the resulting size will be rounded up.
2368 :param factor: A greater than 0 integer or tuple of two integers
2369 for width and height separately.
2370 :param box: An optional 4-tuple of ints providing
2371 the source image region to be reduced.
2372 The values must be within ``(0, 0, width, height)`` rectangle.
2373 If omitted or ``None``, the entire source is used.
2374 """
2375 if not isinstance(factor, (list, tuple)):
2376 factor = (factor, factor)
2378 if box is None:
2379 box = (0, 0) + self.size
2381 if factor == (1, 1) and box == (0, 0) + self.size:
2382 return self.copy()
2384 if self.mode in ["LA", "RGBA"]:
2385 im = self.convert({"LA": "La", "RGBA": "RGBa"}[self.mode])
2386 im = im.reduce(factor, box)
2387 return im.convert(self.mode)
2389 self.load()
2391 return self._new(self.im.reduce(factor, box))
2393 def rotate(
2394 self,
2395 angle: float,
2396 resample: Resampling = Resampling.NEAREST,
2397 expand: int | bool = False,
2398 center: tuple[float, float] | None = None,
2399 translate: tuple[int, int] | None = None,
2400 fillcolor: float | tuple[float, ...] | str | None = None,
2401 ) -> Image:
2402 """
2403 Returns a rotated copy of this image. This method returns a
2404 copy of this image, rotated the given number of degrees counter
2405 clockwise around its centre.
2407 :param angle: In degrees counter clockwise.
2408 :param resample: An optional resampling filter. This can be
2409 one of :py:data:`Resampling.NEAREST` (use nearest neighbour),
2410 :py:data:`Resampling.BILINEAR` (linear interpolation in a 2x2
2411 environment), or :py:data:`Resampling.BICUBIC` (cubic spline
2412 interpolation in a 4x4 environment). If omitted, or if the image has
2413 mode "1" or "P", it is set to :py:data:`Resampling.NEAREST`.
2414 See :ref:`concept-filters`.
2415 :param expand: Optional expansion flag. If true, expands the output
2416 image to make it large enough to hold the entire rotated image.
2417 If false or omitted, make the output image the same size as the
2418 input image. Note that the expand flag assumes rotation around
2419 the center and no translation.
2420 :param center: Optional center of rotation (a 2-tuple). Origin is
2421 the upper left corner. Default is the center of the image.
2422 :param translate: An optional post-rotate translation (a 2-tuple).
2423 :param fillcolor: An optional color for area outside the rotated image.
2424 :returns: An :py:class:`~PIL.Image.Image` object.
2425 """
2427 angle = angle % 360.0
2429 # Fast paths regardless of filter, as long as we're not
2430 # translating or changing the center.
2431 if not (center or translate):
2432 if angle == 0:
2433 return self.copy()
2434 if angle == 180:
2435 return self.transpose(Transpose.ROTATE_180)
2436 if angle in (90, 270) and (expand or self.width == self.height):
2437 return self.transpose(
2438 Transpose.ROTATE_90 if angle == 90 else Transpose.ROTATE_270
2439 )
2441 # Calculate the affine matrix. Note that this is the reverse
2442 # transformation (from destination image to source) because we
2443 # want to interpolate the (discrete) destination pixel from
2444 # the local area around the (floating) source pixel.
2446 # The matrix we actually want (note that it operates from the right):
2447 # (1, 0, tx) (1, 0, cx) ( cos a, sin a, 0) (1, 0, -cx)
2448 # (0, 1, ty) * (0, 1, cy) * (-sin a, cos a, 0) * (0, 1, -cy)
2449 # (0, 0, 1) (0, 0, 1) ( 0, 0, 1) (0, 0, 1)
2451 # The reverse matrix is thus:
2452 # (1, 0, cx) ( cos -a, sin -a, 0) (1, 0, -cx) (1, 0, -tx)
2453 # (0, 1, cy) * (-sin -a, cos -a, 0) * (0, 1, -cy) * (0, 1, -ty)
2454 # (0, 0, 1) ( 0, 0, 1) (0, 0, 1) (0, 0, 1)
2456 # In any case, the final translation may be updated at the end to
2457 # compensate for the expand flag.
2459 w, h = self.size
2461 if translate is None:
2462 post_trans = (0, 0)
2463 else:
2464 post_trans = translate
2465 if center is None:
2466 center = (w / 2, h / 2)
2468 angle = -math.radians(angle)
2469 matrix = [
2470 round(math.cos(angle), 15),
2471 round(math.sin(angle), 15),
2472 0.0,
2473 round(-math.sin(angle), 15),
2474 round(math.cos(angle), 15),
2475 0.0,
2476 ]
2478 def transform(x: float, y: float, matrix: list[float]) -> tuple[float, float]:
2479 (a, b, c, d, e, f) = matrix
2480 return a * x + b * y + c, d * x + e * y + f
2482 matrix[2], matrix[5] = transform(
2483 -center[0] - post_trans[0], -center[1] - post_trans[1], matrix
2484 )
2485 matrix[2] += center[0]
2486 matrix[5] += center[1]
2488 if expand:
2489 # calculate output size
2490 xx = []
2491 yy = []
2492 for x, y in ((0, 0), (w, 0), (w, h), (0, h)):
2493 transformed_x, transformed_y = transform(x, y, matrix)
2494 xx.append(transformed_x)
2495 yy.append(transformed_y)
2496 nw = math.ceil(max(xx)) - math.floor(min(xx))
2497 nh = math.ceil(max(yy)) - math.floor(min(yy))
2499 # We multiply a translation matrix from the right. Because of its
2500 # special form, this is the same as taking the image of the
2501 # translation vector as new translation vector.
2502 matrix[2], matrix[5] = transform(-(nw - w) / 2.0, -(nh - h) / 2.0, matrix)
2503 w, h = nw, nh
2505 return self.transform(
2506 (w, h), Transform.AFFINE, matrix, resample, fillcolor=fillcolor
2507 )
2509 def save(
2510 self, fp: StrOrBytesPath | IO[bytes], format: str | None = None, **params: Any
2511 ) -> None:
2512 """
2513 Saves this image under the given filename. If no format is
2514 specified, the format to use is determined from the filename
2515 extension, if possible.
2517 Keyword options can be used to provide additional instructions
2518 to the writer. If a writer doesn't recognise an option, it is
2519 silently ignored. The available options are described in the
2520 :doc:`image format documentation
2521 <../handbook/image-file-formats>` for each writer.
2523 You can use a file object instead of a filename. In this case,
2524 you must always specify the format. The file object must
2525 implement the ``seek``, ``tell``, and ``write``
2526 methods, and be opened in binary mode.
2528 :param fp: A filename (string), os.PathLike object or file object.
2529 :param format: Optional format override. If omitted, the
2530 format to use is determined from the filename extension.
2531 If a file object was used instead of a filename, this
2532 parameter should always be used.
2533 :param params: Extra parameters to the image writer.
2534 :returns: None
2535 :exception ValueError: If the output format could not be determined
2536 from the file name. Use the format option to solve this.
2537 :exception OSError: If the file could not be written. The file
2538 may have been created, and may contain partial data.
2539 """
2541 filename: str | bytes = ""
2542 open_fp = False
2543 if is_path(fp):
2544 filename = os.fspath(fp)
2545 open_fp = True
2546 elif fp == sys.stdout:
2547 try:
2548 fp = sys.stdout.buffer
2549 except AttributeError:
2550 pass
2551 if not filename and hasattr(fp, "name") and is_path(fp.name):
2552 # only set the name for metadata purposes
2553 filename = os.fspath(fp.name)
2555 # may mutate self!
2556 self._ensure_mutable()
2558 save_all = params.pop("save_all", False)
2559 self.encoderinfo = {**getattr(self, "encoderinfo", {}), **params}
2560 self.encoderconfig: tuple[Any, ...] = ()
2562 preinit()
2564 filename_ext = os.path.splitext(filename)[1].lower()
2565 ext = filename_ext.decode() if isinstance(filename_ext, bytes) else filename_ext
2567 if not format:
2568 if ext not in EXTENSION:
2569 init()
2570 try:
2571 format = EXTENSION[ext]
2572 except KeyError as e:
2573 msg = f"unknown file extension: {ext}"
2574 raise ValueError(msg) from e
2576 if format.upper() not in SAVE:
2577 init()
2578 if save_all:
2579 save_handler = SAVE_ALL[format.upper()]
2580 else:
2581 save_handler = SAVE[format.upper()]
2583 created = False
2584 if open_fp:
2585 created = not os.path.exists(filename)
2586 if params.get("append", False):
2587 # Open also for reading ("+"), because TIFF save_all
2588 # writer needs to go back and edit the written data.
2589 fp = builtins.open(filename, "r+b")
2590 else:
2591 fp = builtins.open(filename, "w+b")
2592 else:
2593 fp = cast(IO[bytes], fp)
2595 try:
2596 save_handler(self, fp, filename)
2597 except Exception:
2598 if open_fp:
2599 fp.close()
2600 if created:
2601 try:
2602 os.remove(filename)
2603 except PermissionError:
2604 pass
2605 raise
2606 finally:
2607 try:
2608 del self.encoderinfo
2609 except AttributeError:
2610 pass
2611 if open_fp:
2612 fp.close()
2614 def seek(self, frame: int) -> None:
2615 """
2616 Seeks to the given frame in this sequence file. If you seek
2617 beyond the end of the sequence, the method raises an
2618 ``EOFError`` exception. When a sequence file is opened, the
2619 library automatically seeks to frame 0.
2621 See :py:meth:`~PIL.Image.Image.tell`.
2623 If defined, :attr:`~PIL.Image.Image.n_frames` refers to the
2624 number of available frames.
2626 :param frame: Frame number, starting at 0.
2627 :exception EOFError: If the call attempts to seek beyond the end
2628 of the sequence.
2629 """
2631 # overridden by file handlers
2632 if frame != 0:
2633 msg = "no more images in file"
2634 raise EOFError(msg)
2636 def show(self, title: str | None = None) -> None:
2637 """
2638 Displays this image. This method is mainly intended for debugging purposes.
2640 This method calls :py:func:`PIL.ImageShow.show` internally. You can use
2641 :py:func:`PIL.ImageShow.register` to override its default behaviour.
2643 The image is first saved to a temporary file. By default, it will be in
2644 PNG format.
2646 On Unix, the image is then opened using the **xdg-open**, **display**,
2647 **gm**, **eog** or **xv** utility, depending on which one can be found.
2649 On macOS, the image is opened with the native Preview application.
2651 On Windows, the image is opened with the standard PNG display utility.
2653 :param title: Optional title to use for the image window, where possible.
2654 """
2656 _show(self, title=title)
2658 def split(self) -> tuple[Image, ...]:
2659 """
2660 Split this image into individual bands. This method returns a
2661 tuple of individual image bands from an image. For example,
2662 splitting an "RGB" image creates three new images each
2663 containing a copy of one of the original bands (red, green,
2664 blue).
2666 If you need only one band, :py:meth:`~PIL.Image.Image.getchannel`
2667 method can be more convenient and faster.
2669 :returns: A tuple containing bands.
2670 """
2672 self.load()
2673 if self.im.bands == 1:
2674 return (self.copy(),)
2675 return tuple(map(self._new, self.im.split()))
2677 def getchannel(self, channel: int | str) -> Image:
2678 """
2679 Returns an image containing a single channel of the source image.
2681 :param channel: What channel to return. Could be index
2682 (0 for "R" channel of "RGB") or channel name
2683 ("A" for alpha channel of "RGBA").
2684 :returns: An image in "L" mode.
2686 .. versionadded:: 4.3.0
2687 """
2688 self.load()
2690 if isinstance(channel, str):
2691 try:
2692 channel = self.getbands().index(channel)
2693 except ValueError as e:
2694 msg = f'The image has no channel "{channel}"'
2695 raise ValueError(msg) from e
2697 return self._new(self.im.getband(channel))
2699 def tell(self) -> int:
2700 """
2701 Returns the current frame number. See :py:meth:`~PIL.Image.Image.seek`.
2703 If defined, :attr:`~PIL.Image.Image.n_frames` refers to the
2704 number of available frames.
2706 :returns: Frame number, starting with 0.
2707 """
2708 return 0
2710 def thumbnail(
2711 self,
2712 size: tuple[float, float],
2713 resample: Resampling = Resampling.BICUBIC,
2714 reducing_gap: float | None = 2.0,
2715 ) -> None:
2716 """
2717 Make this image into a thumbnail. This method modifies the
2718 image to contain a thumbnail version of itself, no larger than
2719 the given size. This method calculates an appropriate thumbnail
2720 size to preserve the aspect of the image, calls the
2721 :py:meth:`~PIL.Image.Image.draft` method to configure the file reader
2722 (where applicable), and finally resizes the image.
2724 Note that this function modifies the :py:class:`~PIL.Image.Image`
2725 object in place. If you need to use the full resolution image as well,
2726 apply this method to a :py:meth:`~PIL.Image.Image.copy` of the original
2727 image.
2729 :param size: The requested size in pixels, as a 2-tuple:
2730 (width, height).
2731 :param resample: Optional resampling filter. This can be one
2732 of :py:data:`Resampling.NEAREST`, :py:data:`Resampling.BOX`,
2733 :py:data:`Resampling.BILINEAR`, :py:data:`Resampling.HAMMING`,
2734 :py:data:`Resampling.BICUBIC` or :py:data:`Resampling.LANCZOS`.
2735 If omitted, it defaults to :py:data:`Resampling.BICUBIC`.
2736 (was :py:data:`Resampling.NEAREST` prior to version 2.5.0).
2737 See: :ref:`concept-filters`.
2738 :param reducing_gap: Apply optimization by resizing the image
2739 in two steps. First, reducing the image by integer times
2740 using :py:meth:`~PIL.Image.Image.reduce` or
2741 :py:meth:`~PIL.Image.Image.draft` for JPEG images.
2742 Second, resizing using regular resampling. The last step
2743 changes size no less than by ``reducing_gap`` times.
2744 ``reducing_gap`` may be None (no first step is performed)
2745 or should be greater than 1.0. The bigger ``reducing_gap``,
2746 the closer the result to the fair resampling.
2747 The smaller ``reducing_gap``, the faster resizing.
2748 With ``reducing_gap`` greater or equal to 3.0, the result is
2749 indistinguishable from fair resampling in most cases.
2750 The default value is 2.0 (very close to fair resampling
2751 while still being faster in many cases).
2752 :returns: None
2753 """
2755 provided_size = tuple(map(math.floor, size))
2757 def preserve_aspect_ratio() -> tuple[int, int] | None:
2758 def round_aspect(number: float, key: Callable[[int], float]) -> int:
2759 return max(min(math.floor(number), math.ceil(number), key=key), 1)
2761 x, y = provided_size
2762 if x >= self.width and y >= self.height:
2763 return None
2765 aspect = self.width / self.height
2766 if x / y >= aspect:
2767 x = round_aspect(y * aspect, key=lambda n: abs(aspect - n / y))
2768 else:
2769 y = round_aspect(
2770 x / aspect, key=lambda n: 0 if n == 0 else abs(aspect - x / n)
2771 )
2772 return x, y
2774 preserved_size = preserve_aspect_ratio()
2775 if preserved_size is None:
2776 return
2777 final_size = preserved_size
2779 box = None
2780 if reducing_gap is not None:
2781 res = self.draft(
2782 None, (int(size[0] * reducing_gap), int(size[1] * reducing_gap))
2783 )
2784 if res is not None:
2785 box = res[1]
2787 if self.size != final_size:
2788 im = self.resize(final_size, resample, box=box, reducing_gap=reducing_gap)
2790 self.im = im.im
2791 self._size = final_size
2792 self._mode = self.im.mode
2794 self.readonly = 0
2796 # FIXME: the different transform methods need further explanation
2797 # instead of bloating the method docs, add a separate chapter.
2798 def transform(
2799 self,
2800 size: tuple[int, int],
2801 method: Transform | ImageTransformHandler | SupportsGetData,
2802 data: Sequence[Any] | None = None,
2803 resample: int = Resampling.NEAREST,
2804 fill: int = 1,
2805 fillcolor: float | tuple[float, ...] | str | None = None,
2806 ) -> Image:
2807 """
2808 Transforms this image. This method creates a new image with the
2809 given size, and the same mode as the original, and copies data
2810 to the new image using the given transform.
2812 :param size: The output size in pixels, as a 2-tuple:
2813 (width, height).
2814 :param method: The transformation method. This is one of
2815 :py:data:`Transform.EXTENT` (cut out a rectangular subregion),
2816 :py:data:`Transform.AFFINE` (affine transform),
2817 :py:data:`Transform.PERSPECTIVE` (perspective transform),
2818 :py:data:`Transform.QUAD` (map a quadrilateral to a rectangle), or
2819 :py:data:`Transform.MESH` (map a number of source quadrilaterals
2820 in one operation).
2822 It may also be an :py:class:`~PIL.Image.ImageTransformHandler`
2823 object::
2825 class Example(Image.ImageTransformHandler):
2826 def transform(self, size, data, resample, fill=1):
2827 # Return result
2829 Implementations of :py:class:`~PIL.Image.ImageTransformHandler`
2830 for some of the :py:class:`Transform` methods are provided
2831 in :py:mod:`~PIL.ImageTransform`.
2833 It may also be an object with a ``method.getdata`` method
2834 that returns a tuple supplying new ``method`` and ``data`` values::
2836 class Example:
2837 def getdata(self):
2838 method = Image.Transform.EXTENT
2839 data = (0, 0, 100, 100)
2840 return method, data
2841 :param data: Extra data to the transformation method.
2842 :param resample: Optional resampling filter. It can be one of
2843 :py:data:`Resampling.NEAREST` (use nearest neighbour),
2844 :py:data:`Resampling.BILINEAR` (linear interpolation in a 2x2
2845 environment), or :py:data:`Resampling.BICUBIC` (cubic spline
2846 interpolation in a 4x4 environment). If omitted, or if the image
2847 has mode "1" or "P", it is set to :py:data:`Resampling.NEAREST`.
2848 See: :ref:`concept-filters`.
2849 :param fill: If ``method`` is an
2850 :py:class:`~PIL.Image.ImageTransformHandler` object, this is one of
2851 the arguments passed to it. Otherwise, it is unused.
2852 :param fillcolor: Optional fill color for the area outside the
2853 transform in the output image.
2854 :returns: An :py:class:`~PIL.Image.Image` object.
2855 """
2857 if self.mode in ("LA", "RGBA") and resample != Resampling.NEAREST:
2858 return (
2859 self.convert({"LA": "La", "RGBA": "RGBa"}[self.mode])
2860 .transform(size, method, data, resample, fill, fillcolor)
2861 .convert(self.mode)
2862 )
2864 if isinstance(method, ImageTransformHandler):
2865 return method.transform(size, self, resample=resample, fill=fill)
2867 if hasattr(method, "getdata"):
2868 # compatibility w. old-style transform objects
2869 method, data = method.getdata()
2871 if data is None:
2872 msg = "missing method data"
2873 raise ValueError(msg)
2875 im = new(self.mode, size, fillcolor)
2876 if self.mode == "P" and self.palette:
2877 im.palette = self.palette.copy()
2878 im.info = self.info.copy()
2879 if method == Transform.MESH:
2880 # list of quads
2881 for box, quad in data:
2882 im.__transformer(
2883 box, self, Transform.QUAD, quad, resample, fillcolor is None
2884 )
2885 else:
2886 im.__transformer(
2887 (0, 0) + size, self, method, data, resample, fillcolor is None
2888 )
2890 return im
2892 def __transformer(
2893 self,
2894 box: tuple[int, int, int, int],
2895 image: Image,
2896 method: Transform,
2897 data: Sequence[float],
2898 resample: int = Resampling.NEAREST,
2899 fill: bool = True,
2900 ) -> None:
2901 w = box[2] - box[0]
2902 h = box[3] - box[1]
2904 if method == Transform.AFFINE:
2905 data = data[:6]
2907 elif method == Transform.EXTENT:
2908 # convert extent to an affine transform
2909 x0, y0, x1, y1 = data
2910 xs = (x1 - x0) / w
2911 ys = (y1 - y0) / h
2912 method = Transform.AFFINE
2913 data = (xs, 0, x0, 0, ys, y0)
2915 elif method == Transform.PERSPECTIVE:
2916 data = data[:8]
2918 elif method == Transform.QUAD:
2919 # quadrilateral warp. data specifies the four corners
2920 # given as NW, SW, SE, and NE.
2921 nw = data[:2]
2922 sw = data[2:4]
2923 se = data[4:6]
2924 ne = data[6:8]
2925 x0, y0 = nw
2926 As = 1.0 / w
2927 At = 1.0 / h
2928 data = (
2929 x0,
2930 (ne[0] - x0) * As,
2931 (sw[0] - x0) * At,
2932 (se[0] - sw[0] - ne[0] + x0) * As * At,
2933 y0,
2934 (ne[1] - y0) * As,
2935 (sw[1] - y0) * At,
2936 (se[1] - sw[1] - ne[1] + y0) * As * At,
2937 )
2939 else:
2940 msg = "unknown transformation method"
2941 raise ValueError(msg)
2943 if resample not in (
2944 Resampling.NEAREST,
2945 Resampling.BILINEAR,
2946 Resampling.BICUBIC,
2947 ):
2948 if resample in (Resampling.BOX, Resampling.HAMMING, Resampling.LANCZOS):
2949 unusable: dict[int, str] = {
2950 Resampling.BOX: "Image.Resampling.BOX",
2951 Resampling.HAMMING: "Image.Resampling.HAMMING",
2952 Resampling.LANCZOS: "Image.Resampling.LANCZOS",
2953 }
2954 msg = unusable[resample] + f" ({resample}) cannot be used."
2955 else:
2956 msg = f"Unknown resampling filter ({resample})."
2958 filters = [
2959 f"{filter[1]} ({filter[0]})"
2960 for filter in (
2961 (Resampling.NEAREST, "Image.Resampling.NEAREST"),
2962 (Resampling.BILINEAR, "Image.Resampling.BILINEAR"),
2963 (Resampling.BICUBIC, "Image.Resampling.BICUBIC"),
2964 )
2965 ]
2966 msg += f" Use {', '.join(filters[:-1])} or {filters[-1]}"
2967 raise ValueError(msg)
2969 image.load()
2971 self.load()
2973 if image.mode in ("1", "P"):
2974 resample = Resampling.NEAREST
2976 self.im.transform(box, image.im, method, data, resample, fill)
2978 def transpose(self, method: Transpose) -> Image:
2979 """
2980 Transpose image (flip or rotate in 90 degree steps)
2982 :param method: One of :py:data:`Transpose.FLIP_LEFT_RIGHT`,
2983 :py:data:`Transpose.FLIP_TOP_BOTTOM`, :py:data:`Transpose.ROTATE_90`,
2984 :py:data:`Transpose.ROTATE_180`, :py:data:`Transpose.ROTATE_270`,
2985 :py:data:`Transpose.TRANSPOSE` or :py:data:`Transpose.TRANSVERSE`.
2986 :returns: Returns a flipped or rotated copy of this image.
2987 """
2989 self.load()
2990 return self._new(self.im.transpose(method))
2992 def effect_spread(self, distance: int) -> Image:
2993 """
2994 Randomly spread pixels in an image.
2996 :param distance: Distance to spread pixels.
2997 """
2998 self.load()
2999 return self._new(self.im.effect_spread(distance))
3001 def toqimage(self) -> ImageQt.ImageQt:
3002 """Returns a QImage copy of this image"""
3003 from . import ImageQt
3005 if not ImageQt.qt_is_installed:
3006 msg = "Qt bindings are not installed"
3007 raise ImportError(msg)
3008 return ImageQt.toqimage(self)
3010 def toqpixmap(self) -> ImageQt.QPixmap:
3011 """Returns a QPixmap copy of this image"""
3012 from . import ImageQt
3014 if not ImageQt.qt_is_installed:
3015 msg = "Qt bindings are not installed"
3016 raise ImportError(msg)
3017 return ImageQt.toqpixmap(self)
3020# --------------------------------------------------------------------
3021# Abstract handlers.
3024class ImagePointHandler:
3025 """
3026 Used as a mixin by point transforms
3027 (for use with :py:meth:`~PIL.Image.Image.point`)
3028 """
3030 @abc.abstractmethod
3031 def point(self, im: Image) -> Image:
3032 pass
3035class ImageTransformHandler:
3036 """
3037 Used as a mixin by geometry transforms
3038 (for use with :py:meth:`~PIL.Image.Image.transform`)
3039 """
3041 @abc.abstractmethod
3042 def transform(
3043 self,
3044 size: tuple[int, int],
3045 image: Image,
3046 **options: Any,
3047 ) -> Image:
3048 pass
3051# --------------------------------------------------------------------
3052# Factories
3054#
3055# Debugging
3058def _wedge() -> Image:
3059 """Create grayscale wedge (for debugging only)"""
3061 return Image()._new(core.wedge("L"))
3064def _check_size(size: Any) -> None:
3065 """
3066 Common check to enforce type and sanity check on size tuples
3068 :param size: Should be a 2 tuple of (width, height)
3069 :returns: None, or raises a ValueError
3070 """
3072 if not isinstance(size, (list, tuple)):
3073 msg = "Size must be a list or tuple"
3074 raise ValueError(msg)
3075 if len(size) != 2:
3076 msg = "Size must be a sequence of length 2"
3077 raise ValueError(msg)
3078 if size[0] < 0 or size[1] < 0:
3079 msg = "Width and height must be >= 0"
3080 raise ValueError(msg)
3083def new(
3084 mode: str,
3085 size: tuple[int, int] | list[int],
3086 color: float | tuple[float, ...] | str | None = 0,
3087) -> Image:
3088 """
3089 Creates a new image with the given mode and size.
3091 :param mode: The mode to use for the new image. See:
3092 :ref:`concept-modes`.
3093 :param size: A 2-tuple, containing (width, height) in pixels.
3094 :param color: What color to use for the image. Default is black.
3095 If given, this should be a single integer or floating point value
3096 for single-band modes, and a tuple for multi-band modes (one value
3097 per band). When creating RGB or HSV images, you can also use color
3098 strings as supported by the ImageColor module. If the color is
3099 None, the image is not initialised.
3100 :returns: An :py:class:`~PIL.Image.Image` object.
3101 """
3103 if mode in ("BGR;15", "BGR;16", "BGR;24"):
3104 deprecate(mode, 12)
3106 _check_size(size)
3108 if color is None:
3109 # don't initialize
3110 return Image()._new(core.new(mode, size))
3112 if isinstance(color, str):
3113 # css3-style specifier
3115 from . import ImageColor
3117 color = ImageColor.getcolor(color, mode)
3119 im = Image()
3120 if (
3121 mode == "P"
3122 and isinstance(color, (list, tuple))
3123 and all(isinstance(i, int) for i in color)
3124 ):
3125 color_ints: tuple[int, ...] = cast(tuple[int, ...], tuple(color))
3126 if len(color_ints) == 3 or len(color_ints) == 4:
3127 # RGB or RGBA value for a P image
3128 from . import ImagePalette
3130 im.palette = ImagePalette.ImagePalette()
3131 color = im.palette.getcolor(color_ints)
3132 return im._new(core.fill(mode, size, color))
3135def frombytes(
3136 mode: str,
3137 size: tuple[int, int],
3138 data: bytes | bytearray | SupportsArrayInterface,
3139 decoder_name: str = "raw",
3140 *args: Any,
3141) -> Image:
3142 """
3143 Creates a copy of an image memory from pixel data in a buffer.
3145 In its simplest form, this function takes three arguments
3146 (mode, size, and unpacked pixel data).
3148 You can also use any pixel decoder supported by PIL. For more
3149 information on available decoders, see the section
3150 :ref:`Writing Your Own File Codec <file-codecs>`.
3152 Note that this function decodes pixel data only, not entire images.
3153 If you have an entire image in a string, wrap it in a
3154 :py:class:`~io.BytesIO` object, and use :py:func:`~PIL.Image.open` to load
3155 it.
3157 :param mode: The image mode. See: :ref:`concept-modes`.
3158 :param size: The image size.
3159 :param data: A byte buffer containing raw data for the given mode.
3160 :param decoder_name: What decoder to use.
3161 :param args: Additional parameters for the given decoder.
3162 :returns: An :py:class:`~PIL.Image.Image` object.
3163 """
3165 _check_size(size)
3167 im = new(mode, size)
3168 if im.width != 0 and im.height != 0:
3169 decoder_args: Any = args
3170 if len(decoder_args) == 1 and isinstance(decoder_args[0], tuple):
3171 # may pass tuple instead of argument list
3172 decoder_args = decoder_args[0]
3174 if decoder_name == "raw" and decoder_args == ():
3175 decoder_args = mode
3177 im.frombytes(data, decoder_name, decoder_args)
3178 return im
3181def frombuffer(
3182 mode: str,
3183 size: tuple[int, int],
3184 data: bytes | SupportsArrayInterface,
3185 decoder_name: str = "raw",
3186 *args: Any,
3187) -> Image:
3188 """
3189 Creates an image memory referencing pixel data in a byte buffer.
3191 This function is similar to :py:func:`~PIL.Image.frombytes`, but uses data
3192 in the byte buffer, where possible. This means that changes to the
3193 original buffer object are reflected in this image). Not all modes can
3194 share memory; supported modes include "L", "RGBX", "RGBA", and "CMYK".
3196 Note that this function decodes pixel data only, not entire images.
3197 If you have an entire image file in a string, wrap it in a
3198 :py:class:`~io.BytesIO` object, and use :py:func:`~PIL.Image.open` to load it.
3200 The default parameters used for the "raw" decoder differs from that used for
3201 :py:func:`~PIL.Image.frombytes`. This is a bug, and will probably be fixed in a
3202 future release. The current release issues a warning if you do this; to disable
3203 the warning, you should provide the full set of parameters. See below for details.
3205 :param mode: The image mode. See: :ref:`concept-modes`.
3206 :param size: The image size.
3207 :param data: A bytes or other buffer object containing raw
3208 data for the given mode.
3209 :param decoder_name: What decoder to use.
3210 :param args: Additional parameters for the given decoder. For the
3211 default encoder ("raw"), it's recommended that you provide the
3212 full set of parameters::
3214 frombuffer(mode, size, data, "raw", mode, 0, 1)
3216 :returns: An :py:class:`~PIL.Image.Image` object.
3218 .. versionadded:: 1.1.4
3219 """
3221 _check_size(size)
3223 # may pass tuple instead of argument list
3224 if len(args) == 1 and isinstance(args[0], tuple):
3225 args = args[0]
3227 if decoder_name == "raw":
3228 if args == ():
3229 args = mode, 0, 1
3230 if args[0] in _MAPMODES:
3231 im = new(mode, (0, 0))
3232 im = im._new(core.map_buffer(data, size, decoder_name, 0, args))
3233 if mode == "P":
3234 from . import ImagePalette
3236 im.palette = ImagePalette.ImagePalette("RGB", im.im.getpalette("RGB"))
3237 im.readonly = 1
3238 return im
3240 return frombytes(mode, size, data, decoder_name, args)
3243class SupportsArrayInterface(Protocol):
3244 """
3245 An object that has an ``__array_interface__`` dictionary.
3246 """
3248 @property
3249 def __array_interface__(self) -> dict[str, Any]:
3250 raise NotImplementedError()
3253def fromarray(obj: SupportsArrayInterface, mode: str | None = None) -> Image:
3254 """
3255 Creates an image memory from an object exporting the array interface
3256 (using the buffer protocol)::
3258 from PIL import Image
3259 import numpy as np
3260 a = np.zeros((5, 5))
3261 im = Image.fromarray(a)
3263 If ``obj`` is not contiguous, then the ``tobytes`` method is called
3264 and :py:func:`~PIL.Image.frombuffer` is used.
3266 In the case of NumPy, be aware that Pillow modes do not always correspond
3267 to NumPy dtypes. Pillow modes only offer 1-bit pixels, 8-bit pixels,
3268 32-bit signed integer pixels, and 32-bit floating point pixels.
3270 Pillow images can also be converted to arrays::
3272 from PIL import Image
3273 import numpy as np
3274 im = Image.open("hopper.jpg")
3275 a = np.asarray(im)
3277 When converting Pillow images to arrays however, only pixel values are
3278 transferred. This means that P and PA mode images will lose their palette.
3280 :param obj: Object with array interface
3281 :param mode: Optional mode to use when reading ``obj``. Will be determined from
3282 type if ``None``.
3284 This will not be used to convert the data after reading, but will be used to
3285 change how the data is read::
3287 from PIL import Image
3288 import numpy as np
3289 a = np.full((1, 1), 300)
3290 im = Image.fromarray(a, mode="L")
3291 im.getpixel((0, 0)) # 44
3292 im = Image.fromarray(a, mode="RGB")
3293 im.getpixel((0, 0)) # (44, 1, 0)
3295 See: :ref:`concept-modes` for general information about modes.
3296 :returns: An image object.
3298 .. versionadded:: 1.1.6
3299 """
3300 arr = obj.__array_interface__
3301 shape = arr["shape"]
3302 ndim = len(shape)
3303 strides = arr.get("strides", None)
3304 if mode is None:
3305 try:
3306 typekey = (1, 1) + shape[2:], arr["typestr"]
3307 except KeyError as e:
3308 msg = "Cannot handle this data type"
3309 raise TypeError(msg) from e
3310 try:
3311 mode, rawmode = _fromarray_typemap[typekey]
3312 except KeyError as e:
3313 typekey_shape, typestr = typekey
3314 msg = f"Cannot handle this data type: {typekey_shape}, {typestr}"
3315 raise TypeError(msg) from e
3316 else:
3317 rawmode = mode
3318 if mode in ["1", "L", "I", "P", "F"]:
3319 ndmax = 2
3320 elif mode == "RGB":
3321 ndmax = 3
3322 else:
3323 ndmax = 4
3324 if ndim > ndmax:
3325 msg = f"Too many dimensions: {ndim} > {ndmax}."
3326 raise ValueError(msg)
3328 size = 1 if ndim == 1 else shape[1], shape[0]
3329 if strides is not None:
3330 if hasattr(obj, "tobytes"):
3331 obj = obj.tobytes()
3332 elif hasattr(obj, "tostring"):
3333 obj = obj.tostring()
3334 else:
3335 msg = "'strides' requires either tobytes() or tostring()"
3336 raise ValueError(msg)
3338 return frombuffer(mode, size, obj, "raw", rawmode, 0, 1)
3341def fromqimage(im: ImageQt.QImage) -> ImageFile.ImageFile:
3342 """Creates an image instance from a QImage image"""
3343 from . import ImageQt
3345 if not ImageQt.qt_is_installed:
3346 msg = "Qt bindings are not installed"
3347 raise ImportError(msg)
3348 return ImageQt.fromqimage(im)
3351def fromqpixmap(im: ImageQt.QPixmap) -> ImageFile.ImageFile:
3352 """Creates an image instance from a QPixmap image"""
3353 from . import ImageQt
3355 if not ImageQt.qt_is_installed:
3356 msg = "Qt bindings are not installed"
3357 raise ImportError(msg)
3358 return ImageQt.fromqpixmap(im)
3361_fromarray_typemap = {
3362 # (shape, typestr) => mode, rawmode
3363 # first two members of shape are set to one
3364 ((1, 1), "|b1"): ("1", "1;8"),
3365 ((1, 1), "|u1"): ("L", "L"),
3366 ((1, 1), "|i1"): ("I", "I;8"),
3367 ((1, 1), "<u2"): ("I", "I;16"),
3368 ((1, 1), ">u2"): ("I", "I;16B"),
3369 ((1, 1), "<i2"): ("I", "I;16S"),
3370 ((1, 1), ">i2"): ("I", "I;16BS"),
3371 ((1, 1), "<u4"): ("I", "I;32"),
3372 ((1, 1), ">u4"): ("I", "I;32B"),
3373 ((1, 1), "<i4"): ("I", "I;32S"),
3374 ((1, 1), ">i4"): ("I", "I;32BS"),
3375 ((1, 1), "<f4"): ("F", "F;32F"),
3376 ((1, 1), ">f4"): ("F", "F;32BF"),
3377 ((1, 1), "<f8"): ("F", "F;64F"),
3378 ((1, 1), ">f8"): ("F", "F;64BF"),
3379 ((1, 1, 2), "|u1"): ("LA", "LA"),
3380 ((1, 1, 3), "|u1"): ("RGB", "RGB"),
3381 ((1, 1, 4), "|u1"): ("RGBA", "RGBA"),
3382 # shortcuts:
3383 ((1, 1), f"{_ENDIAN}i4"): ("I", "I"),
3384 ((1, 1), f"{_ENDIAN}f4"): ("F", "F"),
3385}
3388def _decompression_bomb_check(size: tuple[int, int]) -> None:
3389 if MAX_IMAGE_PIXELS is None:
3390 return
3392 pixels = max(1, size[0]) * max(1, size[1])
3394 if pixels > 2 * MAX_IMAGE_PIXELS:
3395 msg = (
3396 f"Image size ({pixels} pixels) exceeds limit of {2 * MAX_IMAGE_PIXELS} "
3397 "pixels, could be decompression bomb DOS attack."
3398 )
3399 raise DecompressionBombError(msg)
3401 if pixels > MAX_IMAGE_PIXELS:
3402 warnings.warn(
3403 f"Image size ({pixels} pixels) exceeds limit of {MAX_IMAGE_PIXELS} pixels, "
3404 "could be decompression bomb DOS attack.",
3405 DecompressionBombWarning,
3406 )
3409def open(
3410 fp: StrOrBytesPath | IO[bytes],
3411 mode: Literal["r"] = "r",
3412 formats: list[str] | tuple[str, ...] | None = None,
3413) -> ImageFile.ImageFile:
3414 """
3415 Opens and identifies the given image file.
3417 This is a lazy operation; this function identifies the file, but
3418 the file remains open and the actual image data is not read from
3419 the file until you try to process the data (or call the
3420 :py:meth:`~PIL.Image.Image.load` method). See
3421 :py:func:`~PIL.Image.new`. See :ref:`file-handling`.
3423 :param fp: A filename (string), os.PathLike object or a file object.
3424 The file object must implement ``file.read``,
3425 ``file.seek``, and ``file.tell`` methods,
3426 and be opened in binary mode. The file object will also seek to zero
3427 before reading.
3428 :param mode: The mode. If given, this argument must be "r".
3429 :param formats: A list or tuple of formats to attempt to load the file in.
3430 This can be used to restrict the set of formats checked.
3431 Pass ``None`` to try all supported formats. You can print the set of
3432 available formats by running ``python3 -m PIL`` or using
3433 the :py:func:`PIL.features.pilinfo` function.
3434 :returns: An :py:class:`~PIL.Image.Image` object.
3435 :exception FileNotFoundError: If the file cannot be found.
3436 :exception PIL.UnidentifiedImageError: If the image cannot be opened and
3437 identified.
3438 :exception ValueError: If the ``mode`` is not "r", or if a ``StringIO``
3439 instance is used for ``fp``.
3440 :exception TypeError: If ``formats`` is not ``None``, a list or a tuple.
3441 """
3443 if mode != "r":
3444 msg = f"bad mode {repr(mode)}" # type: ignore[unreachable]
3445 raise ValueError(msg)
3446 elif isinstance(fp, io.StringIO):
3447 msg = ( # type: ignore[unreachable]
3448 "StringIO cannot be used to open an image. "
3449 "Binary data must be used instead."
3450 )
3451 raise ValueError(msg)
3453 if formats is None:
3454 formats = ID
3455 elif not isinstance(formats, (list, tuple)):
3456 msg = "formats must be a list or tuple" # type: ignore[unreachable]
3457 raise TypeError(msg)
3459 exclusive_fp = False
3460 filename: str | bytes = ""
3461 if is_path(fp):
3462 filename = os.fspath(fp)
3464 if filename:
3465 fp = builtins.open(filename, "rb")
3466 exclusive_fp = True
3467 else:
3468 fp = cast(IO[bytes], fp)
3470 try:
3471 fp.seek(0)
3472 except (AttributeError, io.UnsupportedOperation):
3473 fp = io.BytesIO(fp.read())
3474 exclusive_fp = True
3476 prefix = fp.read(16)
3478 preinit()
3480 warning_messages: list[str] = []
3482 def _open_core(
3483 fp: IO[bytes],
3484 filename: str | bytes,
3485 prefix: bytes,
3486 formats: list[str] | tuple[str, ...],
3487 ) -> ImageFile.ImageFile | None:
3488 for i in formats:
3489 i = i.upper()
3490 if i not in OPEN:
3491 init()
3492 try:
3493 factory, accept = OPEN[i]
3494 result = not accept or accept(prefix)
3495 if isinstance(result, str):
3496 warning_messages.append(result)
3497 elif result:
3498 fp.seek(0)
3499 im = factory(fp, filename)
3500 _decompression_bomb_check(im.size)
3501 return im
3502 except (SyntaxError, IndexError, TypeError, struct.error) as e:
3503 if WARN_POSSIBLE_FORMATS:
3504 warning_messages.append(i + " opening failed. " + str(e))
3505 except BaseException:
3506 if exclusive_fp:
3507 fp.close()
3508 raise
3509 return None
3511 im = _open_core(fp, filename, prefix, formats)
3513 if im is None and formats is ID:
3514 checked_formats = ID.copy()
3515 if init():
3516 im = _open_core(
3517 fp,
3518 filename,
3519 prefix,
3520 tuple(format for format in formats if format not in checked_formats),
3521 )
3523 if im:
3524 im._exclusive_fp = exclusive_fp
3525 return im
3527 if exclusive_fp:
3528 fp.close()
3529 for message in warning_messages:
3530 warnings.warn(message)
3531 msg = "cannot identify image file %r" % (filename if filename else fp)
3532 raise UnidentifiedImageError(msg)
3535#
3536# Image processing.
3539def alpha_composite(im1: Image, im2: Image) -> Image:
3540 """
3541 Alpha composite im2 over im1.
3543 :param im1: The first image. Must have mode RGBA.
3544 :param im2: The second image. Must have mode RGBA, and the same size as
3545 the first image.
3546 :returns: An :py:class:`~PIL.Image.Image` object.
3547 """
3549 im1.load()
3550 im2.load()
3551 return im1._new(core.alpha_composite(im1.im, im2.im))
3554def blend(im1: Image, im2: Image, alpha: float) -> Image:
3555 """
3556 Creates a new image by interpolating between two input images, using
3557 a constant alpha::
3559 out = image1 * (1.0 - alpha) + image2 * alpha
3561 :param im1: The first image.
3562 :param im2: The second image. Must have the same mode and size as
3563 the first image.
3564 :param alpha: The interpolation alpha factor. If alpha is 0.0, a
3565 copy of the first image is returned. If alpha is 1.0, a copy of
3566 the second image is returned. There are no restrictions on the
3567 alpha value. If necessary, the result is clipped to fit into
3568 the allowed output range.
3569 :returns: An :py:class:`~PIL.Image.Image` object.
3570 """
3572 im1.load()
3573 im2.load()
3574 return im1._new(core.blend(im1.im, im2.im, alpha))
3577def composite(image1: Image, image2: Image, mask: Image) -> Image:
3578 """
3579 Create composite image by blending images using a transparency mask.
3581 :param image1: The first image.
3582 :param image2: The second image. Must have the same mode and
3583 size as the first image.
3584 :param mask: A mask image. This image can have mode
3585 "1", "L", or "RGBA", and must have the same size as the
3586 other two images.
3587 """
3589 image = image2.copy()
3590 image.paste(image1, None, mask)
3591 return image
3594def eval(image: Image, *args: Callable[[int], float]) -> Image:
3595 """
3596 Applies the function (which should take one argument) to each pixel
3597 in the given image. If the image has more than one band, the same
3598 function is applied to each band. Note that the function is
3599 evaluated once for each possible pixel value, so you cannot use
3600 random components or other generators.
3602 :param image: The input image.
3603 :param function: A function object, taking one integer argument.
3604 :returns: An :py:class:`~PIL.Image.Image` object.
3605 """
3607 return image.point(args[0])
3610def merge(mode: str, bands: Sequence[Image]) -> Image:
3611 """
3612 Merge a set of single band images into a new multiband image.
3614 :param mode: The mode to use for the output image. See:
3615 :ref:`concept-modes`.
3616 :param bands: A sequence containing one single-band image for
3617 each band in the output image. All bands must have the
3618 same size.
3619 :returns: An :py:class:`~PIL.Image.Image` object.
3620 """
3622 if getmodebands(mode) != len(bands) or "*" in mode:
3623 msg = "wrong number of bands"
3624 raise ValueError(msg)
3625 for band in bands[1:]:
3626 if band.mode != getmodetype(mode):
3627 msg = "mode mismatch"
3628 raise ValueError(msg)
3629 if band.size != bands[0].size:
3630 msg = "size mismatch"
3631 raise ValueError(msg)
3632 for band in bands:
3633 band.load()
3634 return bands[0]._new(core.merge(mode, *[b.im for b in bands]))
3637# --------------------------------------------------------------------
3638# Plugin registry
3641def register_open(
3642 id: str,
3643 factory: (
3644 Callable[[IO[bytes], str | bytes], ImageFile.ImageFile]
3645 | type[ImageFile.ImageFile]
3646 ),
3647 accept: Callable[[bytes], bool | str] | None = None,
3648) -> None:
3649 """
3650 Register an image file plugin. This function should not be used
3651 in application code.
3653 :param id: An image format identifier.
3654 :param factory: An image file factory method.
3655 :param accept: An optional function that can be used to quickly
3656 reject images having another format.
3657 """
3658 id = id.upper()
3659 if id not in ID:
3660 ID.append(id)
3661 OPEN[id] = factory, accept
3664def register_mime(id: str, mimetype: str) -> None:
3665 """
3666 Registers an image MIME type by populating ``Image.MIME``. This function
3667 should not be used in application code.
3669 ``Image.MIME`` provides a mapping from image format identifiers to mime
3670 formats, but :py:meth:`~PIL.ImageFile.ImageFile.get_format_mimetype` can
3671 provide a different result for specific images.
3673 :param id: An image format identifier.
3674 :param mimetype: The image MIME type for this format.
3675 """
3676 MIME[id.upper()] = mimetype
3679def register_save(
3680 id: str, driver: Callable[[Image, IO[bytes], str | bytes], None]
3681) -> None:
3682 """
3683 Registers an image save function. This function should not be
3684 used in application code.
3686 :param id: An image format identifier.
3687 :param driver: A function to save images in this format.
3688 """
3689 SAVE[id.upper()] = driver
3692def register_save_all(
3693 id: str, driver: Callable[[Image, IO[bytes], str | bytes], None]
3694) -> None:
3695 """
3696 Registers an image function to save all the frames
3697 of a multiframe format. This function should not be
3698 used in application code.
3700 :param id: An image format identifier.
3701 :param driver: A function to save images in this format.
3702 """
3703 SAVE_ALL[id.upper()] = driver
3706def register_extension(id: str, extension: str) -> None:
3707 """
3708 Registers an image extension. This function should not be
3709 used in application code.
3711 :param id: An image format identifier.
3712 :param extension: An extension used for this format.
3713 """
3714 EXTENSION[extension.lower()] = id.upper()
3717def register_extensions(id: str, extensions: list[str]) -> None:
3718 """
3719 Registers image extensions. This function should not be
3720 used in application code.
3722 :param id: An image format identifier.
3723 :param extensions: A list of extensions used for this format.
3724 """
3725 for extension in extensions:
3726 register_extension(id, extension)
3729def registered_extensions() -> dict[str, str]:
3730 """
3731 Returns a dictionary containing all file extensions belonging
3732 to registered plugins
3733 """
3734 init()
3735 return EXTENSION
3738def register_decoder(name: str, decoder: type[ImageFile.PyDecoder]) -> None:
3739 """
3740 Registers an image decoder. This function should not be
3741 used in application code.
3743 :param name: The name of the decoder
3744 :param decoder: An ImageFile.PyDecoder object
3746 .. versionadded:: 4.1.0
3747 """
3748 DECODERS[name] = decoder
3751def register_encoder(name: str, encoder: type[ImageFile.PyEncoder]) -> None:
3752 """
3753 Registers an image encoder. This function should not be
3754 used in application code.
3756 :param name: The name of the encoder
3757 :param encoder: An ImageFile.PyEncoder object
3759 .. versionadded:: 4.1.0
3760 """
3761 ENCODERS[name] = encoder
3764# --------------------------------------------------------------------
3765# Simple display support.
3768def _show(image: Image, **options: Any) -> None:
3769 from . import ImageShow
3771 ImageShow.show(image, **options)
3774# --------------------------------------------------------------------
3775# Effects
3778def effect_mandelbrot(
3779 size: tuple[int, int], extent: tuple[float, float, float, float], quality: int
3780) -> Image:
3781 """
3782 Generate a Mandelbrot set covering the given extent.
3784 :param size: The requested size in pixels, as a 2-tuple:
3785 (width, height).
3786 :param extent: The extent to cover, as a 4-tuple:
3787 (x0, y0, x1, y1).
3788 :param quality: Quality.
3789 """
3790 return Image()._new(core.effect_mandelbrot(size, extent, quality))
3793def effect_noise(size: tuple[int, int], sigma: float) -> Image:
3794 """
3795 Generate Gaussian noise centered around 128.
3797 :param size: The requested size in pixels, as a 2-tuple:
3798 (width, height).
3799 :param sigma: Standard deviation of noise.
3800 """
3801 return Image()._new(core.effect_noise(size, sigma))
3804def linear_gradient(mode: str) -> Image:
3805 """
3806 Generate 256x256 linear gradient from black to white, top to bottom.
3808 :param mode: Input mode.
3809 """
3810 return Image()._new(core.linear_gradient(mode))
3813def radial_gradient(mode: str) -> Image:
3814 """
3815 Generate 256x256 radial gradient from black to white, centre to edge.
3817 :param mode: Input mode.
3818 """
3819 return Image()._new(core.radial_gradient(mode))
3822# --------------------------------------------------------------------
3823# Resources
3826def _apply_env_variables(env: dict[str, str] | None = None) -> None:
3827 env_dict = env if env is not None else os.environ
3829 for var_name, setter in [
3830 ("PILLOW_ALIGNMENT", core.set_alignment),
3831 ("PILLOW_BLOCK_SIZE", core.set_block_size),
3832 ("PILLOW_BLOCKS_MAX", core.set_blocks_max),
3833 ]:
3834 if var_name not in env_dict:
3835 continue
3837 var = env_dict[var_name].lower()
3839 units = 1
3840 for postfix, mul in [("k", 1024), ("m", 1024 * 1024)]:
3841 if var.endswith(postfix):
3842 units = mul
3843 var = var[: -len(postfix)]
3845 try:
3846 var_int = int(var) * units
3847 except ValueError:
3848 warnings.warn(f"{var_name} is not int")
3849 continue
3851 try:
3852 setter(var_int)
3853 except ValueError as e:
3854 warnings.warn(f"{var_name}: {e}")
3857_apply_env_variables()
3858atexit.register(core.clear_cache)
3861if TYPE_CHECKING:
3862 _ExifBase = MutableMapping[int, Any]
3863else:
3864 _ExifBase = MutableMapping
3867class Exif(_ExifBase):
3868 """
3869 This class provides read and write access to EXIF image data::
3871 from PIL import Image
3872 im = Image.open("exif.png")
3873 exif = im.getexif() # Returns an instance of this class
3875 Information can be read and written, iterated over or deleted::
3877 print(exif[274]) # 1
3878 exif[274] = 2
3879 for k, v in exif.items():
3880 print("Tag", k, "Value", v) # Tag 274 Value 2
3881 del exif[274]
3883 To access information beyond IFD0, :py:meth:`~PIL.Image.Exif.get_ifd`
3884 returns a dictionary::
3886 from PIL import ExifTags
3887 im = Image.open("exif_gps.jpg")
3888 exif = im.getexif()
3889 gps_ifd = exif.get_ifd(ExifTags.IFD.GPSInfo)
3890 print(gps_ifd)
3892 Other IFDs include ``ExifTags.IFD.Exif``, ``ExifTags.IFD.MakerNote``,
3893 ``ExifTags.IFD.Interop`` and ``ExifTags.IFD.IFD1``.
3895 :py:mod:`~PIL.ExifTags` also has enum classes to provide names for data::
3897 print(exif[ExifTags.Base.Software]) # PIL
3898 print(gps_ifd[ExifTags.GPS.GPSDateStamp]) # 1999:99:99 99:99:99
3899 """
3901 endian: str | None = None
3902 bigtiff = False
3903 _loaded = False
3905 def __init__(self) -> None:
3906 self._data: dict[int, Any] = {}
3907 self._hidden_data: dict[int, Any] = {}
3908 self._ifds: dict[int, dict[int, Any]] = {}
3909 self._info: TiffImagePlugin.ImageFileDirectory_v2 | None = None
3910 self._loaded_exif: bytes | None = None
3912 def _fixup(self, value: Any) -> Any:
3913 try:
3914 if len(value) == 1 and isinstance(value, tuple):
3915 return value[0]
3916 except Exception:
3917 pass
3918 return value
3920 def _fixup_dict(self, src_dict: dict[int, Any]) -> dict[int, Any]:
3921 # Helper function
3922 # returns a dict with any single item tuples/lists as individual values
3923 return {k: self._fixup(v) for k, v in src_dict.items()}
3925 def _get_ifd_dict(
3926 self, offset: int, group: int | None = None
3927 ) -> dict[int, Any] | None:
3928 try:
3929 # an offset pointer to the location of the nested embedded IFD.
3930 # It should be a long, but may be corrupted.
3931 self.fp.seek(offset)
3932 except (KeyError, TypeError):
3933 return None
3934 else:
3935 from . import TiffImagePlugin
3937 info = TiffImagePlugin.ImageFileDirectory_v2(self.head, group=group)
3938 info.load(self.fp)
3939 return self._fixup_dict(dict(info))
3941 def _get_head(self) -> bytes:
3942 version = b"\x2B" if self.bigtiff else b"\x2A"
3943 if self.endian == "<":
3944 head = b"II" + version + b"\x00" + o32le(8)
3945 else:
3946 head = b"MM\x00" + version + o32be(8)
3947 if self.bigtiff:
3948 head += o32le(8) if self.endian == "<" else o32be(8)
3949 head += b"\x00\x00\x00\x00"
3950 return head
3952 def load(self, data: bytes) -> None:
3953 # Extract EXIF information. This is highly experimental,
3954 # and is likely to be replaced with something better in a future
3955 # version.
3957 # The EXIF record consists of a TIFF file embedded in a JPEG
3958 # application marker (!).
3959 if data == self._loaded_exif:
3960 return
3961 self._loaded_exif = data
3962 self._data.clear()
3963 self._hidden_data.clear()
3964 self._ifds.clear()
3965 while data and data.startswith(b"Exif\x00\x00"):
3966 data = data[6:]
3967 if not data:
3968 self._info = None
3969 return
3971 self.fp: IO[bytes] = io.BytesIO(data)
3972 self.head = self.fp.read(8)
3973 # process dictionary
3974 from . import TiffImagePlugin
3976 self._info = TiffImagePlugin.ImageFileDirectory_v2(self.head)
3977 self.endian = self._info._endian
3978 self.fp.seek(self._info.next)
3979 self._info.load(self.fp)
3981 def load_from_fp(self, fp: IO[bytes], offset: int | None = None) -> None:
3982 self._loaded_exif = None
3983 self._data.clear()
3984 self._hidden_data.clear()
3985 self._ifds.clear()
3987 # process dictionary
3988 from . import TiffImagePlugin
3990 self.fp = fp
3991 if offset is not None:
3992 self.head = self._get_head()
3993 else:
3994 self.head = self.fp.read(8)
3995 self._info = TiffImagePlugin.ImageFileDirectory_v2(self.head)
3996 if self.endian is None:
3997 self.endian = self._info._endian
3998 if offset is None:
3999 offset = self._info.next
4000 self.fp.tell()
4001 self.fp.seek(offset)
4002 self._info.load(self.fp)
4004 def _get_merged_dict(self) -> dict[int, Any]:
4005 merged_dict = dict(self)
4007 # get EXIF extension
4008 if ExifTags.IFD.Exif in self:
4009 ifd = self._get_ifd_dict(self[ExifTags.IFD.Exif], ExifTags.IFD.Exif)
4010 if ifd:
4011 merged_dict.update(ifd)
4013 # GPS
4014 if ExifTags.IFD.GPSInfo in self:
4015 merged_dict[ExifTags.IFD.GPSInfo] = self._get_ifd_dict(
4016 self[ExifTags.IFD.GPSInfo], ExifTags.IFD.GPSInfo
4017 )
4019 return merged_dict
4021 def tobytes(self, offset: int = 8) -> bytes:
4022 from . import TiffImagePlugin
4024 head = self._get_head()
4025 ifd = TiffImagePlugin.ImageFileDirectory_v2(ifh=head)
4026 for tag, ifd_dict in self._ifds.items():
4027 if tag not in self:
4028 ifd[tag] = ifd_dict
4029 for tag, value in self.items():
4030 if tag in [
4031 ExifTags.IFD.Exif,
4032 ExifTags.IFD.GPSInfo,
4033 ] and not isinstance(value, dict):
4034 value = self.get_ifd(tag)
4035 if (
4036 tag == ExifTags.IFD.Exif
4037 and ExifTags.IFD.Interop in value
4038 and not isinstance(value[ExifTags.IFD.Interop], dict)
4039 ):
4040 value = value.copy()
4041 value[ExifTags.IFD.Interop] = self.get_ifd(ExifTags.IFD.Interop)
4042 ifd[tag] = value
4043 return b"Exif\x00\x00" + head + ifd.tobytes(offset)
4045 def get_ifd(self, tag: int) -> dict[int, Any]:
4046 if tag not in self._ifds:
4047 if tag == ExifTags.IFD.IFD1:
4048 if self._info is not None and self._info.next != 0:
4049 ifd = self._get_ifd_dict(self._info.next)
4050 if ifd is not None:
4051 self._ifds[tag] = ifd
4052 elif tag in [ExifTags.IFD.Exif, ExifTags.IFD.GPSInfo]:
4053 offset = self._hidden_data.get(tag, self.get(tag))
4054 if offset is not None:
4055 ifd = self._get_ifd_dict(offset, tag)
4056 if ifd is not None:
4057 self._ifds[tag] = ifd
4058 elif tag in [ExifTags.IFD.Interop, ExifTags.IFD.MakerNote]:
4059 if ExifTags.IFD.Exif not in self._ifds:
4060 self.get_ifd(ExifTags.IFD.Exif)
4061 tag_data = self._ifds[ExifTags.IFD.Exif][tag]
4062 if tag == ExifTags.IFD.MakerNote:
4063 from .TiffImagePlugin import ImageFileDirectory_v2
4065 if tag_data[:8] == b"FUJIFILM":
4066 ifd_offset = i32le(tag_data, 8)
4067 ifd_data = tag_data[ifd_offset:]
4069 makernote = {}
4070 for i in range(0, struct.unpack("<H", ifd_data[:2])[0]):
4071 ifd_tag, typ, count, data = struct.unpack(
4072 "<HHL4s", ifd_data[i * 12 + 2 : (i + 1) * 12 + 2]
4073 )
4074 try:
4075 (
4076 unit_size,
4077 handler,
4078 ) = ImageFileDirectory_v2._load_dispatch[typ]
4079 except KeyError:
4080 continue
4081 size = count * unit_size
4082 if size > 4:
4083 (offset,) = struct.unpack("<L", data)
4084 data = ifd_data[offset - 12 : offset + size - 12]
4085 else:
4086 data = data[:size]
4088 if len(data) != size:
4089 warnings.warn(
4090 "Possibly corrupt EXIF MakerNote data. "
4091 f"Expecting to read {size} bytes but only got "
4092 f"{len(data)}. Skipping tag {ifd_tag}"
4093 )
4094 continue
4096 if not data:
4097 continue
4099 makernote[ifd_tag] = handler(
4100 ImageFileDirectory_v2(), data, False
4101 )
4102 self._ifds[tag] = dict(self._fixup_dict(makernote))
4103 elif self.get(0x010F) == "Nintendo":
4104 makernote = {}
4105 for i in range(0, struct.unpack(">H", tag_data[:2])[0]):
4106 ifd_tag, typ, count, data = struct.unpack(
4107 ">HHL4s", tag_data[i * 12 + 2 : (i + 1) * 12 + 2]
4108 )
4109 if ifd_tag == 0x1101:
4110 # CameraInfo
4111 (offset,) = struct.unpack(">L", data)
4112 self.fp.seek(offset)
4114 camerainfo: dict[str, int | bytes] = {
4115 "ModelID": self.fp.read(4)
4116 }
4118 self.fp.read(4)
4119 # Seconds since 2000
4120 camerainfo["TimeStamp"] = i32le(self.fp.read(12))
4122 self.fp.read(4)
4123 camerainfo["InternalSerialNumber"] = self.fp.read(4)
4125 self.fp.read(12)
4126 parallax = self.fp.read(4)
4127 handler = ImageFileDirectory_v2._load_dispatch[
4128 TiffTags.FLOAT
4129 ][1]
4130 camerainfo["Parallax"] = handler(
4131 ImageFileDirectory_v2(), parallax, False
4132 )[0]
4134 self.fp.read(4)
4135 camerainfo["Category"] = self.fp.read(2)
4137 makernote = {0x1101: camerainfo}
4138 self._ifds[tag] = makernote
4139 else:
4140 # Interop
4141 ifd = self._get_ifd_dict(tag_data, tag)
4142 if ifd is not None:
4143 self._ifds[tag] = ifd
4144 ifd = self._ifds.setdefault(tag, {})
4145 if tag == ExifTags.IFD.Exif and self._hidden_data:
4146 ifd = {
4147 k: v
4148 for (k, v) in ifd.items()
4149 if k not in (ExifTags.IFD.Interop, ExifTags.IFD.MakerNote)
4150 }
4151 return ifd
4153 def hide_offsets(self) -> None:
4154 for tag in (ExifTags.IFD.Exif, ExifTags.IFD.GPSInfo):
4155 if tag in self:
4156 self._hidden_data[tag] = self[tag]
4157 del self[tag]
4159 def __str__(self) -> str:
4160 if self._info is not None:
4161 # Load all keys into self._data
4162 for tag in self._info:
4163 self[tag]
4165 return str(self._data)
4167 def __len__(self) -> int:
4168 keys = set(self._data)
4169 if self._info is not None:
4170 keys.update(self._info)
4171 return len(keys)
4173 def __getitem__(self, tag: int) -> Any:
4174 if self._info is not None and tag not in self._data and tag in self._info:
4175 self._data[tag] = self._fixup(self._info[tag])
4176 del self._info[tag]
4177 return self._data[tag]
4179 def __contains__(self, tag: object) -> bool:
4180 return tag in self._data or (self._info is not None and tag in self._info)
4182 def __setitem__(self, tag: int, value: Any) -> None:
4183 if self._info is not None and tag in self._info:
4184 del self._info[tag]
4185 self._data[tag] = value
4187 def __delitem__(self, tag: int) -> None:
4188 if self._info is not None and tag in self._info:
4189 del self._info[tag]
4190 else:
4191 del self._data[tag]
4193 def __iter__(self) -> Iterator[int]:
4194 keys = set(self._data)
4195 if self._info is not None:
4196 keys.update(self._info)
4197 return iter(keys)