Coverage for /usr/lib/python3/dist-packages/PIL/Image.py: 16%
1683 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
1#
2# The Python Imaging Library.
3# $Id$
4#
5# the Image class wrapper
6#
7# partial release history:
8# 1995-09-09 fl Created
9# 1996-03-11 fl PIL release 0.0 (proof of concept)
10# 1996-04-30 fl PIL release 0.1b1
11# 1999-07-28 fl PIL release 1.0 final
12# 2000-06-07 fl PIL release 1.1
13# 2000-10-20 fl PIL release 1.1.1
14# 2001-05-07 fl PIL release 1.1.2
15# 2002-03-15 fl PIL release 1.1.3
16# 2003-05-10 fl PIL release 1.1.4
17# 2005-03-28 fl PIL release 1.1.5
18# 2006-12-02 fl PIL release 1.1.6
19# 2009-11-15 fl PIL release 1.1.7
20#
21# Copyright (c) 1997-2009 by Secret Labs AB. All rights reserved.
22# Copyright (c) 1995-2009 by Fredrik Lundh.
23#
24# See the README file for information on usage and redistribution.
25#
27from __future__ import annotations
29import atexit
30import builtins
31import io
32import logging
33import math
34import os
35import re
36import struct
37import sys
38import tempfile
39import warnings
40from collections.abc import Callable, MutableMapping
41from enum import IntEnum
42from pathlib import Path
44try:
45 from defusedxml import ElementTree
46except ImportError:
47 ElementTree = None
49# VERSION was removed in Pillow 6.0.0.
50# PILLOW_VERSION was removed in Pillow 9.0.0.
51# Use __version__ instead.
52from . import (
53 ExifTags,
54 ImageMode,
55 TiffTags,
56 UnidentifiedImageError,
57 __version__,
58 _plugins,
59)
60from ._binary import i32le, o32be, o32le
61from ._util import DeferredError, is_path
63logger = logging.getLogger(__name__)
66class DecompressionBombWarning(RuntimeWarning):
67 pass
70class DecompressionBombError(Exception):
71 pass
74# Limit to around a quarter gigabyte for a 24-bit (3 bpp) image
75MAX_IMAGE_PIXELS = int(1024 * 1024 * 1024 // 4 // 3)
78try:
79 # If the _imaging C module is not present, Pillow will not load.
80 # Note that other modules should not refer to _imaging directly;
81 # import Image and use the Image.core variable instead.
82 # Also note that Image.core is not a publicly documented interface,
83 # and should be considered private and subject to change.
84 from . import _imaging as core
86 if __version__ != getattr(core, "PILLOW_VERSION", None):
87 msg = (
88 "The _imaging extension was built for another version of Pillow or PIL:\n"
89 f"Core version: {getattr(core, 'PILLOW_VERSION', None)}\n"
90 f"Pillow version: {__version__}"
91 )
92 raise ImportError(msg)
94except ImportError as v:
95 core = DeferredError.new(ImportError("The _imaging C module is not installed."))
96 # Explanations for ways that we know we might have an import error
97 if str(v).startswith("Module use of python"):
98 # The _imaging C module is present, but not compiled for
99 # the right version (windows only). Print a warning, if
100 # possible.
101 warnings.warn(
102 "The _imaging extension was built for another version of Python.",
103 RuntimeWarning,
104 )
105 elif str(v).startswith("The _imaging extension"):
106 warnings.warn(str(v), RuntimeWarning)
107 # Fail here anyway. Don't let people run with a mostly broken Pillow.
108 # see docs/porting.rst
109 raise
112USE_CFFI_ACCESS = False
113try:
114 import cffi
115except ImportError:
116 cffi = None
119def isImageType(t):
120 """
121 Checks if an object is an image object.
123 .. warning::
125 This function is for internal use only.
127 :param t: object to check if it's an image
128 :returns: True if the object is an image
129 """
130 return hasattr(t, "im")
133#
134# Constants
137# transpose
138class Transpose(IntEnum):
139 FLIP_LEFT_RIGHT = 0
140 FLIP_TOP_BOTTOM = 1
141 ROTATE_90 = 2
142 ROTATE_180 = 3
143 ROTATE_270 = 4
144 TRANSPOSE = 5
145 TRANSVERSE = 6
148# transforms (also defined in Imaging.h)
149class Transform(IntEnum):
150 AFFINE = 0
151 EXTENT = 1
152 PERSPECTIVE = 2
153 QUAD = 3
154 MESH = 4
157# resampling filters (also defined in Imaging.h)
158class Resampling(IntEnum):
159 NEAREST = 0
160 BOX = 4
161 BILINEAR = 2
162 HAMMING = 5
163 BICUBIC = 3
164 LANCZOS = 1
167_filters_support = {
168 Resampling.BOX: 0.5,
169 Resampling.BILINEAR: 1.0,
170 Resampling.HAMMING: 1.0,
171 Resampling.BICUBIC: 2.0,
172 Resampling.LANCZOS: 3.0,
173}
176# dithers
177class Dither(IntEnum):
178 NONE = 0
179 ORDERED = 1 # Not yet implemented
180 RASTERIZE = 2 # Not yet implemented
181 FLOYDSTEINBERG = 3 # default
184# palettes/quantizers
185class Palette(IntEnum):
186 WEB = 0
187 ADAPTIVE = 1
190class Quantize(IntEnum):
191 MEDIANCUT = 0
192 MAXCOVERAGE = 1
193 FASTOCTREE = 2
194 LIBIMAGEQUANT = 3
197module = sys.modules[__name__]
198for enum in (Transpose, Transform, Resampling, Dither, Palette, Quantize):
199 for item in enum:
200 setattr(module, item.name, item.value)
203if hasattr(core, "DEFAULT_STRATEGY"):
204 DEFAULT_STRATEGY = core.DEFAULT_STRATEGY
205 FILTERED = core.FILTERED
206 HUFFMAN_ONLY = core.HUFFMAN_ONLY
207 RLE = core.RLE
208 FIXED = core.FIXED
211# --------------------------------------------------------------------
212# Registries
214ID = []
215OPEN = {}
216MIME = {}
217SAVE = {}
218SAVE_ALL = {}
219EXTENSION = {}
220DECODERS = {}
221ENCODERS = {}
223# --------------------------------------------------------------------
224# Modes
226_ENDIAN = "<" if sys.byteorder == "little" else ">"
229def _conv_type_shape(im):
230 m = ImageMode.getmode(im.mode)
231 shape = (im.height, im.width)
232 extra = len(m.bands)
233 if extra != 1:
234 shape += (extra,)
235 return shape, m.typestr
238MODES = ["1", "CMYK", "F", "HSV", "I", "L", "LAB", "P", "RGB", "RGBA", "RGBX", "YCbCr"]
240# raw modes that may be memory mapped. NOTE: if you change this, you
241# may have to modify the stride calculation in map.c too!
242_MAPMODES = ("L", "P", "RGBX", "RGBA", "CMYK", "I;16", "I;16L", "I;16B")
245def getmodebase(mode):
246 """
247 Gets the "base" mode for given mode. This function returns "L" for
248 images that contain grayscale data, and "RGB" for images that
249 contain color data.
251 :param mode: Input mode.
252 :returns: "L" or "RGB".
253 :exception KeyError: If the input mode was not a standard mode.
254 """
255 return ImageMode.getmode(mode).basemode
258def getmodetype(mode):
259 """
260 Gets the storage type mode. Given a mode, this function returns a
261 single-layer mode suitable for storing individual bands.
263 :param mode: Input mode.
264 :returns: "L", "I", or "F".
265 :exception KeyError: If the input mode was not a standard mode.
266 """
267 return ImageMode.getmode(mode).basetype
270def getmodebandnames(mode):
271 """
272 Gets a list of individual band names. Given a mode, this function returns
273 a tuple containing the names of individual bands (use
274 :py:method:`~PIL.Image.getmodetype` to get the mode used to store each
275 individual band.
277 :param mode: Input mode.
278 :returns: A tuple containing band names. The length of the tuple
279 gives the number of bands in an image of the given mode.
280 :exception KeyError: If the input mode was not a standard mode.
281 """
282 return ImageMode.getmode(mode).bands
285def getmodebands(mode):
286 """
287 Gets the number of individual bands for this mode.
289 :param mode: Input mode.
290 :returns: The number of bands in this mode.
291 :exception KeyError: If the input mode was not a standard mode.
292 """
293 return len(ImageMode.getmode(mode).bands)
296# --------------------------------------------------------------------
297# Helpers
299_initialized = 0
302def preinit():
303 """
304 Explicitly loads BMP, GIF, JPEG, PPM and PPM file format drivers.
306 It is called when opening or saving images.
307 """
309 global _initialized
310 if _initialized >= 1:
311 return
313 try:
314 from . import BmpImagePlugin
316 assert BmpImagePlugin
317 except ImportError:
318 pass
319 try:
320 from . import GifImagePlugin
322 assert GifImagePlugin
323 except ImportError:
324 pass
325 try:
326 from . import JpegImagePlugin
328 assert JpegImagePlugin
329 except ImportError:
330 pass
331 try:
332 from . import PpmImagePlugin
334 assert PpmImagePlugin
335 except ImportError:
336 pass
337 try:
338 from . import PngImagePlugin
340 assert PngImagePlugin
341 except ImportError:
342 pass
344 _initialized = 1
347def init():
348 """
349 Explicitly initializes the Python Imaging Library. This function
350 loads all available file format drivers.
352 It is called when opening or saving images if :py:meth:`~preinit()` is
353 insufficient, and by :py:meth:`~PIL.features.pilinfo`.
354 """
356 global _initialized
357 if _initialized >= 2:
358 return 0
360 parent_name = __name__.rpartition(".")[0]
361 for plugin in _plugins:
362 try:
363 logger.debug("Importing %s", plugin)
364 __import__(f"{parent_name}.{plugin}", globals(), locals(), [])
365 except ImportError as e:
366 logger.debug("Image: failed to import %s: %s", plugin, e)
368 if OPEN or SAVE:
369 _initialized = 2
370 return 1
373# --------------------------------------------------------------------
374# Codec factories (used by tobytes/frombytes and ImageFile.load)
377def _getdecoder(mode, decoder_name, args, extra=()):
378 # tweak arguments
379 if args is None:
380 args = ()
381 elif not isinstance(args, tuple):
382 args = (args,)
384 try:
385 decoder = DECODERS[decoder_name]
386 except KeyError:
387 pass
388 else:
389 return decoder(mode, *args + extra)
391 try:
392 # get decoder
393 decoder = getattr(core, decoder_name + "_decoder")
394 except AttributeError as e:
395 msg = f"decoder {decoder_name} not available"
396 raise OSError(msg) from e
397 return decoder(mode, *args + extra)
400def _getencoder(mode, encoder_name, args, extra=()):
401 # tweak arguments
402 if args is None:
403 args = ()
404 elif not isinstance(args, tuple):
405 args = (args,)
407 try:
408 encoder = ENCODERS[encoder_name]
409 except KeyError:
410 pass
411 else:
412 return encoder(mode, *args + extra)
414 try:
415 # get encoder
416 encoder = getattr(core, encoder_name + "_encoder")
417 except AttributeError as e:
418 msg = f"encoder {encoder_name} not available"
419 raise OSError(msg) from e
420 return encoder(mode, *args + extra)
423# --------------------------------------------------------------------
424# Simple expression analyzer
427class _E:
428 def __init__(self, scale, offset):
429 self.scale = scale
430 self.offset = offset
432 def __neg__(self):
433 return _E(-self.scale, -self.offset)
435 def __add__(self, other):
436 if isinstance(other, _E):
437 return _E(self.scale + other.scale, self.offset + other.offset)
438 return _E(self.scale, self.offset + other)
440 __radd__ = __add__
442 def __sub__(self, other):
443 return self + -other
445 def __rsub__(self, other):
446 return other + -self
448 def __mul__(self, other):
449 if isinstance(other, _E):
450 return NotImplemented
451 return _E(self.scale * other, self.offset * other)
453 __rmul__ = __mul__
455 def __truediv__(self, other):
456 if isinstance(other, _E):
457 return NotImplemented
458 return _E(self.scale / other, self.offset / other)
461def _getscaleoffset(expr):
462 a = expr(_E(1, 0))
463 return (a.scale, a.offset) if isinstance(a, _E) else (0, a)
466# --------------------------------------------------------------------
467# Implementation wrapper
470class Image:
471 """
472 This class represents an image object. To create
473 :py:class:`~PIL.Image.Image` objects, use the appropriate factory
474 functions. There's hardly ever any reason to call the Image constructor
475 directly.
477 * :py:func:`~PIL.Image.open`
478 * :py:func:`~PIL.Image.new`
479 * :py:func:`~PIL.Image.frombytes`
480 """
482 format: str | None = None
483 format_description: str | None = None
484 _close_exclusive_fp_after_loading = True
486 def __init__(self):
487 # FIXME: take "new" parameters / other image?
488 # FIXME: turn mode and size into delegating properties?
489 self.im = None
490 self._mode = ""
491 self._size = (0, 0)
492 self.palette = None
493 self.info = {}
494 self.readonly = 0
495 self.pyaccess = None
496 self._exif = None
498 @property
499 def width(self):
500 return self.size[0]
502 @property
503 def height(self):
504 return self.size[1]
506 @property
507 def size(self):
508 return self._size
510 @property
511 def mode(self):
512 return self._mode
514 def _new(self, im):
515 new = Image()
516 new.im = im
517 new._mode = im.mode
518 new._size = im.size
519 if im.mode in ("P", "PA"):
520 if self.palette:
521 new.palette = self.palette.copy()
522 else:
523 from . import ImagePalette
525 new.palette = ImagePalette.ImagePalette()
526 new.info = self.info.copy()
527 return new
529 # Context manager support
530 def __enter__(self):
531 return self
533 def _close_fp(self):
534 if getattr(self, "_fp", False):
535 if self._fp != self.fp:
536 self._fp.close()
537 self._fp = DeferredError(ValueError("Operation on closed image"))
538 if self.fp:
539 self.fp.close()
541 def __exit__(self, *args):
542 if hasattr(self, "fp"):
543 if getattr(self, "_exclusive_fp", False):
544 self._close_fp()
545 self.fp = None
547 def close(self):
548 """
549 Closes the file pointer, if possible.
551 This operation will destroy the image core and release its memory.
552 The image data will be unusable afterward.
554 This function is required to close images that have multiple frames or
555 have not had their file read and closed by the
556 :py:meth:`~PIL.Image.Image.load` method. See :ref:`file-handling` for
557 more information.
558 """
559 if hasattr(self, "fp"):
560 try:
561 self._close_fp()
562 self.fp = None
563 except Exception as msg:
564 logger.debug("Error closing: %s", msg)
566 if getattr(self, "map", None):
567 self.map = None
569 # Instead of simply setting to None, we're setting up a
570 # deferred error that will better explain that the core image
571 # object is gone.
572 self.im = DeferredError(ValueError("Operation on closed image"))
574 def _copy(self):
575 self.load()
576 self.im = self.im.copy()
577 self.pyaccess = None
578 self.readonly = 0
580 def _ensure_mutable(self):
581 if self.readonly:
582 self._copy()
583 else:
584 self.load()
586 def _dump(self, file=None, format=None, **options):
587 suffix = ""
588 if format:
589 suffix = "." + format
591 if not file:
592 f, filename = tempfile.mkstemp(suffix)
593 os.close(f)
594 else:
595 filename = file
596 if not filename.endswith(suffix):
597 filename = filename + suffix
599 self.load()
601 if not format or format == "PPM":
602 self.im.save_ppm(filename)
603 else:
604 self.save(filename, format, **options)
606 return filename
608 def __eq__(self, other):
609 return (
610 self.__class__ is other.__class__
611 and self.mode == other.mode
612 and self.size == other.size
613 and self.info == other.info
614 and self.getpalette() == other.getpalette()
615 and self.tobytes() == other.tobytes()
616 )
618 def __repr__(self):
619 return "<%s.%s image mode=%s size=%dx%d at 0x%X>" % (
620 self.__class__.__module__,
621 self.__class__.__name__,
622 self.mode,
623 self.size[0],
624 self.size[1],
625 id(self),
626 )
628 def _repr_pretty_(self, p, cycle):
629 """IPython plain text display support"""
631 # Same as __repr__ but without unpredictable id(self),
632 # to keep Jupyter notebook `text/plain` output stable.
633 p.text(
634 "<%s.%s image mode=%s size=%dx%d>"
635 % (
636 self.__class__.__module__,
637 self.__class__.__name__,
638 self.mode,
639 self.size[0],
640 self.size[1],
641 )
642 )
644 def _repr_image(self, image_format, **kwargs):
645 """Helper function for iPython display hook.
647 :param image_format: Image format.
648 :returns: image as bytes, saved into the given format.
649 """
650 b = io.BytesIO()
651 try:
652 self.save(b, image_format, **kwargs)
653 except Exception:
654 return None
655 return b.getvalue()
657 def _repr_png_(self):
658 """iPython display hook support for PNG format.
660 :returns: PNG version of the image as bytes
661 """
662 return self._repr_image("PNG", compress_level=1)
664 def _repr_jpeg_(self):
665 """iPython display hook support for JPEG format.
667 :returns: JPEG version of the image as bytes
668 """
669 return self._repr_image("JPEG")
671 @property
672 def __array_interface__(self):
673 # numpy array interface support
674 new = {"version": 3}
675 try:
676 if self.mode == "1":
677 # Binary images need to be extended from bits to bytes
678 # See: https://github.com/python-pillow/Pillow/issues/350
679 new["data"] = self.tobytes("raw", "L")
680 else:
681 new["data"] = self.tobytes()
682 except Exception as e:
683 if not isinstance(e, (MemoryError, RecursionError)):
684 try:
685 import numpy
686 from packaging.version import parse as parse_version
687 except ImportError:
688 pass
689 else:
690 if parse_version(numpy.__version__) < parse_version("1.23"):
691 warnings.warn(e)
692 raise
693 new["shape"], new["typestr"] = _conv_type_shape(self)
694 return new
696 def __getstate__(self):
697 im_data = self.tobytes() # load image first
698 return [self.info, self.mode, self.size, self.getpalette(), im_data]
700 def __setstate__(self, state):
701 Image.__init__(self)
702 info, mode, size, palette, data = state
703 self.info = info
704 self._mode = mode
705 self._size = size
706 self.im = core.new(mode, size)
707 if mode in ("L", "LA", "P", "PA") and palette:
708 self.putpalette(palette)
709 self.frombytes(data)
711 def tobytes(self, encoder_name="raw", *args):
712 """
713 Return image as a bytes object.
715 .. warning::
717 This method returns the raw image data from the internal
718 storage. For compressed image data (e.g. PNG, JPEG) use
719 :meth:`~.save`, with a BytesIO parameter for in-memory
720 data.
722 :param encoder_name: What encoder to use. The default is to
723 use the standard "raw" encoder.
725 A list of C encoders can be seen under
726 codecs section of the function array in
727 :file:`_imaging.c`. Python encoders are
728 registered within the relevant plugins.
729 :param args: Extra arguments to the encoder.
730 :returns: A :py:class:`bytes` object.
731 """
733 # may pass tuple instead of argument list
734 if len(args) == 1 and isinstance(args[0], tuple):
735 args = args[0]
737 if encoder_name == "raw" and args == ():
738 args = self.mode
740 self.load()
742 if self.width == 0 or self.height == 0:
743 return b""
745 # unpack data
746 e = _getencoder(self.mode, encoder_name, args)
747 e.setimage(self.im)
749 bufsize = max(65536, self.size[0] * 4) # see RawEncode.c
751 output = []
752 while True:
753 bytes_consumed, errcode, data = e.encode(bufsize)
754 output.append(data)
755 if errcode:
756 break
757 if errcode < 0:
758 msg = f"encoder error {errcode} in tobytes"
759 raise RuntimeError(msg)
761 return b"".join(output)
763 def tobitmap(self, name="image"):
764 """
765 Returns the image converted to an X11 bitmap.
767 .. note:: This method only works for mode "1" images.
769 :param name: The name prefix to use for the bitmap variables.
770 :returns: A string containing an X11 bitmap.
771 :raises ValueError: If the mode is not "1"
772 """
774 self.load()
775 if self.mode != "1":
776 msg = "not a bitmap"
777 raise ValueError(msg)
778 data = self.tobytes("xbm")
779 return b"".join(
780 [
781 f"#define {name}_width {self.size[0]}\n".encode("ascii"),
782 f"#define {name}_height {self.size[1]}\n".encode("ascii"),
783 f"static char {name}_bits[] = {{\n".encode("ascii"),
784 data,
785 b"};",
786 ]
787 )
789 def frombytes(self, data, decoder_name="raw", *args):
790 """
791 Loads this image with pixel data from a bytes object.
793 This method is similar to the :py:func:`~PIL.Image.frombytes` function,
794 but loads data into this image instead of creating a new image object.
795 """
797 if self.width == 0 or self.height == 0:
798 return
800 # may pass tuple instead of argument list
801 if len(args) == 1 and isinstance(args[0], tuple):
802 args = args[0]
804 # default format
805 if decoder_name == "raw" and args == ():
806 args = self.mode
808 # unpack data
809 d = _getdecoder(self.mode, decoder_name, args)
810 d.setimage(self.im)
811 s = d.decode(data)
813 if s[0] >= 0:
814 msg = "not enough image data"
815 raise ValueError(msg)
816 if s[1] != 0:
817 msg = "cannot decode image data"
818 raise ValueError(msg)
820 def load(self):
821 """
822 Allocates storage for the image and loads the pixel data. In
823 normal cases, you don't need to call this method, since the
824 Image class automatically loads an opened image when it is
825 accessed for the first time.
827 If the file associated with the image was opened by Pillow, then this
828 method will close it. The exception to this is if the image has
829 multiple frames, in which case the file will be left open for seek
830 operations. See :ref:`file-handling` for more information.
832 :returns: An image access object.
833 :rtype: :ref:`PixelAccess` or :py:class:`PIL.PyAccess`
834 """
835 if self.im is not None and self.palette and self.palette.dirty:
836 # realize palette
837 mode, arr = self.palette.getdata()
838 self.im.putpalette(mode, arr)
839 self.palette.dirty = 0
840 self.palette.rawmode = None
841 if "transparency" in self.info and mode in ("LA", "PA"):
842 if isinstance(self.info["transparency"], int):
843 self.im.putpalettealpha(self.info["transparency"], 0)
844 else:
845 self.im.putpalettealphas(self.info["transparency"])
846 self.palette.mode = "RGBA"
847 else:
848 palette_mode = "RGBA" if mode.startswith("RGBA") else "RGB"
849 self.palette.mode = palette_mode
850 self.palette.palette = self.im.getpalette(palette_mode, palette_mode)
852 if self.im is not None:
853 if cffi and USE_CFFI_ACCESS:
854 if self.pyaccess:
855 return self.pyaccess
856 from . import PyAccess
858 self.pyaccess = PyAccess.new(self, self.readonly)
859 if self.pyaccess:
860 return self.pyaccess
861 return self.im.pixel_access(self.readonly)
863 def verify(self):
864 """
865 Verifies the contents of a file. For data read from a file, this
866 method attempts to determine if the file is broken, without
867 actually decoding the image data. If this method finds any
868 problems, it raises suitable exceptions. If you need to load
869 the image after using this method, you must reopen the image
870 file.
871 """
872 pass
874 def convert(
875 self, mode=None, matrix=None, dither=None, palette=Palette.WEB, colors=256
876 ):
877 """
878 Returns a converted copy of this image. For the "P" mode, this
879 method translates pixels through the palette. If mode is
880 omitted, a mode is chosen so that all information in the image
881 and the palette can be represented without a palette.
883 The current version supports all possible conversions between
884 "L", "RGB" and "CMYK". The ``matrix`` argument only supports "L"
885 and "RGB".
887 When translating a color image to grayscale (mode "L"),
888 the library uses the ITU-R 601-2 luma transform::
890 L = R * 299/1000 + G * 587/1000 + B * 114/1000
892 The default method of converting a grayscale ("L") or "RGB"
893 image into a bilevel (mode "1") image uses Floyd-Steinberg
894 dither to approximate the original image luminosity levels. If
895 dither is ``None``, all values larger than 127 are set to 255 (white),
896 all other values to 0 (black). To use other thresholds, use the
897 :py:meth:`~PIL.Image.Image.point` method.
899 When converting from "RGBA" to "P" without a ``matrix`` argument,
900 this passes the operation to :py:meth:`~PIL.Image.Image.quantize`,
901 and ``dither`` and ``palette`` are ignored.
903 When converting from "PA", if an "RGBA" palette is present, the alpha
904 channel from the image will be used instead of the values from the palette.
906 :param mode: The requested mode. See: :ref:`concept-modes`.
907 :param matrix: An optional conversion matrix. If given, this
908 should be 4- or 12-tuple containing floating point values.
909 :param dither: Dithering method, used when converting from
910 mode "RGB" to "P" or from "RGB" or "L" to "1".
911 Available methods are :data:`Dither.NONE` or :data:`Dither.FLOYDSTEINBERG`
912 (default). Note that this is not used when ``matrix`` is supplied.
913 :param palette: Palette to use when converting from mode "RGB"
914 to "P". Available palettes are :data:`Palette.WEB` or
915 :data:`Palette.ADAPTIVE`.
916 :param colors: Number of colors to use for the :data:`Palette.ADAPTIVE`
917 palette. Defaults to 256.
918 :rtype: :py:class:`~PIL.Image.Image`
919 :returns: An :py:class:`~PIL.Image.Image` object.
920 """
922 self.load()
924 has_transparency = "transparency" in self.info
925 if not mode and self.mode == "P":
926 # determine default mode
927 if self.palette:
928 mode = self.palette.mode
929 else:
930 mode = "RGB"
931 if mode == "RGB" and has_transparency:
932 mode = "RGBA"
933 if not mode or (mode == self.mode and not matrix):
934 return self.copy()
936 if matrix:
937 # matrix conversion
938 if mode not in ("L", "RGB"):
939 msg = "illegal conversion"
940 raise ValueError(msg)
941 im = self.im.convert_matrix(mode, matrix)
942 new_im = self._new(im)
943 if has_transparency and self.im.bands == 3:
944 transparency = new_im.info["transparency"]
946 def convert_transparency(m, v):
947 v = m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3] * 0.5
948 return max(0, min(255, int(v)))
950 if mode == "L":
951 transparency = convert_transparency(matrix, transparency)
952 elif len(mode) == 3:
953 transparency = tuple(
954 convert_transparency(matrix[i * 4 : i * 4 + 4], transparency)
955 for i in range(0, len(transparency))
956 )
957 new_im.info["transparency"] = transparency
958 return new_im
960 if mode == "P" and self.mode == "RGBA":
961 return self.quantize(colors)
963 trns = None
964 delete_trns = False
965 # transparency handling
966 if has_transparency:
967 if (self.mode in ("1", "L", "I") and mode in ("LA", "RGBA")) or (
968 self.mode == "RGB" and mode == "RGBA"
969 ):
970 # Use transparent conversion to promote from transparent
971 # color to an alpha channel.
972 new_im = self._new(
973 self.im.convert_transparent(mode, self.info["transparency"])
974 )
975 del new_im.info["transparency"]
976 return new_im
977 elif self.mode in ("L", "RGB", "P") and mode in ("L", "RGB", "P"):
978 t = self.info["transparency"]
979 if isinstance(t, bytes):
980 # Dragons. This can't be represented by a single color
981 warnings.warn(
982 "Palette images with Transparency expressed in bytes should be "
983 "converted to RGBA images"
984 )
985 delete_trns = True
986 else:
987 # get the new transparency color.
988 # use existing conversions
989 trns_im = new(self.mode, (1, 1))
990 if self.mode == "P":
991 trns_im.putpalette(self.palette)
992 if isinstance(t, tuple):
993 err = "Couldn't allocate a palette color for transparency"
994 try:
995 t = trns_im.palette.getcolor(t, self)
996 except ValueError as e:
997 if str(e) == "cannot allocate more than 256 colors":
998 # If all 256 colors are in use,
999 # then there is no need for transparency
1000 t = None
1001 else:
1002 raise ValueError(err) from e
1003 if t is None:
1004 trns = None
1005 else:
1006 trns_im.putpixel((0, 0), t)
1008 if mode in ("L", "RGB"):
1009 trns_im = trns_im.convert(mode)
1010 else:
1011 # can't just retrieve the palette number, got to do it
1012 # after quantization.
1013 trns_im = trns_im.convert("RGB")
1014 trns = trns_im.getpixel((0, 0))
1016 elif self.mode == "P" and mode in ("LA", "PA", "RGBA"):
1017 t = self.info["transparency"]
1018 delete_trns = True
1020 if isinstance(t, bytes):
1021 self.im.putpalettealphas(t)
1022 elif isinstance(t, int):
1023 self.im.putpalettealpha(t, 0)
1024 else:
1025 msg = "Transparency for P mode should be bytes or int"
1026 raise ValueError(msg)
1028 if mode == "P" and palette == Palette.ADAPTIVE:
1029 im = self.im.quantize(colors)
1030 new_im = self._new(im)
1031 from . import ImagePalette
1033 new_im.palette = ImagePalette.ImagePalette(
1034 "RGB", new_im.im.getpalette("RGB")
1035 )
1036 if delete_trns:
1037 # This could possibly happen if we requantize to fewer colors.
1038 # The transparency would be totally off in that case.
1039 del new_im.info["transparency"]
1040 if trns is not None:
1041 try:
1042 new_im.info["transparency"] = new_im.palette.getcolor(trns, new_im)
1043 except Exception:
1044 # if we can't make a transparent color, don't leave the old
1045 # transparency hanging around to mess us up.
1046 del new_im.info["transparency"]
1047 warnings.warn("Couldn't allocate palette entry for transparency")
1048 return new_im
1050 if "LAB" in (self.mode, mode):
1051 other_mode = mode if self.mode == "LAB" else self.mode
1052 if other_mode in ("RGB", "RGBA", "RGBX"):
1053 from . import ImageCms
1055 srgb = ImageCms.createProfile("sRGB")
1056 lab = ImageCms.createProfile("LAB")
1057 profiles = [lab, srgb] if self.mode == "LAB" else [srgb, lab]
1058 transform = ImageCms.buildTransform(
1059 profiles[0], profiles[1], self.mode, mode
1060 )
1061 return transform.apply(self)
1063 # colorspace conversion
1064 if dither is None:
1065 dither = Dither.FLOYDSTEINBERG
1067 try:
1068 im = self.im.convert(mode, dither)
1069 except ValueError:
1070 try:
1071 # normalize source image and try again
1072 modebase = getmodebase(self.mode)
1073 if modebase == self.mode:
1074 raise
1075 im = self.im.convert(modebase)
1076 im = im.convert(mode, dither)
1077 except KeyError as e:
1078 msg = "illegal conversion"
1079 raise ValueError(msg) from e
1081 new_im = self._new(im)
1082 if mode == "P" and palette != Palette.ADAPTIVE:
1083 from . import ImagePalette
1085 new_im.palette = ImagePalette.ImagePalette("RGB", im.getpalette("RGB"))
1086 if delete_trns:
1087 # crash fail if we leave a bytes transparency in an rgb/l mode.
1088 del new_im.info["transparency"]
1089 if trns is not None:
1090 if new_im.mode == "P":
1091 try:
1092 new_im.info["transparency"] = new_im.palette.getcolor(trns, new_im)
1093 except ValueError as e:
1094 del new_im.info["transparency"]
1095 if str(e) != "cannot allocate more than 256 colors":
1096 # If all 256 colors are in use,
1097 # then there is no need for transparency
1098 warnings.warn(
1099 "Couldn't allocate palette entry for transparency"
1100 )
1101 else:
1102 new_im.info["transparency"] = trns
1103 return new_im
1105 def quantize(
1106 self,
1107 colors=256,
1108 method=None,
1109 kmeans=0,
1110 palette=None,
1111 dither=Dither.FLOYDSTEINBERG,
1112 ):
1113 """
1114 Convert the image to 'P' mode with the specified number
1115 of colors.
1117 :param colors: The desired number of colors, <= 256
1118 :param method: :data:`Quantize.MEDIANCUT` (median cut),
1119 :data:`Quantize.MAXCOVERAGE` (maximum coverage),
1120 :data:`Quantize.FASTOCTREE` (fast octree),
1121 :data:`Quantize.LIBIMAGEQUANT` (libimagequant; check support
1122 using :py:func:`PIL.features.check_feature` with
1123 ``feature="libimagequant"``).
1125 By default, :data:`Quantize.MEDIANCUT` will be used.
1127 The exception to this is RGBA images. :data:`Quantize.MEDIANCUT`
1128 and :data:`Quantize.MAXCOVERAGE` do not support RGBA images, so
1129 :data:`Quantize.FASTOCTREE` is used by default instead.
1130 :param kmeans: Integer
1131 :param palette: Quantize to the palette of given
1132 :py:class:`PIL.Image.Image`.
1133 :param dither: Dithering method, used when converting from
1134 mode "RGB" to "P" or from "RGB" or "L" to "1".
1135 Available methods are :data:`Dither.NONE` or :data:`Dither.FLOYDSTEINBERG`
1136 (default).
1137 :returns: A new image
1138 """
1140 self.load()
1142 if method is None:
1143 # defaults:
1144 method = Quantize.MEDIANCUT
1145 if self.mode == "RGBA":
1146 method = Quantize.FASTOCTREE
1148 if self.mode == "RGBA" and method not in (
1149 Quantize.FASTOCTREE,
1150 Quantize.LIBIMAGEQUANT,
1151 ):
1152 # Caller specified an invalid mode.
1153 msg = (
1154 "Fast Octree (method == 2) and libimagequant (method == 3) "
1155 "are the only valid methods for quantizing RGBA images"
1156 )
1157 raise ValueError(msg)
1159 if palette:
1160 # use palette from reference image
1161 palette.load()
1162 if palette.mode != "P":
1163 msg = "bad mode for palette image"
1164 raise ValueError(msg)
1165 if self.mode not in {"RGB", "L"}:
1166 msg = "only RGB or L mode images can be quantized to a palette"
1167 raise ValueError(msg)
1168 im = self.im.convert("P", dither, palette.im)
1169 new_im = self._new(im)
1170 new_im.palette = palette.palette.copy()
1171 return new_im
1173 im = self._new(self.im.quantize(colors, method, kmeans))
1175 from . import ImagePalette
1177 mode = im.im.getpalettemode()
1178 palette = im.im.getpalette(mode, mode)[: colors * len(mode)]
1179 im.palette = ImagePalette.ImagePalette(mode, palette)
1181 return im
1183 def copy(self) -> Image:
1184 """
1185 Copies this image. Use this method if you wish to paste things
1186 into an image, but still retain the original.
1188 :rtype: :py:class:`~PIL.Image.Image`
1189 :returns: An :py:class:`~PIL.Image.Image` object.
1190 """
1191 self.load()
1192 return self._new(self.im.copy())
1194 __copy__ = copy
1196 def crop(self, box=None) -> Image:
1197 """
1198 Returns a rectangular region from this image. The box is a
1199 4-tuple defining the left, upper, right, and lower pixel
1200 coordinate. See :ref:`coordinate-system`.
1202 Note: Prior to Pillow 3.4.0, this was a lazy operation.
1204 :param box: The crop rectangle, as a (left, upper, right, lower)-tuple.
1205 :rtype: :py:class:`~PIL.Image.Image`
1206 :returns: An :py:class:`~PIL.Image.Image` object.
1207 """
1209 if box is None:
1210 return self.copy()
1212 if box[2] < box[0]:
1213 msg = "Coordinate 'right' is less than 'left'"
1214 raise ValueError(msg)
1215 elif box[3] < box[1]:
1216 msg = "Coordinate 'lower' is less than 'upper'"
1217 raise ValueError(msg)
1219 self.load()
1220 return self._new(self._crop(self.im, box))
1222 def _crop(self, im, box):
1223 """
1224 Returns a rectangular region from the core image object im.
1226 This is equivalent to calling im.crop((x0, y0, x1, y1)), but
1227 includes additional sanity checks.
1229 :param im: a core image object
1230 :param box: The crop rectangle, as a (left, upper, right, lower)-tuple.
1231 :returns: A core image object.
1232 """
1234 x0, y0, x1, y1 = map(int, map(round, box))
1236 absolute_values = (abs(x1 - x0), abs(y1 - y0))
1238 _decompression_bomb_check(absolute_values)
1240 return im.crop((x0, y0, x1, y1))
1242 def draft(self, mode, size):
1243 """
1244 Configures the image file loader so it returns a version of the
1245 image that as closely as possible matches the given mode and
1246 size. For example, you can use this method to convert a color
1247 JPEG to grayscale while loading it.
1249 If any changes are made, returns a tuple with the chosen ``mode`` and
1250 ``box`` with coordinates of the original image within the altered one.
1252 Note that this method modifies the :py:class:`~PIL.Image.Image` object
1253 in place. If the image has already been loaded, this method has no
1254 effect.
1256 Note: This method is not implemented for most images. It is
1257 currently implemented only for JPEG and MPO images.
1259 :param mode: The requested mode.
1260 :param size: The requested size in pixels, as a 2-tuple:
1261 (width, height).
1262 """
1263 pass
1265 def _expand(self, xmargin, ymargin=None):
1266 if ymargin is None:
1267 ymargin = xmargin
1268 self.load()
1269 return self._new(self.im.expand(xmargin, ymargin))
1271 def filter(self, filter):
1272 """
1273 Filters this image using the given filter. For a list of
1274 available filters, see the :py:mod:`~PIL.ImageFilter` module.
1276 :param filter: Filter kernel.
1277 :returns: An :py:class:`~PIL.Image.Image` object."""
1279 from . import ImageFilter
1281 self.load()
1283 if isinstance(filter, Callable):
1284 filter = filter()
1285 if not hasattr(filter, "filter"):
1286 msg = "filter argument should be ImageFilter.Filter instance or class"
1287 raise TypeError(msg)
1289 multiband = isinstance(filter, ImageFilter.MultibandFilter)
1290 if self.im.bands == 1 or multiband:
1291 return self._new(filter.filter(self.im))
1293 ims = [
1294 self._new(filter.filter(self.im.getband(c))) for c in range(self.im.bands)
1295 ]
1296 return merge(self.mode, ims)
1298 def getbands(self):
1299 """
1300 Returns a tuple containing the name of each band in this image.
1301 For example, ``getbands`` on an RGB image returns ("R", "G", "B").
1303 :returns: A tuple containing band names.
1304 :rtype: tuple
1305 """
1306 return ImageMode.getmode(self.mode).bands
1308 def getbbox(self, *, alpha_only=True):
1309 """
1310 Calculates the bounding box of the non-zero regions in the
1311 image.
1313 :param alpha_only: Optional flag, defaulting to ``True``.
1314 If ``True`` and the image has an alpha channel, trim transparent pixels.
1315 Otherwise, trim pixels when all channels are zero.
1316 Keyword-only argument.
1317 :returns: The bounding box is returned as a 4-tuple defining the
1318 left, upper, right, and lower pixel coordinate. See
1319 :ref:`coordinate-system`. If the image is completely empty, this
1320 method returns None.
1322 """
1324 self.load()
1325 return self.im.getbbox(alpha_only)
1327 def getcolors(self, maxcolors=256):
1328 """
1329 Returns a list of colors used in this image.
1331 The colors will be in the image's mode. For example, an RGB image will
1332 return a tuple of (red, green, blue) color values, and a P image will
1333 return the index of the color in the palette.
1335 :param maxcolors: Maximum number of colors. If this number is
1336 exceeded, this method returns None. The default limit is
1337 256 colors.
1338 :returns: An unsorted list of (count, pixel) values.
1339 """
1341 self.load()
1342 if self.mode in ("1", "L", "P"):
1343 h = self.im.histogram()
1344 out = [(h[i], i) for i in range(256) if h[i]]
1345 if len(out) > maxcolors:
1346 return None
1347 return out
1348 return self.im.getcolors(maxcolors)
1350 def getdata(self, band=None):
1351 """
1352 Returns the contents of this image as a sequence object
1353 containing pixel values. The sequence object is flattened, so
1354 that values for line one follow directly after the values of
1355 line zero, and so on.
1357 Note that the sequence object returned by this method is an
1358 internal PIL data type, which only supports certain sequence
1359 operations. To convert it to an ordinary sequence (e.g. for
1360 printing), use ``list(im.getdata())``.
1362 :param band: What band to return. The default is to return
1363 all bands. To return a single band, pass in the index
1364 value (e.g. 0 to get the "R" band from an "RGB" image).
1365 :returns: A sequence-like object.
1366 """
1368 self.load()
1369 if band is not None:
1370 return self.im.getband(band)
1371 return self.im # could be abused
1373 def getextrema(self):
1374 """
1375 Gets the minimum and maximum pixel values for each band in
1376 the image.
1378 :returns: For a single-band image, a 2-tuple containing the
1379 minimum and maximum pixel value. For a multi-band image,
1380 a tuple containing one 2-tuple for each band.
1381 """
1383 self.load()
1384 if self.im.bands > 1:
1385 return tuple(self.im.getband(i).getextrema() for i in range(self.im.bands))
1386 return self.im.getextrema()
1388 def _getxmp(self, xmp_tags):
1389 def get_name(tag):
1390 return re.sub("^{[^}]+}", "", tag)
1392 def get_value(element):
1393 value = {get_name(k): v for k, v in element.attrib.items()}
1394 children = list(element)
1395 if children:
1396 for child in children:
1397 name = get_name(child.tag)
1398 child_value = get_value(child)
1399 if name in value:
1400 if not isinstance(value[name], list):
1401 value[name] = [value[name]]
1402 value[name].append(child_value)
1403 else:
1404 value[name] = child_value
1405 elif value:
1406 if element.text:
1407 value["text"] = element.text
1408 else:
1409 return element.text
1410 return value
1412 if ElementTree is None:
1413 warnings.warn("XMP data cannot be read without defusedxml dependency")
1414 return {}
1415 else:
1416 root = ElementTree.fromstring(xmp_tags)
1417 return {get_name(root.tag): get_value(root)}
1419 def getexif(self):
1420 """
1421 Gets EXIF data from the image.
1423 :returns: an :py:class:`~PIL.Image.Exif` object.
1424 """
1425 if self._exif is None:
1426 self._exif = Exif()
1427 self._exif._loaded = False
1428 elif self._exif._loaded:
1429 return self._exif
1430 self._exif._loaded = True
1432 exif_info = self.info.get("exif")
1433 if exif_info is None:
1434 if "Raw profile type exif" in self.info:
1435 exif_info = bytes.fromhex(
1436 "".join(self.info["Raw profile type exif"].split("\n")[3:])
1437 )
1438 elif hasattr(self, "tag_v2"):
1439 self._exif.bigtiff = self.tag_v2._bigtiff
1440 self._exif.endian = self.tag_v2._endian
1441 self._exif.load_from_fp(self.fp, self.tag_v2._offset)
1442 if exif_info is not None:
1443 self._exif.load(exif_info)
1445 # XMP tags
1446 if ExifTags.Base.Orientation not in self._exif:
1447 xmp_tags = self.info.get("XML:com.adobe.xmp")
1448 if xmp_tags:
1449 match = re.search(r'tiff:Orientation(="|>)([0-9])', xmp_tags)
1450 if match:
1451 self._exif[ExifTags.Base.Orientation] = int(match[2])
1453 return self._exif
1455 def _reload_exif(self):
1456 if self._exif is None or not self._exif._loaded:
1457 return
1458 self._exif._loaded = False
1459 self.getexif()
1461 def get_child_images(self):
1462 child_images = []
1463 exif = self.getexif()
1464 ifds = []
1465 if ExifTags.Base.SubIFDs in exif:
1466 subifd_offsets = exif[ExifTags.Base.SubIFDs]
1467 if subifd_offsets:
1468 if not isinstance(subifd_offsets, tuple):
1469 subifd_offsets = (subifd_offsets,)
1470 for subifd_offset in subifd_offsets:
1471 ifds.append((exif._get_ifd_dict(subifd_offset), subifd_offset))
1472 ifd1 = exif.get_ifd(ExifTags.IFD.IFD1)
1473 if ifd1 and ifd1.get(513):
1474 ifds.append((ifd1, exif._info.next))
1476 offset = None
1477 for ifd, ifd_offset in ifds:
1478 current_offset = self.fp.tell()
1479 if offset is None:
1480 offset = current_offset
1482 fp = self.fp
1483 thumbnail_offset = ifd.get(513)
1484 if thumbnail_offset is not None:
1485 try:
1486 thumbnail_offset += self._exif_offset
1487 except AttributeError:
1488 pass
1489 self.fp.seek(thumbnail_offset)
1490 data = self.fp.read(ifd.get(514))
1491 fp = io.BytesIO(data)
1493 with open(fp) as im:
1494 if thumbnail_offset is None:
1495 im._frame_pos = [ifd_offset]
1496 im._seek(0)
1497 im.load()
1498 child_images.append(im)
1500 if offset is not None:
1501 self.fp.seek(offset)
1502 return child_images
1504 def getim(self):
1505 """
1506 Returns a capsule that points to the internal image memory.
1508 :returns: A capsule object.
1509 """
1511 self.load()
1512 return self.im.ptr
1514 def getpalette(self, rawmode="RGB"):
1515 """
1516 Returns the image palette as a list.
1518 :param rawmode: The mode in which to return the palette. ``None`` will
1519 return the palette in its current mode.
1521 .. versionadded:: 9.1.0
1523 :returns: A list of color values [r, g, b, ...], or None if the
1524 image has no palette.
1525 """
1527 self.load()
1528 try:
1529 mode = self.im.getpalettemode()
1530 except ValueError:
1531 return None # no palette
1532 if rawmode is None:
1533 rawmode = mode
1534 return list(self.im.getpalette(mode, rawmode))
1536 @property
1537 def has_transparency_data(self) -> bool:
1538 """
1539 Determine if an image has transparency data, whether in the form of an
1540 alpha channel, a palette with an alpha channel, or a "transparency" key
1541 in the info dictionary.
1543 Note the image might still appear solid, if all of the values shown
1544 within are opaque.
1546 :returns: A boolean.
1547 """
1548 return (
1549 self.mode in ("LA", "La", "PA", "RGBA", "RGBa")
1550 or (self.mode == "P" and self.palette.mode.endswith("A"))
1551 or "transparency" in self.info
1552 )
1554 def apply_transparency(self):
1555 """
1556 If a P mode image has a "transparency" key in the info dictionary,
1557 remove the key and instead apply the transparency to the palette.
1558 Otherwise, the image is unchanged.
1559 """
1560 if self.mode != "P" or "transparency" not in self.info:
1561 return
1563 from . import ImagePalette
1565 palette = self.getpalette("RGBA")
1566 transparency = self.info["transparency"]
1567 if isinstance(transparency, bytes):
1568 for i, alpha in enumerate(transparency):
1569 palette[i * 4 + 3] = alpha
1570 else:
1571 palette[transparency * 4 + 3] = 0
1572 self.palette = ImagePalette.ImagePalette("RGBA", bytes(palette))
1573 self.palette.dirty = 1
1575 del self.info["transparency"]
1577 def getpixel(self, xy):
1578 """
1579 Returns the pixel value at a given position.
1581 :param xy: The coordinate, given as (x, y). See
1582 :ref:`coordinate-system`.
1583 :returns: The pixel value. If the image is a multi-layer image,
1584 this method returns a tuple.
1585 """
1587 self.load()
1588 if self.pyaccess:
1589 return self.pyaccess.getpixel(xy)
1590 return self.im.getpixel(tuple(xy))
1592 def getprojection(self):
1593 """
1594 Get projection to x and y axes
1596 :returns: Two sequences, indicating where there are non-zero
1597 pixels along the X-axis and the Y-axis, respectively.
1598 """
1600 self.load()
1601 x, y = self.im.getprojection()
1602 return list(x), list(y)
1604 def histogram(self, mask=None, extrema=None):
1605 """
1606 Returns a histogram for the image. The histogram is returned as a
1607 list of pixel counts, one for each pixel value in the source
1608 image. Counts are grouped into 256 bins for each band, even if
1609 the image has more than 8 bits per band. If the image has more
1610 than one band, the histograms for all bands are concatenated (for
1611 example, the histogram for an "RGB" image contains 768 values).
1613 A bilevel image (mode "1") is treated as a grayscale ("L") image
1614 by this method.
1616 If a mask is provided, the method returns a histogram for those
1617 parts of the image where the mask image is non-zero. The mask
1618 image must have the same size as the image, and be either a
1619 bi-level image (mode "1") or a grayscale image ("L").
1621 :param mask: An optional mask.
1622 :param extrema: An optional tuple of manually-specified extrema.
1623 :returns: A list containing pixel counts.
1624 """
1625 self.load()
1626 if mask:
1627 mask.load()
1628 return self.im.histogram((0, 0), mask.im)
1629 if self.mode in ("I", "F"):
1630 if extrema is None:
1631 extrema = self.getextrema()
1632 return self.im.histogram(extrema)
1633 return self.im.histogram()
1635 def entropy(self, mask=None, extrema=None):
1636 """
1637 Calculates and returns the entropy for the image.
1639 A bilevel image (mode "1") is treated as a grayscale ("L")
1640 image by this method.
1642 If a mask is provided, the method employs the histogram for
1643 those parts of the image where the mask image is non-zero.
1644 The mask image must have the same size as the image, and be
1645 either a bi-level image (mode "1") or a grayscale image ("L").
1647 :param mask: An optional mask.
1648 :param extrema: An optional tuple of manually-specified extrema.
1649 :returns: A float value representing the image entropy
1650 """
1651 self.load()
1652 if mask:
1653 mask.load()
1654 return self.im.entropy((0, 0), mask.im)
1655 if self.mode in ("I", "F"):
1656 if extrema is None:
1657 extrema = self.getextrema()
1658 return self.im.entropy(extrema)
1659 return self.im.entropy()
1661 def paste(self, im, box=None, mask=None) -> None:
1662 """
1663 Pastes another image into this image. The box argument is either
1664 a 2-tuple giving the upper left corner, a 4-tuple defining the
1665 left, upper, right, and lower pixel coordinate, or None (same as
1666 (0, 0)). See :ref:`coordinate-system`. If a 4-tuple is given, the size
1667 of the pasted image must match the size of the region.
1669 If the modes don't match, the pasted image is converted to the mode of
1670 this image (see the :py:meth:`~PIL.Image.Image.convert` method for
1671 details).
1673 Instead of an image, the source can be a integer or tuple
1674 containing pixel values. The method then fills the region
1675 with the given color. When creating RGB images, you can
1676 also use color strings as supported by the ImageColor module.
1678 If a mask is given, this method updates only the regions
1679 indicated by the mask. You can use either "1", "L", "LA", "RGBA"
1680 or "RGBa" images (if present, the alpha band is used as mask).
1681 Where the mask is 255, the given image is copied as is. Where
1682 the mask is 0, the current value is preserved. Intermediate
1683 values will mix the two images together, including their alpha
1684 channels if they have them.
1686 See :py:meth:`~PIL.Image.Image.alpha_composite` if you want to
1687 combine images with respect to their alpha channels.
1689 :param im: Source image or pixel value (integer or tuple).
1690 :param box: An optional 4-tuple giving the region to paste into.
1691 If a 2-tuple is used instead, it's treated as the upper left
1692 corner. If omitted or None, the source is pasted into the
1693 upper left corner.
1695 If an image is given as the second argument and there is no
1696 third, the box defaults to (0, 0), and the second argument
1697 is interpreted as a mask image.
1698 :param mask: An optional mask image.
1699 """
1701 if isImageType(box) and mask is None:
1702 # abbreviated paste(im, mask) syntax
1703 mask = box
1704 box = None
1706 if box is None:
1707 box = (0, 0)
1709 if len(box) == 2:
1710 # upper left corner given; get size from image or mask
1711 if isImageType(im):
1712 size = im.size
1713 elif isImageType(mask):
1714 size = mask.size
1715 else:
1716 # FIXME: use self.size here?
1717 msg = "cannot determine region size; use 4-item box"
1718 raise ValueError(msg)
1719 box += (box[0] + size[0], box[1] + size[1])
1721 if isinstance(im, str):
1722 from . import ImageColor
1724 im = ImageColor.getcolor(im, self.mode)
1726 elif isImageType(im):
1727 im.load()
1728 if self.mode != im.mode:
1729 if self.mode != "RGB" or im.mode not in ("LA", "RGBA", "RGBa"):
1730 # should use an adapter for this!
1731 im = im.convert(self.mode)
1732 im = im.im
1734 self._ensure_mutable()
1736 if mask:
1737 mask.load()
1738 self.im.paste(im, box, mask.im)
1739 else:
1740 self.im.paste(im, box)
1742 def alpha_composite(self, im, dest=(0, 0), source=(0, 0)):
1743 """'In-place' analog of Image.alpha_composite. Composites an image
1744 onto this image.
1746 :param im: image to composite over this one
1747 :param dest: Optional 2 tuple (left, top) specifying the upper
1748 left corner in this (destination) image.
1749 :param source: Optional 2 (left, top) tuple for the upper left
1750 corner in the overlay source image, or 4 tuple (left, top, right,
1751 bottom) for the bounds of the source rectangle
1753 Performance Note: Not currently implemented in-place in the core layer.
1754 """
1756 if not isinstance(source, (list, tuple)):
1757 msg = "Source must be a tuple"
1758 raise ValueError(msg)
1759 if not isinstance(dest, (list, tuple)):
1760 msg = "Destination must be a tuple"
1761 raise ValueError(msg)
1762 if len(source) not in (2, 4):
1763 msg = "Source must be a 2 or 4-tuple"
1764 raise ValueError(msg)
1765 if not len(dest) == 2:
1766 msg = "Destination must be a 2-tuple"
1767 raise ValueError(msg)
1768 if min(source) < 0:
1769 msg = "Source must be non-negative"
1770 raise ValueError(msg)
1772 if len(source) == 2:
1773 source = source + im.size
1775 # over image, crop if it's not the whole thing.
1776 if source == (0, 0) + im.size:
1777 overlay = im
1778 else:
1779 overlay = im.crop(source)
1781 # target for the paste
1782 box = dest + (dest[0] + overlay.width, dest[1] + overlay.height)
1784 # destination image. don't copy if we're using the whole image.
1785 if box == (0, 0) + self.size:
1786 background = self
1787 else:
1788 background = self.crop(box)
1790 result = alpha_composite(background, overlay)
1791 self.paste(result, box)
1793 def point(self, lut, mode=None):
1794 """
1795 Maps this image through a lookup table or function.
1797 :param lut: A lookup table, containing 256 (or 65536 if
1798 self.mode=="I" and mode == "L") values per band in the
1799 image. A function can be used instead, it should take a
1800 single argument. The function is called once for each
1801 possible pixel value, and the resulting table is applied to
1802 all bands of the image.
1804 It may also be an :py:class:`~PIL.Image.ImagePointHandler`
1805 object::
1807 class Example(Image.ImagePointHandler):
1808 def point(self, data):
1809 # Return result
1810 :param mode: Output mode (default is same as input). In the
1811 current version, this can only be used if the source image
1812 has mode "L" or "P", and the output has mode "1" or the
1813 source image mode is "I" and the output mode is "L".
1814 :returns: An :py:class:`~PIL.Image.Image` object.
1815 """
1817 self.load()
1819 if isinstance(lut, ImagePointHandler):
1820 return lut.point(self)
1822 if callable(lut):
1823 # if it isn't a list, it should be a function
1824 if self.mode in ("I", "I;16", "F"):
1825 # check if the function can be used with point_transform
1826 # UNDONE wiredfool -- I think this prevents us from ever doing
1827 # a gamma function point transform on > 8bit images.
1828 scale, offset = _getscaleoffset(lut)
1829 return self._new(self.im.point_transform(scale, offset))
1830 # for other modes, convert the function to a table
1831 lut = [lut(i) for i in range(256)] * self.im.bands
1833 if self.mode == "F":
1834 # FIXME: _imaging returns a confusing error message for this case
1835 msg = "point operation not supported for this mode"
1836 raise ValueError(msg)
1838 if mode != "F":
1839 lut = [round(i) for i in lut]
1840 return self._new(self.im.point(lut, mode))
1842 def putalpha(self, alpha):
1843 """
1844 Adds or replaces the alpha layer in this image. If the image
1845 does not have an alpha layer, it's converted to "LA" or "RGBA".
1846 The new layer must be either "L" or "1".
1848 :param alpha: The new alpha layer. This can either be an "L" or "1"
1849 image having the same size as this image, or an integer or
1850 other color value.
1851 """
1853 self._ensure_mutable()
1855 if self.mode not in ("LA", "PA", "RGBA"):
1856 # attempt to promote self to a matching alpha mode
1857 try:
1858 mode = getmodebase(self.mode) + "A"
1859 try:
1860 self.im.setmode(mode)
1861 except (AttributeError, ValueError) as e:
1862 # do things the hard way
1863 im = self.im.convert(mode)
1864 if im.mode not in ("LA", "PA", "RGBA"):
1865 msg = "alpha channel could not be added"
1866 raise ValueError(msg) from e # sanity check
1867 self.im = im
1868 self.pyaccess = None
1869 self._mode = self.im.mode
1870 except KeyError as e:
1871 msg = "illegal image mode"
1872 raise ValueError(msg) from e
1874 if self.mode in ("LA", "PA"):
1875 band = 1
1876 else:
1877 band = 3
1879 if isImageType(alpha):
1880 # alpha layer
1881 if alpha.mode not in ("1", "L"):
1882 msg = "illegal image mode"
1883 raise ValueError(msg)
1884 alpha.load()
1885 if alpha.mode == "1":
1886 alpha = alpha.convert("L")
1887 else:
1888 # constant alpha
1889 try:
1890 self.im.fillband(band, alpha)
1891 except (AttributeError, ValueError):
1892 # do things the hard way
1893 alpha = new("L", self.size, alpha)
1894 else:
1895 return
1897 self.im.putband(alpha.im, band)
1899 def putdata(self, data, scale=1.0, offset=0.0):
1900 """
1901 Copies pixel data from a flattened sequence object into the image. The
1902 values should start at the upper left corner (0, 0), continue to the
1903 end of the line, followed directly by the first value of the second
1904 line, and so on. Data will be read until either the image or the
1905 sequence ends. The scale and offset values are used to adjust the
1906 sequence values: **pixel = value*scale + offset**.
1908 :param data: A flattened sequence object.
1909 :param scale: An optional scale value. The default is 1.0.
1910 :param offset: An optional offset value. The default is 0.0.
1911 """
1913 self._ensure_mutable()
1915 self.im.putdata(data, scale, offset)
1917 def putpalette(self, data, rawmode="RGB"):
1918 """
1919 Attaches a palette to this image. The image must be a "P", "PA", "L"
1920 or "LA" image.
1922 The palette sequence must contain at most 256 colors, made up of one
1923 integer value for each channel in the raw mode.
1924 For example, if the raw mode is "RGB", then it can contain at most 768
1925 values, made up of red, green and blue values for the corresponding pixel
1926 index in the 256 colors.
1927 If the raw mode is "RGBA", then it can contain at most 1024 values,
1928 containing red, green, blue and alpha values.
1930 Alternatively, an 8-bit string may be used instead of an integer sequence.
1932 :param data: A palette sequence (either a list or a string).
1933 :param rawmode: The raw mode of the palette. Either "RGB", "RGBA", or a mode
1934 that can be transformed to "RGB" or "RGBA" (e.g. "R", "BGR;15", "RGBA;L").
1935 """
1936 from . import ImagePalette
1938 if self.mode not in ("L", "LA", "P", "PA"):
1939 msg = "illegal image mode"
1940 raise ValueError(msg)
1941 if isinstance(data, ImagePalette.ImagePalette):
1942 palette = ImagePalette.raw(data.rawmode, data.palette)
1943 else:
1944 if not isinstance(data, bytes):
1945 data = bytes(data)
1946 palette = ImagePalette.raw(rawmode, data)
1947 self._mode = "PA" if "A" in self.mode else "P"
1948 self.palette = palette
1949 self.palette.mode = "RGB"
1950 self.load() # install new palette
1952 def putpixel(self, xy, value):
1953 """
1954 Modifies the pixel at the given position. The color is given as
1955 a single numerical value for single-band images, and a tuple for
1956 multi-band images. In addition to this, RGB and RGBA tuples are
1957 accepted for P and PA images.
1959 Note that this method is relatively slow. For more extensive changes,
1960 use :py:meth:`~PIL.Image.Image.paste` or the :py:mod:`~PIL.ImageDraw`
1961 module instead.
1963 See:
1965 * :py:meth:`~PIL.Image.Image.paste`
1966 * :py:meth:`~PIL.Image.Image.putdata`
1967 * :py:mod:`~PIL.ImageDraw`
1969 :param xy: The pixel coordinate, given as (x, y). See
1970 :ref:`coordinate-system`.
1971 :param value: The pixel value.
1972 """
1974 if self.readonly:
1975 self._copy()
1976 self.load()
1978 if self.pyaccess:
1979 return self.pyaccess.putpixel(xy, value)
1981 if (
1982 self.mode in ("P", "PA")
1983 and isinstance(value, (list, tuple))
1984 and len(value) in [3, 4]
1985 ):
1986 # RGB or RGBA value for a P or PA image
1987 if self.mode == "PA":
1988 alpha = value[3] if len(value) == 4 else 255
1989 value = value[:3]
1990 value = self.palette.getcolor(value, self)
1991 if self.mode == "PA":
1992 value = (value, alpha)
1993 return self.im.putpixel(xy, value)
1995 def remap_palette(self, dest_map, source_palette=None):
1996 """
1997 Rewrites the image to reorder the palette.
1999 :param dest_map: A list of indexes into the original palette.
2000 e.g. ``[1,0]`` would swap a two item palette, and ``list(range(256))``
2001 is the identity transform.
2002 :param source_palette: Bytes or None.
2003 :returns: An :py:class:`~PIL.Image.Image` object.
2005 """
2006 from . import ImagePalette
2008 if self.mode not in ("L", "P"):
2009 msg = "illegal image mode"
2010 raise ValueError(msg)
2012 bands = 3
2013 palette_mode = "RGB"
2014 if source_palette is None:
2015 if self.mode == "P":
2016 self.load()
2017 palette_mode = self.im.getpalettemode()
2018 if palette_mode == "RGBA":
2019 bands = 4
2020 source_palette = self.im.getpalette(palette_mode, palette_mode)
2021 else: # L-mode
2022 source_palette = bytearray(i // 3 for i in range(768))
2024 palette_bytes = b""
2025 new_positions = [0] * 256
2027 # pick only the used colors from the palette
2028 for i, oldPosition in enumerate(dest_map):
2029 palette_bytes += source_palette[
2030 oldPosition * bands : oldPosition * bands + bands
2031 ]
2032 new_positions[oldPosition] = i
2034 # replace the palette color id of all pixel with the new id
2036 # Palette images are [0..255], mapped through a 1 or 3
2037 # byte/color map. We need to remap the whole image
2038 # from palette 1 to palette 2. New_positions is
2039 # an array of indexes into palette 1. Palette 2 is
2040 # palette 1 with any holes removed.
2042 # We're going to leverage the convert mechanism to use the
2043 # C code to remap the image from palette 1 to palette 2,
2044 # by forcing the source image into 'L' mode and adding a
2045 # mapping 'L' mode palette, then converting back to 'L'
2046 # sans palette thus converting the image bytes, then
2047 # assigning the optimized RGB palette.
2049 # perf reference, 9500x4000 gif, w/~135 colors
2050 # 14 sec prepatch, 1 sec postpatch with optimization forced.
2052 mapping_palette = bytearray(new_positions)
2054 m_im = self.copy()
2055 m_im._mode = "P"
2057 m_im.palette = ImagePalette.ImagePalette(
2058 palette_mode, palette=mapping_palette * bands
2059 )
2060 # possibly set palette dirty, then
2061 # m_im.putpalette(mapping_palette, 'L') # converts to 'P'
2062 # or just force it.
2063 # UNDONE -- this is part of the general issue with palettes
2064 m_im.im.putpalette(palette_mode + ";L", m_im.palette.tobytes())
2066 m_im = m_im.convert("L")
2068 m_im.putpalette(palette_bytes, palette_mode)
2069 m_im.palette = ImagePalette.ImagePalette(palette_mode, palette=palette_bytes)
2071 if "transparency" in self.info:
2072 try:
2073 m_im.info["transparency"] = dest_map.index(self.info["transparency"])
2074 except ValueError:
2075 if "transparency" in m_im.info:
2076 del m_im.info["transparency"]
2078 return m_im
2080 def _get_safe_box(self, size, resample, box):
2081 """Expands the box so it includes adjacent pixels
2082 that may be used by resampling with the given resampling filter.
2083 """
2084 filter_support = _filters_support[resample] - 0.5
2085 scale_x = (box[2] - box[0]) / size[0]
2086 scale_y = (box[3] - box[1]) / size[1]
2087 support_x = filter_support * scale_x
2088 support_y = filter_support * scale_y
2090 return (
2091 max(0, int(box[0] - support_x)),
2092 max(0, int(box[1] - support_y)),
2093 min(self.size[0], math.ceil(box[2] + support_x)),
2094 min(self.size[1], math.ceil(box[3] + support_y)),
2095 )
2097 def resize(self, size, resample=None, box=None, reducing_gap=None):
2098 """
2099 Returns a resized copy of this image.
2101 :param size: The requested size in pixels, as a 2-tuple:
2102 (width, height).
2103 :param resample: An optional resampling filter. This can be
2104 one of :py:data:`Resampling.NEAREST`, :py:data:`Resampling.BOX`,
2105 :py:data:`Resampling.BILINEAR`, :py:data:`Resampling.HAMMING`,
2106 :py:data:`Resampling.BICUBIC` or :py:data:`Resampling.LANCZOS`.
2107 If the image has mode "1" or "P", it is always set to
2108 :py:data:`Resampling.NEAREST`. If the image mode specifies a number
2109 of bits, such as "I;16", then the default filter is
2110 :py:data:`Resampling.NEAREST`. Otherwise, the default filter is
2111 :py:data:`Resampling.BICUBIC`. See: :ref:`concept-filters`.
2112 :param box: An optional 4-tuple of floats providing
2113 the source image region to be scaled.
2114 The values must be within (0, 0, width, height) rectangle.
2115 If omitted or None, the entire source is used.
2116 :param reducing_gap: Apply optimization by resizing the image
2117 in two steps. First, reducing the image by integer times
2118 using :py:meth:`~PIL.Image.Image.reduce`.
2119 Second, resizing using regular resampling. The last step
2120 changes size no less than by ``reducing_gap`` times.
2121 ``reducing_gap`` may be None (no first step is performed)
2122 or should be greater than 1.0. The bigger ``reducing_gap``,
2123 the closer the result to the fair resampling.
2124 The smaller ``reducing_gap``, the faster resizing.
2125 With ``reducing_gap`` greater or equal to 3.0, the result is
2126 indistinguishable from fair resampling in most cases.
2127 The default value is None (no optimization).
2128 :returns: An :py:class:`~PIL.Image.Image` object.
2129 """
2131 if resample is None:
2132 type_special = ";" in self.mode
2133 resample = Resampling.NEAREST if type_special else Resampling.BICUBIC
2134 elif resample not in (
2135 Resampling.NEAREST,
2136 Resampling.BILINEAR,
2137 Resampling.BICUBIC,
2138 Resampling.LANCZOS,
2139 Resampling.BOX,
2140 Resampling.HAMMING,
2141 ):
2142 msg = f"Unknown resampling filter ({resample})."
2144 filters = [
2145 f"{filter[1]} ({filter[0]})"
2146 for filter in (
2147 (Resampling.NEAREST, "Image.Resampling.NEAREST"),
2148 (Resampling.LANCZOS, "Image.Resampling.LANCZOS"),
2149 (Resampling.BILINEAR, "Image.Resampling.BILINEAR"),
2150 (Resampling.BICUBIC, "Image.Resampling.BICUBIC"),
2151 (Resampling.BOX, "Image.Resampling.BOX"),
2152 (Resampling.HAMMING, "Image.Resampling.HAMMING"),
2153 )
2154 ]
2155 msg += " Use " + ", ".join(filters[:-1]) + " or " + filters[-1]
2156 raise ValueError(msg)
2158 if reducing_gap is not None and reducing_gap < 1.0:
2159 msg = "reducing_gap must be 1.0 or greater"
2160 raise ValueError(msg)
2162 size = tuple(size)
2164 self.load()
2165 if box is None:
2166 box = (0, 0) + self.size
2167 else:
2168 box = tuple(box)
2170 if self.size == size and box == (0, 0) + self.size:
2171 return self.copy()
2173 if self.mode in ("1", "P"):
2174 resample = Resampling.NEAREST
2176 if self.mode in ["LA", "RGBA"] and resample != Resampling.NEAREST:
2177 im = self.convert({"LA": "La", "RGBA": "RGBa"}[self.mode])
2178 im = im.resize(size, resample, box)
2179 return im.convert(self.mode)
2181 self.load()
2183 if reducing_gap is not None and resample != Resampling.NEAREST:
2184 factor_x = int((box[2] - box[0]) / size[0] / reducing_gap) or 1
2185 factor_y = int((box[3] - box[1]) / size[1] / reducing_gap) or 1
2186 if factor_x > 1 or factor_y > 1:
2187 reduce_box = self._get_safe_box(size, resample, box)
2188 factor = (factor_x, factor_y)
2189 if callable(self.reduce):
2190 self = self.reduce(factor, box=reduce_box)
2191 else:
2192 self = Image.reduce(self, factor, box=reduce_box)
2193 box = (
2194 (box[0] - reduce_box[0]) / factor_x,
2195 (box[1] - reduce_box[1]) / factor_y,
2196 (box[2] - reduce_box[0]) / factor_x,
2197 (box[3] - reduce_box[1]) / factor_y,
2198 )
2200 return self._new(self.im.resize(size, resample, box))
2202 def reduce(self, factor, box=None):
2203 """
2204 Returns a copy of the image reduced ``factor`` times.
2205 If the size of the image is not dividable by ``factor``,
2206 the resulting size will be rounded up.
2208 :param factor: A greater than 0 integer or tuple of two integers
2209 for width and height separately.
2210 :param box: An optional 4-tuple of ints providing
2211 the source image region to be reduced.
2212 The values must be within ``(0, 0, width, height)`` rectangle.
2213 If omitted or ``None``, the entire source is used.
2214 """
2215 if not isinstance(factor, (list, tuple)):
2216 factor = (factor, factor)
2218 if box is None:
2219 box = (0, 0) + self.size
2220 else:
2221 box = tuple(box)
2223 if factor == (1, 1) and box == (0, 0) + self.size:
2224 return self.copy()
2226 if self.mode in ["LA", "RGBA"]:
2227 im = self.convert({"LA": "La", "RGBA": "RGBa"}[self.mode])
2228 im = im.reduce(factor, box)
2229 return im.convert(self.mode)
2231 self.load()
2233 return self._new(self.im.reduce(factor, box))
2235 def rotate(
2236 self,
2237 angle,
2238 resample=Resampling.NEAREST,
2239 expand=0,
2240 center=None,
2241 translate=None,
2242 fillcolor=None,
2243 ):
2244 """
2245 Returns a rotated copy of this image. This method returns a
2246 copy of this image, rotated the given number of degrees counter
2247 clockwise around its centre.
2249 :param angle: In degrees counter clockwise.
2250 :param resample: An optional resampling filter. This can be
2251 one of :py:data:`Resampling.NEAREST` (use nearest neighbour),
2252 :py:data:`Resampling.BILINEAR` (linear interpolation in a 2x2
2253 environment), or :py:data:`Resampling.BICUBIC` (cubic spline
2254 interpolation in a 4x4 environment). If omitted, or if the image has
2255 mode "1" or "P", it is set to :py:data:`Resampling.NEAREST`.
2256 See :ref:`concept-filters`.
2257 :param expand: Optional expansion flag. If true, expands the output
2258 image to make it large enough to hold the entire rotated image.
2259 If false or omitted, make the output image the same size as the
2260 input image. Note that the expand flag assumes rotation around
2261 the center and no translation.
2262 :param center: Optional center of rotation (a 2-tuple). Origin is
2263 the upper left corner. Default is the center of the image.
2264 :param translate: An optional post-rotate translation (a 2-tuple).
2265 :param fillcolor: An optional color for area outside the rotated image.
2266 :returns: An :py:class:`~PIL.Image.Image` object.
2267 """
2269 angle = angle % 360.0
2271 # Fast paths regardless of filter, as long as we're not
2272 # translating or changing the center.
2273 if not (center or translate):
2274 if angle == 0:
2275 return self.copy()
2276 if angle == 180:
2277 return self.transpose(Transpose.ROTATE_180)
2278 if angle in (90, 270) and (expand or self.width == self.height):
2279 return self.transpose(
2280 Transpose.ROTATE_90 if angle == 90 else Transpose.ROTATE_270
2281 )
2283 # Calculate the affine matrix. Note that this is the reverse
2284 # transformation (from destination image to source) because we
2285 # want to interpolate the (discrete) destination pixel from
2286 # the local area around the (floating) source pixel.
2288 # The matrix we actually want (note that it operates from the right):
2289 # (1, 0, tx) (1, 0, cx) ( cos a, sin a, 0) (1, 0, -cx)
2290 # (0, 1, ty) * (0, 1, cy) * (-sin a, cos a, 0) * (0, 1, -cy)
2291 # (0, 0, 1) (0, 0, 1) ( 0, 0, 1) (0, 0, 1)
2293 # The reverse matrix is thus:
2294 # (1, 0, cx) ( cos -a, sin -a, 0) (1, 0, -cx) (1, 0, -tx)
2295 # (0, 1, cy) * (-sin -a, cos -a, 0) * (0, 1, -cy) * (0, 1, -ty)
2296 # (0, 0, 1) ( 0, 0, 1) (0, 0, 1) (0, 0, 1)
2298 # In any case, the final translation may be updated at the end to
2299 # compensate for the expand flag.
2301 w, h = self.size
2303 if translate is None:
2304 post_trans = (0, 0)
2305 else:
2306 post_trans = translate
2307 if center is None:
2308 # FIXME These should be rounded to ints?
2309 rotn_center = (w / 2.0, h / 2.0)
2310 else:
2311 rotn_center = center
2313 angle = -math.radians(angle)
2314 matrix = [
2315 round(math.cos(angle), 15),
2316 round(math.sin(angle), 15),
2317 0.0,
2318 round(-math.sin(angle), 15),
2319 round(math.cos(angle), 15),
2320 0.0,
2321 ]
2323 def transform(x, y, matrix):
2324 (a, b, c, d, e, f) = matrix
2325 return a * x + b * y + c, d * x + e * y + f
2327 matrix[2], matrix[5] = transform(
2328 -rotn_center[0] - post_trans[0], -rotn_center[1] - post_trans[1], matrix
2329 )
2330 matrix[2] += rotn_center[0]
2331 matrix[5] += rotn_center[1]
2333 if expand:
2334 # calculate output size
2335 xx = []
2336 yy = []
2337 for x, y in ((0, 0), (w, 0), (w, h), (0, h)):
2338 x, y = transform(x, y, matrix)
2339 xx.append(x)
2340 yy.append(y)
2341 nw = math.ceil(max(xx)) - math.floor(min(xx))
2342 nh = math.ceil(max(yy)) - math.floor(min(yy))
2344 # We multiply a translation matrix from the right. Because of its
2345 # special form, this is the same as taking the image of the
2346 # translation vector as new translation vector.
2347 matrix[2], matrix[5] = transform(-(nw - w) / 2.0, -(nh - h) / 2.0, matrix)
2348 w, h = nw, nh
2350 return self.transform(
2351 (w, h), Transform.AFFINE, matrix, resample, fillcolor=fillcolor
2352 )
2354 def save(self, fp, format=None, **params) -> None:
2355 """
2356 Saves this image under the given filename. If no format is
2357 specified, the format to use is determined from the filename
2358 extension, if possible.
2360 Keyword options can be used to provide additional instructions
2361 to the writer. If a writer doesn't recognise an option, it is
2362 silently ignored. The available options are described in the
2363 :doc:`image format documentation
2364 <../handbook/image-file-formats>` for each writer.
2366 You can use a file object instead of a filename. In this case,
2367 you must always specify the format. The file object must
2368 implement the ``seek``, ``tell``, and ``write``
2369 methods, and be opened in binary mode.
2371 :param fp: A filename (string), pathlib.Path object or file object.
2372 :param format: Optional format override. If omitted, the
2373 format to use is determined from the filename extension.
2374 If a file object was used instead of a filename, this
2375 parameter should always be used.
2376 :param params: Extra parameters to the image writer.
2377 :returns: None
2378 :exception ValueError: If the output format could not be determined
2379 from the file name. Use the format option to solve this.
2380 :exception OSError: If the file could not be written. The file
2381 may have been created, and may contain partial data.
2382 """
2384 filename = ""
2385 open_fp = False
2386 if isinstance(fp, Path):
2387 filename = str(fp)
2388 open_fp = True
2389 elif is_path(fp):
2390 filename = fp
2391 open_fp = True
2392 elif fp == sys.stdout:
2393 try:
2394 fp = sys.stdout.buffer
2395 except AttributeError:
2396 pass
2397 if not filename and hasattr(fp, "name") and is_path(fp.name):
2398 # only set the name for metadata purposes
2399 filename = fp.name
2401 # may mutate self!
2402 self._ensure_mutable()
2404 save_all = params.pop("save_all", False)
2405 self.encoderinfo = params
2406 self.encoderconfig = ()
2408 preinit()
2410 ext = os.path.splitext(filename)[1].lower()
2412 if not format:
2413 if ext not in EXTENSION:
2414 init()
2415 try:
2416 format = EXTENSION[ext]
2417 except KeyError as e:
2418 msg = f"unknown file extension: {ext}"
2419 raise ValueError(msg) from e
2421 if format.upper() not in SAVE:
2422 init()
2423 if save_all:
2424 save_handler = SAVE_ALL[format.upper()]
2425 else:
2426 save_handler = SAVE[format.upper()]
2428 created = False
2429 if open_fp:
2430 created = not os.path.exists(filename)
2431 if params.get("append", False):
2432 # Open also for reading ("+"), because TIFF save_all
2433 # writer needs to go back and edit the written data.
2434 fp = builtins.open(filename, "r+b")
2435 else:
2436 fp = builtins.open(filename, "w+b")
2438 try:
2439 save_handler(self, fp, filename)
2440 except Exception:
2441 if open_fp:
2442 fp.close()
2443 if created:
2444 try:
2445 os.remove(filename)
2446 except PermissionError:
2447 pass
2448 raise
2449 if open_fp:
2450 fp.close()
2452 def seek(self, frame) -> Image:
2453 """
2454 Seeks to the given frame in this sequence file. If you seek
2455 beyond the end of the sequence, the method raises an
2456 ``EOFError`` exception. When a sequence file is opened, the
2457 library automatically seeks to frame 0.
2459 See :py:meth:`~PIL.Image.Image.tell`.
2461 If defined, :attr:`~PIL.Image.Image.n_frames` refers to the
2462 number of available frames.
2464 :param frame: Frame number, starting at 0.
2465 :exception EOFError: If the call attempts to seek beyond the end
2466 of the sequence.
2467 """
2469 # overridden by file handlers
2470 if frame != 0:
2471 msg = "no more images in file"
2472 raise EOFError(msg)
2474 def show(self, title=None):
2475 """
2476 Displays this image. This method is mainly intended for debugging purposes.
2478 This method calls :py:func:`PIL.ImageShow.show` internally. You can use
2479 :py:func:`PIL.ImageShow.register` to override its default behaviour.
2481 The image is first saved to a temporary file. By default, it will be in
2482 PNG format.
2484 On Unix, the image is then opened using the **xdg-open**, **display**,
2485 **gm**, **eog** or **xv** utility, depending on which one can be found.
2487 On macOS, the image is opened with the native Preview application.
2489 On Windows, the image is opened with the standard PNG display utility.
2491 :param title: Optional title to use for the image window, where possible.
2492 """
2494 _show(self, title=title)
2496 def split(self):
2497 """
2498 Split this image into individual bands. This method returns a
2499 tuple of individual image bands from an image. For example,
2500 splitting an "RGB" image creates three new images each
2501 containing a copy of one of the original bands (red, green,
2502 blue).
2504 If you need only one band, :py:meth:`~PIL.Image.Image.getchannel`
2505 method can be more convenient and faster.
2507 :returns: A tuple containing bands.
2508 """
2510 self.load()
2511 if self.im.bands == 1:
2512 ims = [self.copy()]
2513 else:
2514 ims = map(self._new, self.im.split())
2515 return tuple(ims)
2517 def getchannel(self, channel):
2518 """
2519 Returns an image containing a single channel of the source image.
2521 :param channel: What channel to return. Could be index
2522 (0 for "R" channel of "RGB") or channel name
2523 ("A" for alpha channel of "RGBA").
2524 :returns: An image in "L" mode.
2526 .. versionadded:: 4.3.0
2527 """
2528 self.load()
2530 if isinstance(channel, str):
2531 try:
2532 channel = self.getbands().index(channel)
2533 except ValueError as e:
2534 msg = f'The image has no channel "{channel}"'
2535 raise ValueError(msg) from e
2537 return self._new(self.im.getband(channel))
2539 def tell(self) -> int:
2540 """
2541 Returns the current frame number. See :py:meth:`~PIL.Image.Image.seek`.
2543 If defined, :attr:`~PIL.Image.Image.n_frames` refers to the
2544 number of available frames.
2546 :returns: Frame number, starting with 0.
2547 """
2548 return 0
2550 def thumbnail(self, size, resample=Resampling.BICUBIC, reducing_gap=2.0):
2551 """
2552 Make this image into a thumbnail. This method modifies the
2553 image to contain a thumbnail version of itself, no larger than
2554 the given size. This method calculates an appropriate thumbnail
2555 size to preserve the aspect of the image, calls the
2556 :py:meth:`~PIL.Image.Image.draft` method to configure the file reader
2557 (where applicable), and finally resizes the image.
2559 Note that this function modifies the :py:class:`~PIL.Image.Image`
2560 object in place. If you need to use the full resolution image as well,
2561 apply this method to a :py:meth:`~PIL.Image.Image.copy` of the original
2562 image.
2564 :param size: The requested size in pixels, as a 2-tuple:
2565 (width, height).
2566 :param resample: Optional resampling filter. This can be one
2567 of :py:data:`Resampling.NEAREST`, :py:data:`Resampling.BOX`,
2568 :py:data:`Resampling.BILINEAR`, :py:data:`Resampling.HAMMING`,
2569 :py:data:`Resampling.BICUBIC` or :py:data:`Resampling.LANCZOS`.
2570 If omitted, it defaults to :py:data:`Resampling.BICUBIC`.
2571 (was :py:data:`Resampling.NEAREST` prior to version 2.5.0).
2572 See: :ref:`concept-filters`.
2573 :param reducing_gap: Apply optimization by resizing the image
2574 in two steps. First, reducing the image by integer times
2575 using :py:meth:`~PIL.Image.Image.reduce` or
2576 :py:meth:`~PIL.Image.Image.draft` for JPEG images.
2577 Second, resizing using regular resampling. The last step
2578 changes size no less than by ``reducing_gap`` times.
2579 ``reducing_gap`` may be None (no first step is performed)
2580 or should be greater than 1.0. The bigger ``reducing_gap``,
2581 the closer the result to the fair resampling.
2582 The smaller ``reducing_gap``, the faster resizing.
2583 With ``reducing_gap`` greater or equal to 3.0, the result is
2584 indistinguishable from fair resampling in most cases.
2585 The default value is 2.0 (very close to fair resampling
2586 while still being faster in many cases).
2587 :returns: None
2588 """
2590 provided_size = tuple(map(math.floor, size))
2592 def preserve_aspect_ratio():
2593 def round_aspect(number, key):
2594 return max(min(math.floor(number), math.ceil(number), key=key), 1)
2596 x, y = provided_size
2597 if x >= self.width and y >= self.height:
2598 return
2600 aspect = self.width / self.height
2601 if x / y >= aspect:
2602 x = round_aspect(y * aspect, key=lambda n: abs(aspect - n / y))
2603 else:
2604 y = round_aspect(
2605 x / aspect, key=lambda n: 0 if n == 0 else abs(aspect - x / n)
2606 )
2607 return x, y
2609 box = None
2610 if reducing_gap is not None:
2611 size = preserve_aspect_ratio()
2612 if size is None:
2613 return
2615 res = self.draft(None, (size[0] * reducing_gap, size[1] * reducing_gap))
2616 if res is not None:
2617 box = res[1]
2618 if box is None:
2619 self.load()
2621 # load() may have changed the size of the image
2622 size = preserve_aspect_ratio()
2623 if size is None:
2624 return
2626 if self.size != size:
2627 im = self.resize(size, resample, box=box, reducing_gap=reducing_gap)
2629 self.im = im.im
2630 self._size = size
2631 self._mode = self.im.mode
2633 self.readonly = 0
2634 self.pyaccess = None
2636 # FIXME: the different transform methods need further explanation
2637 # instead of bloating the method docs, add a separate chapter.
2638 def transform(
2639 self,
2640 size,
2641 method,
2642 data=None,
2643 resample=Resampling.NEAREST,
2644 fill=1,
2645 fillcolor=None,
2646 ) -> Image:
2647 """
2648 Transforms this image. This method creates a new image with the
2649 given size, and the same mode as the original, and copies data
2650 to the new image using the given transform.
2652 :param size: The output size in pixels, as a 2-tuple:
2653 (width, height).
2654 :param method: The transformation method. This is one of
2655 :py:data:`Transform.EXTENT` (cut out a rectangular subregion),
2656 :py:data:`Transform.AFFINE` (affine transform),
2657 :py:data:`Transform.PERSPECTIVE` (perspective transform),
2658 :py:data:`Transform.QUAD` (map a quadrilateral to a rectangle), or
2659 :py:data:`Transform.MESH` (map a number of source quadrilaterals
2660 in one operation).
2662 It may also be an :py:class:`~PIL.Image.ImageTransformHandler`
2663 object::
2665 class Example(Image.ImageTransformHandler):
2666 def transform(self, size, data, resample, fill=1):
2667 # Return result
2669 It may also be an object with a ``method.getdata`` method
2670 that returns a tuple supplying new ``method`` and ``data`` values::
2672 class Example:
2673 def getdata(self):
2674 method = Image.Transform.EXTENT
2675 data = (0, 0, 100, 100)
2676 return method, data
2677 :param data: Extra data to the transformation method.
2678 :param resample: Optional resampling filter. It can be one of
2679 :py:data:`Resampling.NEAREST` (use nearest neighbour),
2680 :py:data:`Resampling.BILINEAR` (linear interpolation in a 2x2
2681 environment), or :py:data:`Resampling.BICUBIC` (cubic spline
2682 interpolation in a 4x4 environment). If omitted, or if the image
2683 has mode "1" or "P", it is set to :py:data:`Resampling.NEAREST`.
2684 See: :ref:`concept-filters`.
2685 :param fill: If ``method`` is an
2686 :py:class:`~PIL.Image.ImageTransformHandler` object, this is one of
2687 the arguments passed to it. Otherwise, it is unused.
2688 :param fillcolor: Optional fill color for the area outside the
2689 transform in the output image.
2690 :returns: An :py:class:`~PIL.Image.Image` object.
2691 """
2693 if self.mode in ("LA", "RGBA") and resample != Resampling.NEAREST:
2694 return (
2695 self.convert({"LA": "La", "RGBA": "RGBa"}[self.mode])
2696 .transform(size, method, data, resample, fill, fillcolor)
2697 .convert(self.mode)
2698 )
2700 if isinstance(method, ImageTransformHandler):
2701 return method.transform(size, self, resample=resample, fill=fill)
2703 if hasattr(method, "getdata"):
2704 # compatibility w. old-style transform objects
2705 method, data = method.getdata()
2707 if data is None:
2708 msg = "missing method data"
2709 raise ValueError(msg)
2711 im = new(self.mode, size, fillcolor)
2712 if self.mode == "P" and self.palette:
2713 im.palette = self.palette.copy()
2714 im.info = self.info.copy()
2715 if method == Transform.MESH:
2716 # list of quads
2717 for box, quad in data:
2718 im.__transformer(
2719 box, self, Transform.QUAD, quad, resample, fillcolor is None
2720 )
2721 else:
2722 im.__transformer(
2723 (0, 0) + size, self, method, data, resample, fillcolor is None
2724 )
2726 return im
2728 def __transformer(
2729 self, box, image, method, data, resample=Resampling.NEAREST, fill=1
2730 ):
2731 w = box[2] - box[0]
2732 h = box[3] - box[1]
2734 if method == Transform.AFFINE:
2735 data = data[:6]
2737 elif method == Transform.EXTENT:
2738 # convert extent to an affine transform
2739 x0, y0, x1, y1 = data
2740 xs = (x1 - x0) / w
2741 ys = (y1 - y0) / h
2742 method = Transform.AFFINE
2743 data = (xs, 0, x0, 0, ys, y0)
2745 elif method == Transform.PERSPECTIVE:
2746 data = data[:8]
2748 elif method == Transform.QUAD:
2749 # quadrilateral warp. data specifies the four corners
2750 # given as NW, SW, SE, and NE.
2751 nw = data[:2]
2752 sw = data[2:4]
2753 se = data[4:6]
2754 ne = data[6:8]
2755 x0, y0 = nw
2756 As = 1.0 / w
2757 At = 1.0 / h
2758 data = (
2759 x0,
2760 (ne[0] - x0) * As,
2761 (sw[0] - x0) * At,
2762 (se[0] - sw[0] - ne[0] + x0) * As * At,
2763 y0,
2764 (ne[1] - y0) * As,
2765 (sw[1] - y0) * At,
2766 (se[1] - sw[1] - ne[1] + y0) * As * At,
2767 )
2769 else:
2770 msg = "unknown transformation method"
2771 raise ValueError(msg)
2773 if resample not in (
2774 Resampling.NEAREST,
2775 Resampling.BILINEAR,
2776 Resampling.BICUBIC,
2777 ):
2778 if resample in (Resampling.BOX, Resampling.HAMMING, Resampling.LANCZOS):
2779 msg = {
2780 Resampling.BOX: "Image.Resampling.BOX",
2781 Resampling.HAMMING: "Image.Resampling.HAMMING",
2782 Resampling.LANCZOS: "Image.Resampling.LANCZOS",
2783 }[resample] + f" ({resample}) cannot be used."
2784 else:
2785 msg = f"Unknown resampling filter ({resample})."
2787 filters = [
2788 f"{filter[1]} ({filter[0]})"
2789 for filter in (
2790 (Resampling.NEAREST, "Image.Resampling.NEAREST"),
2791 (Resampling.BILINEAR, "Image.Resampling.BILINEAR"),
2792 (Resampling.BICUBIC, "Image.Resampling.BICUBIC"),
2793 )
2794 ]
2795 msg += " Use " + ", ".join(filters[:-1]) + " or " + filters[-1]
2796 raise ValueError(msg)
2798 image.load()
2800 self.load()
2802 if image.mode in ("1", "P"):
2803 resample = Resampling.NEAREST
2805 self.im.transform2(box, image.im, method, data, resample, fill)
2807 def transpose(self, method):
2808 """
2809 Transpose image (flip or rotate in 90 degree steps)
2811 :param method: One of :py:data:`Transpose.FLIP_LEFT_RIGHT`,
2812 :py:data:`Transpose.FLIP_TOP_BOTTOM`, :py:data:`Transpose.ROTATE_90`,
2813 :py:data:`Transpose.ROTATE_180`, :py:data:`Transpose.ROTATE_270`,
2814 :py:data:`Transpose.TRANSPOSE` or :py:data:`Transpose.TRANSVERSE`.
2815 :returns: Returns a flipped or rotated copy of this image.
2816 """
2818 self.load()
2819 return self._new(self.im.transpose(method))
2821 def effect_spread(self, distance):
2822 """
2823 Randomly spread pixels in an image.
2825 :param distance: Distance to spread pixels.
2826 """
2827 self.load()
2828 return self._new(self.im.effect_spread(distance))
2830 def toqimage(self):
2831 """Returns a QImage copy of this image"""
2832 from . import ImageQt
2834 if not ImageQt.qt_is_installed:
2835 msg = "Qt bindings are not installed"
2836 raise ImportError(msg)
2837 return ImageQt.toqimage(self)
2839 def toqpixmap(self):
2840 """Returns a QPixmap copy of this image"""
2841 from . import ImageQt
2843 if not ImageQt.qt_is_installed:
2844 msg = "Qt bindings are not installed"
2845 raise ImportError(msg)
2846 return ImageQt.toqpixmap(self)
2849# --------------------------------------------------------------------
2850# Abstract handlers.
2853class ImagePointHandler:
2854 """
2855 Used as a mixin by point transforms
2856 (for use with :py:meth:`~PIL.Image.Image.point`)
2857 """
2859 pass
2862class ImageTransformHandler:
2863 """
2864 Used as a mixin by geometry transforms
2865 (for use with :py:meth:`~PIL.Image.Image.transform`)
2866 """
2868 pass
2871# --------------------------------------------------------------------
2872# Factories
2874#
2875# Debugging
2878def _wedge():
2879 """Create grayscale wedge (for debugging only)"""
2881 return Image()._new(core.wedge("L"))
2884def _check_size(size):
2885 """
2886 Common check to enforce type and sanity check on size tuples
2888 :param size: Should be a 2 tuple of (width, height)
2889 :returns: True, or raises a ValueError
2890 """
2892 if not isinstance(size, (list, tuple)):
2893 msg = "Size must be a tuple"
2894 raise ValueError(msg)
2895 if len(size) != 2:
2896 msg = "Size must be a tuple of length 2"
2897 raise ValueError(msg)
2898 if size[0] < 0 or size[1] < 0:
2899 msg = "Width and height must be >= 0"
2900 raise ValueError(msg)
2902 return True
2905def new(mode, size, color=0) -> Image:
2906 """
2907 Creates a new image with the given mode and size.
2909 :param mode: The mode to use for the new image. See:
2910 :ref:`concept-modes`.
2911 :param size: A 2-tuple, containing (width, height) in pixels.
2912 :param color: What color to use for the image. Default is black.
2913 If given, this should be a single integer or floating point value
2914 for single-band modes, and a tuple for multi-band modes (one value
2915 per band). When creating RGB or HSV images, you can also use color
2916 strings as supported by the ImageColor module. If the color is
2917 None, the image is not initialised.
2918 :returns: An :py:class:`~PIL.Image.Image` object.
2919 """
2921 _check_size(size)
2923 if color is None:
2924 # don't initialize
2925 return Image()._new(core.new(mode, size))
2927 if isinstance(color, str):
2928 # css3-style specifier
2930 from . import ImageColor
2932 color = ImageColor.getcolor(color, mode)
2934 im = Image()
2935 if mode == "P" and isinstance(color, (list, tuple)) and len(color) in [3, 4]:
2936 # RGB or RGBA value for a P image
2937 from . import ImagePalette
2939 im.palette = ImagePalette.ImagePalette()
2940 color = im.palette.getcolor(color)
2941 return im._new(core.fill(mode, size, color))
2944def frombytes(mode, size, data, decoder_name="raw", *args) -> Image:
2945 """
2946 Creates a copy of an image memory from pixel data in a buffer.
2948 In its simplest form, this function takes three arguments
2949 (mode, size, and unpacked pixel data).
2951 You can also use any pixel decoder supported by PIL. For more
2952 information on available decoders, see the section
2953 :ref:`Writing Your Own File Codec <file-codecs>`.
2955 Note that this function decodes pixel data only, not entire images.
2956 If you have an entire image in a string, wrap it in a
2957 :py:class:`~io.BytesIO` object, and use :py:func:`~PIL.Image.open` to load
2958 it.
2960 :param mode: The image mode. See: :ref:`concept-modes`.
2961 :param size: The image size.
2962 :param data: A byte buffer containing raw data for the given mode.
2963 :param decoder_name: What decoder to use.
2964 :param args: Additional parameters for the given decoder.
2965 :returns: An :py:class:`~PIL.Image.Image` object.
2966 """
2968 _check_size(size)
2970 im = new(mode, size)
2971 if im.width != 0 and im.height != 0:
2972 # may pass tuple instead of argument list
2973 if len(args) == 1 and isinstance(args[0], tuple):
2974 args = args[0]
2976 if decoder_name == "raw" and args == ():
2977 args = mode
2979 im.frombytes(data, decoder_name, args)
2980 return im
2983def frombuffer(mode, size, data, decoder_name="raw", *args):
2984 """
2985 Creates an image memory referencing pixel data in a byte buffer.
2987 This function is similar to :py:func:`~PIL.Image.frombytes`, but uses data
2988 in the byte buffer, where possible. This means that changes to the
2989 original buffer object are reflected in this image). Not all modes can
2990 share memory; supported modes include "L", "RGBX", "RGBA", and "CMYK".
2992 Note that this function decodes pixel data only, not entire images.
2993 If you have an entire image file in a string, wrap it in a
2994 :py:class:`~io.BytesIO` object, and use :py:func:`~PIL.Image.open` to load it.
2996 In the current version, the default parameters used for the "raw" decoder
2997 differs from that used for :py:func:`~PIL.Image.frombytes`. This is a
2998 bug, and will probably be fixed in a future release. The current release
2999 issues a warning if you do this; to disable the warning, you should provide
3000 the full set of parameters. See below for details.
3002 :param mode: The image mode. See: :ref:`concept-modes`.
3003 :param size: The image size.
3004 :param data: A bytes or other buffer object containing raw
3005 data for the given mode.
3006 :param decoder_name: What decoder to use.
3007 :param args: Additional parameters for the given decoder. For the
3008 default encoder ("raw"), it's recommended that you provide the
3009 full set of parameters::
3011 frombuffer(mode, size, data, "raw", mode, 0, 1)
3013 :returns: An :py:class:`~PIL.Image.Image` object.
3015 .. versionadded:: 1.1.4
3016 """
3018 _check_size(size)
3020 # may pass tuple instead of argument list
3021 if len(args) == 1 and isinstance(args[0], tuple):
3022 args = args[0]
3024 if decoder_name == "raw":
3025 if args == ():
3026 args = mode, 0, 1
3027 if args[0] in _MAPMODES:
3028 im = new(mode, (0, 0))
3029 im = im._new(core.map_buffer(data, size, decoder_name, 0, args))
3030 if mode == "P":
3031 from . import ImagePalette
3033 im.palette = ImagePalette.ImagePalette("RGB", im.im.getpalette("RGB"))
3034 im.readonly = 1
3035 return im
3037 return frombytes(mode, size, data, decoder_name, args)
3040def fromarray(obj, mode=None):
3041 """
3042 Creates an image memory from an object exporting the array interface
3043 (using the buffer protocol)::
3045 from PIL import Image
3046 import numpy as np
3047 a = np.zeros((5, 5))
3048 im = Image.fromarray(a)
3050 If ``obj`` is not contiguous, then the ``tobytes`` method is called
3051 and :py:func:`~PIL.Image.frombuffer` is used.
3053 In the case of NumPy, be aware that Pillow modes do not always correspond
3054 to NumPy dtypes. Pillow modes only offer 1-bit pixels, 8-bit pixels,
3055 32-bit signed integer pixels, and 32-bit floating point pixels.
3057 Pillow images can also be converted to arrays::
3059 from PIL import Image
3060 import numpy as np
3061 im = Image.open("hopper.jpg")
3062 a = np.asarray(im)
3064 When converting Pillow images to arrays however, only pixel values are
3065 transferred. This means that P and PA mode images will lose their palette.
3067 :param obj: Object with array interface
3068 :param mode: Optional mode to use when reading ``obj``. Will be determined from
3069 type if ``None``.
3071 This will not be used to convert the data after reading, but will be used to
3072 change how the data is read::
3074 from PIL import Image
3075 import numpy as np
3076 a = np.full((1, 1), 300)
3077 im = Image.fromarray(a, mode="L")
3078 im.getpixel((0, 0)) # 44
3079 im = Image.fromarray(a, mode="RGB")
3080 im.getpixel((0, 0)) # (44, 1, 0)
3082 See: :ref:`concept-modes` for general information about modes.
3083 :returns: An image object.
3085 .. versionadded:: 1.1.6
3086 """
3087 arr = obj.__array_interface__
3088 shape = arr["shape"]
3089 ndim = len(shape)
3090 strides = arr.get("strides", None)
3091 if mode is None:
3092 try:
3093 typekey = (1, 1) + shape[2:], arr["typestr"]
3094 except KeyError as e:
3095 msg = "Cannot handle this data type"
3096 raise TypeError(msg) from e
3097 try:
3098 mode, rawmode = _fromarray_typemap[typekey]
3099 except KeyError as e:
3100 typekey_shape, typestr = typekey
3101 msg = f"Cannot handle this data type: {typekey_shape}, {typestr}"
3102 raise TypeError(msg) from e
3103 else:
3104 rawmode = mode
3105 if mode in ["1", "L", "I", "P", "F"]:
3106 ndmax = 2
3107 elif mode == "RGB":
3108 ndmax = 3
3109 else:
3110 ndmax = 4
3111 if ndim > ndmax:
3112 msg = f"Too many dimensions: {ndim} > {ndmax}."
3113 raise ValueError(msg)
3115 size = 1 if ndim == 1 else shape[1], shape[0]
3116 if strides is not None:
3117 if hasattr(obj, "tobytes"):
3118 obj = obj.tobytes()
3119 else:
3120 obj = obj.tostring()
3122 return frombuffer(mode, size, obj, "raw", rawmode, 0, 1)
3125def fromqimage(im):
3126 """Creates an image instance from a QImage image"""
3127 from . import ImageQt
3129 if not ImageQt.qt_is_installed:
3130 msg = "Qt bindings are not installed"
3131 raise ImportError(msg)
3132 return ImageQt.fromqimage(im)
3135def fromqpixmap(im):
3136 """Creates an image instance from a QPixmap image"""
3137 from . import ImageQt
3139 if not ImageQt.qt_is_installed:
3140 msg = "Qt bindings are not installed"
3141 raise ImportError(msg)
3142 return ImageQt.fromqpixmap(im)
3145_fromarray_typemap = {
3146 # (shape, typestr) => mode, rawmode
3147 # first two members of shape are set to one
3148 ((1, 1), "|b1"): ("1", "1;8"),
3149 ((1, 1), "|u1"): ("L", "L"),
3150 ((1, 1), "|i1"): ("I", "I;8"),
3151 ((1, 1), "<u2"): ("I", "I;16"),
3152 ((1, 1), ">u2"): ("I", "I;16B"),
3153 ((1, 1), "<i2"): ("I", "I;16S"),
3154 ((1, 1), ">i2"): ("I", "I;16BS"),
3155 ((1, 1), "<u4"): ("I", "I;32"),
3156 ((1, 1), ">u4"): ("I", "I;32B"),
3157 ((1, 1), "<i4"): ("I", "I;32S"),
3158 ((1, 1), ">i4"): ("I", "I;32BS"),
3159 ((1, 1), "<f4"): ("F", "F;32F"),
3160 ((1, 1), ">f4"): ("F", "F;32BF"),
3161 ((1, 1), "<f8"): ("F", "F;64F"),
3162 ((1, 1), ">f8"): ("F", "F;64BF"),
3163 ((1, 1, 2), "|u1"): ("LA", "LA"),
3164 ((1, 1, 3), "|u1"): ("RGB", "RGB"),
3165 ((1, 1, 4), "|u1"): ("RGBA", "RGBA"),
3166 # shortcuts:
3167 ((1, 1), _ENDIAN + "i4"): ("I", "I"),
3168 ((1, 1), _ENDIAN + "f4"): ("F", "F"),
3169}
3172def _decompression_bomb_check(size):
3173 if MAX_IMAGE_PIXELS is None:
3174 return
3176 pixels = max(1, size[0]) * max(1, size[1])
3178 if pixels > 2 * MAX_IMAGE_PIXELS:
3179 msg = (
3180 f"Image size ({pixels} pixels) exceeds limit of {2 * MAX_IMAGE_PIXELS} "
3181 "pixels, could be decompression bomb DOS attack."
3182 )
3183 raise DecompressionBombError(msg)
3185 if pixels > MAX_IMAGE_PIXELS:
3186 warnings.warn(
3187 f"Image size ({pixels} pixels) exceeds limit of {MAX_IMAGE_PIXELS} pixels, "
3188 "could be decompression bomb DOS attack.",
3189 DecompressionBombWarning,
3190 )
3193def open(fp, mode="r", formats=None) -> Image:
3194 """
3195 Opens and identifies the given image file.
3197 This is a lazy operation; this function identifies the file, but
3198 the file remains open and the actual image data is not read from
3199 the file until you try to process the data (or call the
3200 :py:meth:`~PIL.Image.Image.load` method). See
3201 :py:func:`~PIL.Image.new`. See :ref:`file-handling`.
3203 :param fp: A filename (string), pathlib.Path object or a file object.
3204 The file object must implement ``file.read``,
3205 ``file.seek``, and ``file.tell`` methods,
3206 and be opened in binary mode. The file object will also seek to zero
3207 before reading.
3208 :param mode: The mode. If given, this argument must be "r".
3209 :param formats: A list or tuple of formats to attempt to load the file in.
3210 This can be used to restrict the set of formats checked.
3211 Pass ``None`` to try all supported formats. You can print the set of
3212 available formats by running ``python3 -m PIL`` or using
3213 the :py:func:`PIL.features.pilinfo` function.
3214 :returns: An :py:class:`~PIL.Image.Image` object.
3215 :exception FileNotFoundError: If the file cannot be found.
3216 :exception PIL.UnidentifiedImageError: If the image cannot be opened and
3217 identified.
3218 :exception ValueError: If the ``mode`` is not "r", or if a ``StringIO``
3219 instance is used for ``fp``.
3220 :exception TypeError: If ``formats`` is not ``None``, a list or a tuple.
3221 """
3223 if mode != "r":
3224 msg = f"bad mode {repr(mode)}"
3225 raise ValueError(msg)
3226 elif isinstance(fp, io.StringIO):
3227 msg = (
3228 "StringIO cannot be used to open an image. "
3229 "Binary data must be used instead."
3230 )
3231 raise ValueError(msg)
3233 if formats is None:
3234 formats = ID
3235 elif not isinstance(formats, (list, tuple)):
3236 msg = "formats must be a list or tuple"
3237 raise TypeError(msg)
3239 exclusive_fp = False
3240 filename = ""
3241 if isinstance(fp, Path):
3242 filename = str(fp.resolve())
3243 elif is_path(fp):
3244 filename = fp
3246 if filename:
3247 fp = builtins.open(filename, "rb")
3248 exclusive_fp = True
3250 try:
3251 fp.seek(0)
3252 except (AttributeError, io.UnsupportedOperation):
3253 fp = io.BytesIO(fp.read())
3254 exclusive_fp = True
3256 prefix = fp.read(16)
3258 preinit()
3260 accept_warnings = []
3262 def _open_core(fp, filename, prefix, formats):
3263 for i in formats:
3264 i = i.upper()
3265 if i not in OPEN:
3266 init()
3267 try:
3268 factory, accept = OPEN[i]
3269 result = not accept or accept(prefix)
3270 if type(result) in [str, bytes]:
3271 accept_warnings.append(result)
3272 elif result:
3273 fp.seek(0)
3274 im = factory(fp, filename)
3275 _decompression_bomb_check(im.size)
3276 return im
3277 except (SyntaxError, IndexError, TypeError, struct.error):
3278 # Leave disabled by default, spams the logs with image
3279 # opening failures that are entirely expected.
3280 # logger.debug("", exc_info=True)
3281 continue
3282 except BaseException:
3283 if exclusive_fp:
3284 fp.close()
3285 raise
3286 return None
3288 im = _open_core(fp, filename, prefix, formats)
3290 if im is None and formats is ID:
3291 checked_formats = formats.copy()
3292 if init():
3293 im = _open_core(
3294 fp,
3295 filename,
3296 prefix,
3297 tuple(format for format in formats if format not in checked_formats),
3298 )
3300 if im:
3301 im._exclusive_fp = exclusive_fp
3302 return im
3304 if exclusive_fp:
3305 fp.close()
3306 for message in accept_warnings:
3307 warnings.warn(message)
3308 msg = "cannot identify image file %r" % (filename if filename else fp)
3309 raise UnidentifiedImageError(msg)
3312#
3313# Image processing.
3316def alpha_composite(im1, im2):
3317 """
3318 Alpha composite im2 over im1.
3320 :param im1: The first image. Must have mode RGBA.
3321 :param im2: The second image. Must have mode RGBA, and the same size as
3322 the first image.
3323 :returns: An :py:class:`~PIL.Image.Image` object.
3324 """
3326 im1.load()
3327 im2.load()
3328 return im1._new(core.alpha_composite(im1.im, im2.im))
3331def blend(im1, im2, alpha):
3332 """
3333 Creates a new image by interpolating between two input images, using
3334 a constant alpha::
3336 out = image1 * (1.0 - alpha) + image2 * alpha
3338 :param im1: The first image.
3339 :param im2: The second image. Must have the same mode and size as
3340 the first image.
3341 :param alpha: The interpolation alpha factor. If alpha is 0.0, a
3342 copy of the first image is returned. If alpha is 1.0, a copy of
3343 the second image is returned. There are no restrictions on the
3344 alpha value. If necessary, the result is clipped to fit into
3345 the allowed output range.
3346 :returns: An :py:class:`~PIL.Image.Image` object.
3347 """
3349 im1.load()
3350 im2.load()
3351 return im1._new(core.blend(im1.im, im2.im, alpha))
3354def composite(image1, image2, mask):
3355 """
3356 Create composite image by blending images using a transparency mask.
3358 :param image1: The first image.
3359 :param image2: The second image. Must have the same mode and
3360 size as the first image.
3361 :param mask: A mask image. This image can have mode
3362 "1", "L", or "RGBA", and must have the same size as the
3363 other two images.
3364 """
3366 image = image2.copy()
3367 image.paste(image1, None, mask)
3368 return image
3371def eval(image, *args):
3372 """
3373 Applies the function (which should take one argument) to each pixel
3374 in the given image. If the image has more than one band, the same
3375 function is applied to each band. Note that the function is
3376 evaluated once for each possible pixel value, so you cannot use
3377 random components or other generators.
3379 :param image: The input image.
3380 :param function: A function object, taking one integer argument.
3381 :returns: An :py:class:`~PIL.Image.Image` object.
3382 """
3384 return image.point(args[0])
3387def merge(mode, bands):
3388 """
3389 Merge a set of single band images into a new multiband image.
3391 :param mode: The mode to use for the output image. See:
3392 :ref:`concept-modes`.
3393 :param bands: A sequence containing one single-band image for
3394 each band in the output image. All bands must have the
3395 same size.
3396 :returns: An :py:class:`~PIL.Image.Image` object.
3397 """
3399 if getmodebands(mode) != len(bands) or "*" in mode:
3400 msg = "wrong number of bands"
3401 raise ValueError(msg)
3402 for band in bands[1:]:
3403 if band.mode != getmodetype(mode):
3404 msg = "mode mismatch"
3405 raise ValueError(msg)
3406 if band.size != bands[0].size:
3407 msg = "size mismatch"
3408 raise ValueError(msg)
3409 for band in bands:
3410 band.load()
3411 return bands[0]._new(core.merge(mode, *[b.im for b in bands]))
3414# --------------------------------------------------------------------
3415# Plugin registry
3418def register_open(id, factory, accept=None) -> None:
3419 """
3420 Register an image file plugin. This function should not be used
3421 in application code.
3423 :param id: An image format identifier.
3424 :param factory: An image file factory method.
3425 :param accept: An optional function that can be used to quickly
3426 reject images having another format.
3427 """
3428 id = id.upper()
3429 if id not in ID:
3430 ID.append(id)
3431 OPEN[id] = factory, accept
3434def register_mime(id, mimetype):
3435 """
3436 Registers an image MIME type by populating ``Image.MIME``. This function
3437 should not be used in application code.
3439 ``Image.MIME`` provides a mapping from image format identifiers to mime
3440 formats, but :py:meth:`~PIL.ImageFile.ImageFile.get_format_mimetype` can
3441 provide a different result for specific images.
3443 :param id: An image format identifier.
3444 :param mimetype: The image MIME type for this format.
3445 """
3446 MIME[id.upper()] = mimetype
3449def register_save(id, driver):
3450 """
3451 Registers an image save function. This function should not be
3452 used in application code.
3454 :param id: An image format identifier.
3455 :param driver: A function to save images in this format.
3456 """
3457 SAVE[id.upper()] = driver
3460def register_save_all(id, driver):
3461 """
3462 Registers an image function to save all the frames
3463 of a multiframe format. This function should not be
3464 used in application code.
3466 :param id: An image format identifier.
3467 :param driver: A function to save images in this format.
3468 """
3469 SAVE_ALL[id.upper()] = driver
3472def register_extension(id, extension) -> None:
3473 """
3474 Registers an image extension. This function should not be
3475 used in application code.
3477 :param id: An image format identifier.
3478 :param extension: An extension used for this format.
3479 """
3480 EXTENSION[extension.lower()] = id.upper()
3483def register_extensions(id, extensions):
3484 """
3485 Registers image extensions. This function should not be
3486 used in application code.
3488 :param id: An image format identifier.
3489 :param extensions: A list of extensions used for this format.
3490 """
3491 for extension in extensions:
3492 register_extension(id, extension)
3495def registered_extensions():
3496 """
3497 Returns a dictionary containing all file extensions belonging
3498 to registered plugins
3499 """
3500 init()
3501 return EXTENSION
3504def register_decoder(name, decoder):
3505 """
3506 Registers an image decoder. This function should not be
3507 used in application code.
3509 :param name: The name of the decoder
3510 :param decoder: A callable(mode, args) that returns an
3511 ImageFile.PyDecoder object
3513 .. versionadded:: 4.1.0
3514 """
3515 DECODERS[name] = decoder
3518def register_encoder(name, encoder):
3519 """
3520 Registers an image encoder. This function should not be
3521 used in application code.
3523 :param name: The name of the encoder
3524 :param encoder: A callable(mode, args) that returns an
3525 ImageFile.PyEncoder object
3527 .. versionadded:: 4.1.0
3528 """
3529 ENCODERS[name] = encoder
3532# --------------------------------------------------------------------
3533# Simple display support.
3536def _show(image, **options):
3537 from . import ImageShow
3539 ImageShow.show(image, **options)
3542# --------------------------------------------------------------------
3543# Effects
3546def effect_mandelbrot(size, extent, quality):
3547 """
3548 Generate a Mandelbrot set covering the given extent.
3550 :param size: The requested size in pixels, as a 2-tuple:
3551 (width, height).
3552 :param extent: The extent to cover, as a 4-tuple:
3553 (x0, y0, x1, y1).
3554 :param quality: Quality.
3555 """
3556 return Image()._new(core.effect_mandelbrot(size, extent, quality))
3559def effect_noise(size, sigma):
3560 """
3561 Generate Gaussian noise centered around 128.
3563 :param size: The requested size in pixels, as a 2-tuple:
3564 (width, height).
3565 :param sigma: Standard deviation of noise.
3566 """
3567 return Image()._new(core.effect_noise(size, sigma))
3570def linear_gradient(mode):
3571 """
3572 Generate 256x256 linear gradient from black to white, top to bottom.
3574 :param mode: Input mode.
3575 """
3576 return Image()._new(core.linear_gradient(mode))
3579def radial_gradient(mode):
3580 """
3581 Generate 256x256 radial gradient from black to white, centre to edge.
3583 :param mode: Input mode.
3584 """
3585 return Image()._new(core.radial_gradient(mode))
3588# --------------------------------------------------------------------
3589# Resources
3592def _apply_env_variables(env=None):
3593 if env is None:
3594 env = os.environ
3596 for var_name, setter in [
3597 ("PILLOW_ALIGNMENT", core.set_alignment),
3598 ("PILLOW_BLOCK_SIZE", core.set_block_size),
3599 ("PILLOW_BLOCKS_MAX", core.set_blocks_max),
3600 ]:
3601 if var_name not in env:
3602 continue
3604 var = env[var_name].lower()
3606 units = 1
3607 for postfix, mul in [("k", 1024), ("m", 1024 * 1024)]:
3608 if var.endswith(postfix):
3609 units = mul
3610 var = var[: -len(postfix)]
3612 try:
3613 var = int(var) * units
3614 except ValueError:
3615 warnings.warn(f"{var_name} is not int")
3616 continue
3618 try:
3619 setter(var)
3620 except ValueError as e:
3621 warnings.warn(f"{var_name}: {e}")
3624_apply_env_variables()
3625atexit.register(core.clear_cache)
3628class Exif(MutableMapping):
3629 """
3630 This class provides read and write access to EXIF image data::
3632 from PIL import Image
3633 im = Image.open("exif.png")
3634 exif = im.getexif() # Returns an instance of this class
3636 Information can be read and written, iterated over or deleted::
3638 print(exif[274]) # 1
3639 exif[274] = 2
3640 for k, v in exif.items():
3641 print("Tag", k, "Value", v) # Tag 274 Value 2
3642 del exif[274]
3644 To access information beyond IFD0, :py:meth:`~PIL.Image.Exif.get_ifd`
3645 returns a dictionary::
3647 from PIL import ExifTags
3648 im = Image.open("exif_gps.jpg")
3649 exif = im.getexif()
3650 gps_ifd = exif.get_ifd(ExifTags.IFD.GPSInfo)
3651 print(gps_ifd)
3653 Other IFDs include ``ExifTags.IFD.Exif``, ``ExifTags.IFD.Makernote``,
3654 ``ExifTags.IFD.Interop`` and ``ExifTags.IFD.IFD1``.
3656 :py:mod:`~PIL.ExifTags` also has enum classes to provide names for data::
3658 print(exif[ExifTags.Base.Software]) # PIL
3659 print(gps_ifd[ExifTags.GPS.GPSDateStamp]) # 1999:99:99 99:99:99
3660 """
3662 endian = None
3663 bigtiff = False
3665 def __init__(self):
3666 self._data = {}
3667 self._hidden_data = {}
3668 self._ifds = {}
3669 self._info = None
3670 self._loaded_exif = None
3672 def _fixup(self, value):
3673 try:
3674 if len(value) == 1 and isinstance(value, tuple):
3675 return value[0]
3676 except Exception:
3677 pass
3678 return value
3680 def _fixup_dict(self, src_dict):
3681 # Helper function
3682 # returns a dict with any single item tuples/lists as individual values
3683 return {k: self._fixup(v) for k, v in src_dict.items()}
3685 def _get_ifd_dict(self, offset):
3686 try:
3687 # an offset pointer to the location of the nested embedded IFD.
3688 # It should be a long, but may be corrupted.
3689 self.fp.seek(offset)
3690 except (KeyError, TypeError):
3691 pass
3692 else:
3693 from . import TiffImagePlugin
3695 info = TiffImagePlugin.ImageFileDirectory_v2(self.head)
3696 info.load(self.fp)
3697 return self._fixup_dict(info)
3699 def _get_head(self):
3700 version = b"\x2B" if self.bigtiff else b"\x2A"
3701 if self.endian == "<":
3702 head = b"II" + version + b"\x00" + o32le(8)
3703 else:
3704 head = b"MM\x00" + version + o32be(8)
3705 if self.bigtiff:
3706 head += o32le(8) if self.endian == "<" else o32be(8)
3707 head += b"\x00\x00\x00\x00"
3708 return head
3710 def load(self, data):
3711 # Extract EXIF information. This is highly experimental,
3712 # and is likely to be replaced with something better in a future
3713 # version.
3715 # The EXIF record consists of a TIFF file embedded in a JPEG
3716 # application marker (!).
3717 if data == self._loaded_exif:
3718 return
3719 self._loaded_exif = data
3720 self._data.clear()
3721 self._hidden_data.clear()
3722 self._ifds.clear()
3723 if data and data.startswith(b"Exif\x00\x00"):
3724 data = data[6:]
3725 if not data:
3726 self._info = None
3727 return
3729 self.fp = io.BytesIO(data)
3730 self.head = self.fp.read(8)
3731 # process dictionary
3732 from . import TiffImagePlugin
3734 self._info = TiffImagePlugin.ImageFileDirectory_v2(self.head)
3735 self.endian = self._info._endian
3736 self.fp.seek(self._info.next)
3737 self._info.load(self.fp)
3739 def load_from_fp(self, fp, offset=None):
3740 self._loaded_exif = None
3741 self._data.clear()
3742 self._hidden_data.clear()
3743 self._ifds.clear()
3745 # process dictionary
3746 from . import TiffImagePlugin
3748 self.fp = fp
3749 if offset is not None:
3750 self.head = self._get_head()
3751 else:
3752 self.head = self.fp.read(8)
3753 self._info = TiffImagePlugin.ImageFileDirectory_v2(self.head)
3754 if self.endian is None:
3755 self.endian = self._info._endian
3756 if offset is None:
3757 offset = self._info.next
3758 self.fp.tell()
3759 self.fp.seek(offset)
3760 self._info.load(self.fp)
3762 def _get_merged_dict(self):
3763 merged_dict = dict(self)
3765 # get EXIF extension
3766 if ExifTags.IFD.Exif in self:
3767 ifd = self._get_ifd_dict(self[ExifTags.IFD.Exif])
3768 if ifd:
3769 merged_dict.update(ifd)
3771 # GPS
3772 if ExifTags.IFD.GPSInfo in self:
3773 merged_dict[ExifTags.IFD.GPSInfo] = self._get_ifd_dict(
3774 self[ExifTags.IFD.GPSInfo]
3775 )
3777 return merged_dict
3779 def tobytes(self, offset=8):
3780 from . import TiffImagePlugin
3782 head = self._get_head()
3783 ifd = TiffImagePlugin.ImageFileDirectory_v2(ifh=head)
3784 for tag, value in self.items():
3785 if tag in [
3786 ExifTags.IFD.Exif,
3787 ExifTags.IFD.GPSInfo,
3788 ] and not isinstance(value, dict):
3789 value = self.get_ifd(tag)
3790 if (
3791 tag == ExifTags.IFD.Exif
3792 and ExifTags.IFD.Interop in value
3793 and not isinstance(value[ExifTags.IFD.Interop], dict)
3794 ):
3795 value = value.copy()
3796 value[ExifTags.IFD.Interop] = self.get_ifd(ExifTags.IFD.Interop)
3797 ifd[tag] = value
3798 return b"Exif\x00\x00" + head + ifd.tobytes(offset)
3800 def get_ifd(self, tag):
3801 if tag not in self._ifds:
3802 if tag == ExifTags.IFD.IFD1:
3803 if self._info is not None and self._info.next != 0:
3804 self._ifds[tag] = self._get_ifd_dict(self._info.next)
3805 elif tag in [ExifTags.IFD.Exif, ExifTags.IFD.GPSInfo]:
3806 offset = self._hidden_data.get(tag, self.get(tag))
3807 if offset is not None:
3808 self._ifds[tag] = self._get_ifd_dict(offset)
3809 elif tag in [ExifTags.IFD.Interop, ExifTags.IFD.Makernote]:
3810 if ExifTags.IFD.Exif not in self._ifds:
3811 self.get_ifd(ExifTags.IFD.Exif)
3812 tag_data = self._ifds[ExifTags.IFD.Exif][tag]
3813 if tag == ExifTags.IFD.Makernote:
3814 from .TiffImagePlugin import ImageFileDirectory_v2
3816 if tag_data[:8] == b"FUJIFILM":
3817 ifd_offset = i32le(tag_data, 8)
3818 ifd_data = tag_data[ifd_offset:]
3820 makernote = {}
3821 for i in range(0, struct.unpack("<H", ifd_data[:2])[0]):
3822 ifd_tag, typ, count, data = struct.unpack(
3823 "<HHL4s", ifd_data[i * 12 + 2 : (i + 1) * 12 + 2]
3824 )
3825 try:
3826 (
3827 unit_size,
3828 handler,
3829 ) = ImageFileDirectory_v2._load_dispatch[typ]
3830 except KeyError:
3831 continue
3832 size = count * unit_size
3833 if size > 4:
3834 (offset,) = struct.unpack("<L", data)
3835 data = ifd_data[offset - 12 : offset + size - 12]
3836 else:
3837 data = data[:size]
3839 if len(data) != size:
3840 warnings.warn(
3841 "Possibly corrupt EXIF MakerNote data. "
3842 f"Expecting to read {size} bytes but only got "
3843 f"{len(data)}. Skipping tag {ifd_tag}"
3844 )
3845 continue
3847 if not data:
3848 continue
3850 makernote[ifd_tag] = handler(
3851 ImageFileDirectory_v2(), data, False
3852 )
3853 self._ifds[tag] = dict(self._fixup_dict(makernote))
3854 elif self.get(0x010F) == "Nintendo":
3855 makernote = {}
3856 for i in range(0, struct.unpack(">H", tag_data[:2])[0]):
3857 ifd_tag, typ, count, data = struct.unpack(
3858 ">HHL4s", tag_data[i * 12 + 2 : (i + 1) * 12 + 2]
3859 )
3860 if ifd_tag == 0x1101:
3861 # CameraInfo
3862 (offset,) = struct.unpack(">L", data)
3863 self.fp.seek(offset)
3865 camerainfo = {"ModelID": self.fp.read(4)}
3867 self.fp.read(4)
3868 # Seconds since 2000
3869 camerainfo["TimeStamp"] = i32le(self.fp.read(12))
3871 self.fp.read(4)
3872 camerainfo["InternalSerialNumber"] = self.fp.read(4)
3874 self.fp.read(12)
3875 parallax = self.fp.read(4)
3876 handler = ImageFileDirectory_v2._load_dispatch[
3877 TiffTags.FLOAT
3878 ][1]
3879 camerainfo["Parallax"] = handler(
3880 ImageFileDirectory_v2(), parallax, False
3881 )
3883 self.fp.read(4)
3884 camerainfo["Category"] = self.fp.read(2)
3886 makernote = {0x1101: dict(self._fixup_dict(camerainfo))}
3887 self._ifds[tag] = makernote
3888 else:
3889 # Interop
3890 self._ifds[tag] = self._get_ifd_dict(tag_data)
3891 ifd = self._ifds.get(tag, {})
3892 if tag == ExifTags.IFD.Exif and self._hidden_data:
3893 ifd = {
3894 k: v
3895 for (k, v) in ifd.items()
3896 if k not in (ExifTags.IFD.Interop, ExifTags.IFD.Makernote)
3897 }
3898 return ifd
3900 def hide_offsets(self):
3901 for tag in (ExifTags.IFD.Exif, ExifTags.IFD.GPSInfo):
3902 if tag in self:
3903 self._hidden_data[tag] = self[tag]
3904 del self[tag]
3906 def __str__(self):
3907 if self._info is not None:
3908 # Load all keys into self._data
3909 for tag in self._info:
3910 self[tag]
3912 return str(self._data)
3914 def __len__(self):
3915 keys = set(self._data)
3916 if self._info is not None:
3917 keys.update(self._info)
3918 return len(keys)
3920 def __getitem__(self, tag):
3921 if self._info is not None and tag not in self._data and tag in self._info:
3922 self._data[tag] = self._fixup(self._info[tag])
3923 del self._info[tag]
3924 return self._data[tag]
3926 def __contains__(self, tag):
3927 return tag in self._data or (self._info is not None and tag in self._info)
3929 def __setitem__(self, tag, value):
3930 if self._info is not None and tag in self._info:
3931 del self._info[tag]
3932 self._data[tag] = value
3934 def __delitem__(self, tag):
3935 if self._info is not None and tag in self._info:
3936 del self._info[tag]
3937 else:
3938 del self._data[tag]
3940 def __iter__(self):
3941 keys = set(self._data)
3942 if self._info is not None:
3943 keys.update(self._info)
3944 return iter(keys)