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