Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/PIL/Image.py: 25%
1551 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
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#
27import atexit
28import builtins
29import io
30import logging
31import math
32import os
33import re
34import struct
35import sys
36import tempfile
37import warnings
38from collections.abc import Callable, MutableMapping
39from enum import IntEnum
40from pathlib import Path
42try:
43 import defusedxml.ElementTree as ElementTree
44except ImportError:
45 ElementTree = None
47# VERSION was removed in Pillow 6.0.0.
48# PILLOW_VERSION was removed in Pillow 9.0.0.
49# Use __version__ instead.
50from . import ImageMode, TiffTags, UnidentifiedImageError, __version__, _plugins
51from ._binary import i32le, o32be, o32le
52from ._deprecate import deprecate
53from ._util import DeferredError, is_path
56def __getattr__(name):
57 categories = {"NORMAL": 0, "SEQUENCE": 1, "CONTAINER": 2}
58 if name in categories:
59 deprecate("Image categories", 10, "is_animated", plural=True)
60 return categories[name]
61 elif name in ("NEAREST", "NONE"):
62 deprecate(name, 10, "Resampling.NEAREST or Dither.NONE")
63 return 0
64 old_resampling = {
65 "LINEAR": "BILINEAR",
66 "CUBIC": "BICUBIC",
67 "ANTIALIAS": "LANCZOS",
68 }
69 if name in old_resampling:
70 deprecate(name, 10, f"Resampling.{old_resampling[name]}")
71 return Resampling[old_resampling[name]]
72 for enum in (Transpose, Transform, Resampling, Dither, Palette, Quantize):
73 if name in enum.__members__:
74 deprecate(name, 10, f"{enum.__name__}.{name}")
75 return enum[name]
76 raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
79logger = logging.getLogger(__name__)
82class DecompressionBombWarning(RuntimeWarning):
83 pass
86class DecompressionBombError(Exception):
87 pass
90# Limit to around a quarter gigabyte for a 24-bit (3 bpp) image
91MAX_IMAGE_PIXELS = int(1024 * 1024 * 1024 // 4 // 3)
94try:
95 # If the _imaging C module is not present, Pillow will not load.
96 # Note that other modules should not refer to _imaging directly;
97 # import Image and use the Image.core variable instead.
98 # Also note that Image.core is not a publicly documented interface,
99 # and should be considered private and subject to change.
100 from . import _imaging as core
102 if __version__ != getattr(core, "PILLOW_VERSION", None): 102 ↛ 103line 102 didn't jump to line 103, because the condition on line 102 was never true
103 raise ImportError(
104 "The _imaging extension was built for another version of Pillow or PIL:\n"
105 f"Core version: {getattr(core, 'PILLOW_VERSION', None)}\n"
106 f"Pillow version: {__version__}"
107 )
109except ImportError as v:
110 core = DeferredError(ImportError("The _imaging C module is not installed."))
111 # Explanations for ways that we know we might have an import error
112 if str(v).startswith("Module use of python"):
113 # The _imaging C module is present, but not compiled for
114 # the right version (windows only). Print a warning, if
115 # possible.
116 warnings.warn(
117 "The _imaging extension was built for another version of Python.",
118 RuntimeWarning,
119 )
120 elif str(v).startswith("The _imaging extension"):
121 warnings.warn(str(v), RuntimeWarning)
122 # Fail here anyway. Don't let people run with a mostly broken Pillow.
123 # see docs/porting.rst
124 raise
127# works everywhere, win for pypy, not cpython
128USE_CFFI_ACCESS = hasattr(sys, "pypy_version_info")
129try:
130 import cffi
131except ImportError:
132 cffi = None
135def isImageType(t):
136 """
137 Checks if an object is an image object.
139 .. warning::
141 This function is for internal use only.
143 :param t: object to check if it's an image
144 :returns: True if the object is an image
145 """
146 return hasattr(t, "im")
149#
150# Constants
152# transpose
153class Transpose(IntEnum):
154 FLIP_LEFT_RIGHT = 0
155 FLIP_TOP_BOTTOM = 1
156 ROTATE_90 = 2
157 ROTATE_180 = 3
158 ROTATE_270 = 4
159 TRANSPOSE = 5
160 TRANSVERSE = 6
163# transforms (also defined in Imaging.h)
164class Transform(IntEnum):
165 AFFINE = 0
166 EXTENT = 1
167 PERSPECTIVE = 2
168 QUAD = 3
169 MESH = 4
172# resampling filters (also defined in Imaging.h)
173class Resampling(IntEnum):
174 NEAREST = 0
175 BOX = 4
176 BILINEAR = 2
177 HAMMING = 5
178 BICUBIC = 3
179 LANCZOS = 1
182_filters_support = {
183 Resampling.BOX: 0.5,
184 Resampling.BILINEAR: 1.0,
185 Resampling.HAMMING: 1.0,
186 Resampling.BICUBIC: 2.0,
187 Resampling.LANCZOS: 3.0,
188}
191# dithers
192class Dither(IntEnum):
193 NONE = 0
194 ORDERED = 1 # Not yet implemented
195 RASTERIZE = 2 # Not yet implemented
196 FLOYDSTEINBERG = 3 # default
199# palettes/quantizers
200class Palette(IntEnum):
201 WEB = 0
202 ADAPTIVE = 1
205class Quantize(IntEnum):
206 MEDIANCUT = 0
207 MAXCOVERAGE = 1
208 FASTOCTREE = 2
209 LIBIMAGEQUANT = 3
212if hasattr(core, "DEFAULT_STRATEGY"): 212 ↛ 223line 212 didn't jump to line 223, because the condition on line 212 was never false
213 DEFAULT_STRATEGY = core.DEFAULT_STRATEGY
214 FILTERED = core.FILTERED
215 HUFFMAN_ONLY = core.HUFFMAN_ONLY
216 RLE = core.RLE
217 FIXED = core.FIXED
220# --------------------------------------------------------------------
221# Registries
223ID = []
224OPEN = {}
225MIME = {}
226SAVE = {}
227SAVE_ALL = {}
228EXTENSION = {}
229DECODERS = {}
230ENCODERS = {}
232# --------------------------------------------------------------------
233# Modes
235_ENDIAN = "<" if sys.byteorder == "little" else ">"
238def _conv_type_shape(im):
239 m = ImageMode.getmode(im.mode)
240 shape = (im.height, im.width)
241 extra = len(m.bands)
242 if extra != 1:
243 shape += (extra,)
244 return shape, m.typestr
247MODES = ["1", "CMYK", "F", "HSV", "I", "L", "LAB", "P", "RGB", "RGBA", "RGBX", "YCbCr"]
249# raw modes that may be memory mapped. NOTE: if you change this, you
250# may have to modify the stride calculation in map.c too!
251_MAPMODES = ("L", "P", "RGBX", "RGBA", "CMYK", "I;16", "I;16L", "I;16B")
254def getmodebase(mode):
255 """
256 Gets the "base" mode for given mode. This function returns "L" for
257 images that contain grayscale data, and "RGB" for images that
258 contain color data.
260 :param mode: Input mode.
261 :returns: "L" or "RGB".
262 :exception KeyError: If the input mode was not a standard mode.
263 """
264 return ImageMode.getmode(mode).basemode
267def getmodetype(mode):
268 """
269 Gets the storage type mode. Given a mode, this function returns a
270 single-layer mode suitable for storing individual bands.
272 :param mode: Input mode.
273 :returns: "L", "I", or "F".
274 :exception KeyError: If the input mode was not a standard mode.
275 """
276 return ImageMode.getmode(mode).basetype
279def getmodebandnames(mode):
280 """
281 Gets a list of individual band names. Given a mode, this function returns
282 a tuple containing the names of individual bands (use
283 :py:method:`~PIL.Image.getmodetype` to get the mode used to store each
284 individual band.
286 :param mode: Input mode.
287 :returns: A tuple containing band names. The length of the tuple
288 gives the number of bands in an image of the given mode.
289 :exception KeyError: If the input mode was not a standard mode.
290 """
291 return ImageMode.getmode(mode).bands
294def getmodebands(mode):
295 """
296 Gets the number of individual bands for this mode.
298 :param mode: Input mode.
299 :returns: The number of bands in this mode.
300 :exception KeyError: If the input mode was not a standard mode.
301 """
302 return len(ImageMode.getmode(mode).bands)
305# --------------------------------------------------------------------
306# Helpers
308_initialized = 0
311def preinit():
312 """Explicitly load standard file format drivers."""
314 global _initialized
315 if _initialized >= 1:
316 return
318 try:
319 from . import BmpImagePlugin
321 assert BmpImagePlugin
322 except ImportError:
323 pass
324 try:
325 from . import GifImagePlugin
327 assert GifImagePlugin
328 except ImportError:
329 pass
330 try:
331 from . import JpegImagePlugin
333 assert JpegImagePlugin
334 except ImportError:
335 pass
336 try:
337 from . import PpmImagePlugin
339 assert PpmImagePlugin
340 except ImportError:
341 pass
342 try:
343 from . import PngImagePlugin
345 assert PngImagePlugin
346 except ImportError:
347 pass
348 # try:
349 # import TiffImagePlugin
350 # assert TiffImagePlugin
351 # except ImportError:
352 # pass
354 _initialized = 1
357def init():
358 """
359 Explicitly initializes the Python Imaging Library. This function
360 loads all available file format drivers.
361 """
363 global _initialized
364 if _initialized >= 2: 364 ↛ 365line 364 didn't jump to line 365, because the condition on line 364 was never true
365 return 0
367 for plugin in _plugins:
368 try:
369 logger.debug("Importing %s", plugin)
370 __import__(f"PIL.{plugin}", globals(), locals(), [])
371 except ImportError as e:
372 logger.debug("Image: failed to import %s: %s", plugin, e)
374 if OPEN or SAVE: 374 ↛ exitline 374 didn't return from function 'init', because the condition on line 374 was never false
375 _initialized = 2
376 return 1
379# --------------------------------------------------------------------
380# Codec factories (used by tobytes/frombytes and ImageFile.load)
383def _getdecoder(mode, decoder_name, args, extra=()):
385 # tweak arguments
386 if args is None:
387 args = ()
388 elif not isinstance(args, tuple):
389 args = (args,)
391 try:
392 decoder = DECODERS[decoder_name]
393 except KeyError:
394 pass
395 else:
396 return decoder(mode, *args + extra)
398 try:
399 # get decoder
400 decoder = getattr(core, decoder_name + "_decoder")
401 except AttributeError as e:
402 raise OSError(f"decoder {decoder_name} not available") from e
403 return decoder(mode, *args + extra)
406def _getencoder(mode, encoder_name, args, extra=()):
408 # tweak arguments
409 if args is None: 409 ↛ 410line 409 didn't jump to line 410, because the condition on line 409 was never true
410 args = ()
411 elif not isinstance(args, tuple): 411 ↛ 414line 411 didn't jump to line 414, because the condition on line 411 was never false
412 args = (args,)
414 try:
415 encoder = ENCODERS[encoder_name]
416 except KeyError:
417 pass
418 else:
419 return encoder(mode, *args + extra)
421 try:
422 # get encoder
423 encoder = getattr(core, encoder_name + "_encoder")
424 except AttributeError as e:
425 raise OSError(f"encoder {encoder_name} not available") from e
426 return encoder(mode, *args + extra)
429# --------------------------------------------------------------------
430# Simple expression analyzer
433def coerce_e(value):
434 deprecate("coerce_e", 10)
435 return value if isinstance(value, _E) else _E(1, value)
438# _E(scale, offset) represents the affine transformation scale * x + offset.
439# The "data" field is named for compatibility with the old implementation,
440# and should be renamed once coerce_e is removed.
441class _E:
442 def __init__(self, scale, data):
443 self.scale = scale
444 self.data = data
446 def __neg__(self):
447 return _E(-self.scale, -self.data)
449 def __add__(self, other):
450 if isinstance(other, _E):
451 return _E(self.scale + other.scale, self.data + other.data)
452 return _E(self.scale, self.data + other)
454 __radd__ = __add__
456 def __sub__(self, other):
457 return self + -other
459 def __rsub__(self, other):
460 return other + -self
462 def __mul__(self, other):
463 if isinstance(other, _E):
464 return NotImplemented
465 return _E(self.scale * other, self.data * other)
467 __rmul__ = __mul__
469 def __truediv__(self, other):
470 if isinstance(other, _E):
471 return NotImplemented
472 return _E(self.scale / other, self.data / other)
475def _getscaleoffset(expr):
476 a = expr(_E(1, 0))
477 return (a.scale, a.data) if isinstance(a, _E) else (0, a)
480# --------------------------------------------------------------------
481# Implementation wrapper
484class Image:
485 """
486 This class represents an image object. To create
487 :py:class:`~PIL.Image.Image` objects, use the appropriate factory
488 functions. There's hardly ever any reason to call the Image constructor
489 directly.
491 * :py:func:`~PIL.Image.open`
492 * :py:func:`~PIL.Image.new`
493 * :py:func:`~PIL.Image.frombytes`
494 """
496 format = None
497 format_description = None
498 _close_exclusive_fp_after_loading = True
500 def __init__(self):
501 # FIXME: take "new" parameters / other image?
502 # FIXME: turn mode and size into delegating properties?
503 self.im = None
504 self.mode = ""
505 self._size = (0, 0)
506 self.palette = None
507 self.info = {}
508 self._category = 0
509 self.readonly = 0
510 self.pyaccess = None
511 self._exif = None
513 def __getattr__(self, name):
514 if name == "category": 514 ↛ 515line 514 didn't jump to line 515, because the condition on line 514 was never true
515 deprecate("Image categories", 10, "is_animated", plural=True)
516 return self._category
517 raise AttributeError(name)
519 @property
520 def width(self):
521 return self.size[0]
523 @property
524 def height(self):
525 return self.size[1]
527 @property
528 def size(self):
529 return self._size
531 def _new(self, im):
532 new = Image()
533 new.im = im
534 new.mode = im.mode
535 new._size = im.size
536 if im.mode in ("P", "PA"): 536 ↛ 537line 536 didn't jump to line 537, because the condition on line 536 was never true
537 if self.palette:
538 new.palette = self.palette.copy()
539 else:
540 from . import ImagePalette
542 new.palette = ImagePalette.ImagePalette()
543 new.info = self.info.copy()
544 return new
546 # Context manager support
547 def __enter__(self):
548 return self
550 def __exit__(self, *args):
551 if hasattr(self, "fp") and getattr(self, "_exclusive_fp", False):
552 if getattr(self, "_fp", False):
553 if self._fp != self.fp:
554 self._fp.close()
555 self._fp = DeferredError(ValueError("Operation on closed image"))
556 if self.fp:
557 self.fp.close()
558 self.fp = None
560 def close(self):
561 """
562 Closes the file pointer, if possible.
564 This operation will destroy the image core and release its memory.
565 The image data will be unusable afterward.
567 This function is required to close images that have multiple frames or
568 have not had their file read and closed by the
569 :py:meth:`~PIL.Image.Image.load` method. See :ref:`file-handling` for
570 more information.
571 """
572 try:
573 if getattr(self, "_fp", False): 573 ↛ 574line 573 didn't jump to line 574, because the condition on line 573 was never true
574 if self._fp != self.fp:
575 self._fp.close()
576 self._fp = DeferredError(ValueError("Operation on closed image"))
577 if self.fp: 577 ↛ 578, 577 ↛ 5792 missed branches: 1) line 577 didn't jump to line 578, because the condition on line 577 was never true, 2) line 577 didn't jump to line 579, because the condition on line 577 was never false
578 self.fp.close()
579 self.fp = None
580 except Exception as msg:
581 logger.debug("Error closing: %s", msg)
583 if getattr(self, "map", None): 583 ↛ 584line 583 didn't jump to line 584, because the condition on line 583 was never true
584 self.map = None
586 # Instead of simply setting to None, we're setting up a
587 # deferred error that will better explain that the core image
588 # object is gone.
589 self.im = DeferredError(ValueError("Operation on closed image"))
591 def _copy(self):
592 self.load()
593 self.im = self.im.copy()
594 self.pyaccess = None
595 self.readonly = 0
597 def _ensure_mutable(self):
598 if self.readonly: 598 ↛ 599line 598 didn't jump to line 599, because the condition on line 598 was never true
599 self._copy()
600 else:
601 self.load()
603 def _dump(self, file=None, format=None, **options):
604 suffix = ""
605 if format:
606 suffix = "." + format
608 if not file:
609 f, filename = tempfile.mkstemp(suffix)
610 os.close(f)
611 else:
612 filename = file
613 if not filename.endswith(suffix):
614 filename = filename + suffix
616 self.load()
618 if not format or format == "PPM":
619 self.im.save_ppm(filename)
620 else:
621 self.save(filename, format, **options)
623 return filename
625 def __eq__(self, other):
626 return (
627 self.__class__ is other.__class__
628 and self.mode == other.mode
629 and self.size == other.size
630 and self.info == other.info
631 and self._category == other._category
632 and self.getpalette() == other.getpalette()
633 and self.tobytes() == other.tobytes()
634 )
636 def __repr__(self):
637 return "<%s.%s image mode=%s size=%dx%d at 0x%X>" % (
638 self.__class__.__module__,
639 self.__class__.__name__,
640 self.mode,
641 self.size[0],
642 self.size[1],
643 id(self),
644 )
646 def _repr_pretty_(self, p, cycle):
647 """IPython plain text display support"""
649 # Same as __repr__ but without unpredicatable id(self),
650 # to keep Jupyter notebook `text/plain` output stable.
651 p.text(
652 "<%s.%s image mode=%s size=%dx%d>"
653 % (
654 self.__class__.__module__,
655 self.__class__.__name__,
656 self.mode,
657 self.size[0],
658 self.size[1],
659 )
660 )
662 def _repr_png_(self):
663 """iPython display hook support
665 :returns: png version of the image as bytes
666 """
667 b = io.BytesIO()
668 try:
669 self.save(b, "PNG")
670 except Exception as e:
671 raise ValueError("Could not save to PNG for display") from e
672 return b.getvalue()
674 @property
675 def __array_interface__(self):
676 # numpy array interface support
677 new = {}
678 shape, typestr = _conv_type_shape(self)
679 new["shape"] = shape
680 new["typestr"] = typestr
681 new["version"] = 3
682 if self.mode == "1":
683 # Binary images need to be extended from bits to bytes
684 # See: https://github.com/python-pillow/Pillow/issues/350
685 new["data"] = self.tobytes("raw", "L")
686 else:
687 new["data"] = self.tobytes()
688 return new
690 def __getstate__(self):
691 return [self.info, self.mode, self.size, self.getpalette(), self.tobytes()]
693 def __setstate__(self, state):
694 Image.__init__(self)
695 self.tile = []
696 info, mode, size, palette, data = state
697 self.info = info
698 self.mode = mode
699 self._size = size
700 self.im = core.new(mode, size)
701 if mode in ("L", "LA", "P", "PA") and palette:
702 self.putpalette(palette)
703 self.frombytes(data)
705 def tobytes(self, encoder_name="raw", *args):
706 """
707 Return image as a bytes object.
709 .. warning::
711 This method returns the raw image data from the internal
712 storage. For compressed image data (e.g. PNG, JPEG) use
713 :meth:`~.save`, with a BytesIO parameter for in-memory
714 data.
716 :param encoder_name: What encoder to use. The default is to
717 use the standard "raw" encoder.
718 :param args: Extra arguments to the encoder.
719 :returns: A :py:class:`bytes` object.
720 """
722 # may pass tuple instead of argument list
723 if len(args) == 1 and isinstance(args[0], tuple):
724 args = args[0]
726 if encoder_name == "raw" and args == ():
727 args = self.mode
729 self.load()
731 if self.width == 0 or self.height == 0:
732 return b""
734 # unpack data
735 e = _getencoder(self.mode, encoder_name, args)
736 e.setimage(self.im)
738 bufsize = max(65536, self.size[0] * 4) # see RawEncode.c
740 data = []
741 while True:
742 l, s, d = e.encode(bufsize)
743 data.append(d)
744 if s:
745 break
746 if s < 0:
747 raise RuntimeError(f"encoder error {s} in tobytes")
749 return b"".join(data)
751 def tobitmap(self, name="image"):
752 """
753 Returns the image converted to an X11 bitmap.
755 .. note:: This method only works for mode "1" images.
757 :param name: The name prefix to use for the bitmap variables.
758 :returns: A string containing an X11 bitmap.
759 :raises ValueError: If the mode is not "1"
760 """
762 self.load()
763 if self.mode != "1":
764 raise ValueError("not a bitmap")
765 data = self.tobytes("xbm")
766 return b"".join(
767 [
768 f"#define {name}_width {self.size[0]}\n".encode("ascii"),
769 f"#define {name}_height {self.size[1]}\n".encode("ascii"),
770 f"static char {name}_bits[] = {{\n".encode("ascii"),
771 data,
772 b"};",
773 ]
774 )
776 def frombytes(self, data, decoder_name="raw", *args):
777 """
778 Loads this image with pixel data from a bytes object.
780 This method is similar to the :py:func:`~PIL.Image.frombytes` function,
781 but loads data into this image instead of creating a new image object.
782 """
784 # may pass tuple instead of argument list
785 if len(args) == 1 and isinstance(args[0], tuple):
786 args = args[0]
788 # default format
789 if decoder_name == "raw" and args == ():
790 args = self.mode
792 # unpack data
793 d = _getdecoder(self.mode, decoder_name, args)
794 d.setimage(self.im)
795 s = d.decode(data)
797 if s[0] >= 0:
798 raise ValueError("not enough image data")
799 if s[1] != 0:
800 raise ValueError("cannot decode image data")
802 def load(self):
803 """
804 Allocates storage for the image and loads the pixel data. In
805 normal cases, you don't need to call this method, since the
806 Image class automatically loads an opened image when it is
807 accessed for the first time.
809 If the file associated with the image was opened by Pillow, then this
810 method will close it. The exception to this is if the image has
811 multiple frames, in which case the file will be left open for seek
812 operations. See :ref:`file-handling` for more information.
814 :returns: An image access object.
815 :rtype: :ref:`PixelAccess` or :py:class:`PIL.PyAccess`
816 """
817 if self.im is not None and self.palette and self.palette.dirty:
818 # realize palette
819 mode, arr = self.palette.getdata()
820 self.im.putpalette(mode, arr)
821 self.palette.dirty = 0
822 self.palette.rawmode = None
823 if "transparency" in self.info and mode in ("LA", "PA"): 823 ↛ 824line 823 didn't jump to line 824, because the condition on line 823 was never true
824 if isinstance(self.info["transparency"], int):
825 self.im.putpalettealpha(self.info["transparency"], 0)
826 else:
827 self.im.putpalettealphas(self.info["transparency"])
828 self.palette.mode = "RGBA"
829 else:
830 palette_mode = "RGBA" if mode.startswith("RGBA") else "RGB"
831 self.palette.mode = palette_mode
832 self.palette.palette = self.im.getpalette(palette_mode, palette_mode)
834 if self.im is not None: 834 ↛ exitline 834 didn't return from function 'load', because the condition on line 834 was never false
835 if cffi and USE_CFFI_ACCESS: 835 ↛ 836line 835 didn't jump to line 836, because the condition on line 835 was never true
836 if self.pyaccess:
837 return self.pyaccess
838 from . import PyAccess
840 self.pyaccess = PyAccess.new(self, self.readonly)
841 if self.pyaccess:
842 return self.pyaccess
843 return self.im.pixel_access(self.readonly)
845 def verify(self):
846 """
847 Verifies the contents of a file. For data read from a file, this
848 method attempts to determine if the file is broken, without
849 actually decoding the image data. If this method finds any
850 problems, it raises suitable exceptions. If you need to load
851 the image after using this method, you must reopen the image
852 file.
853 """
854 pass
856 def convert(
857 self, mode=None, matrix=None, dither=None, palette=Palette.WEB, colors=256
858 ):
859 """
860 Returns a converted copy of this image. For the "P" mode, this
861 method translates pixels through the palette. If mode is
862 omitted, a mode is chosen so that all information in the image
863 and the palette can be represented without a palette.
865 The current version supports all possible conversions between
866 "L", "RGB" and "CMYK." The ``matrix`` argument only supports "L"
867 and "RGB".
869 When translating a color image to greyscale (mode "L"),
870 the library uses the ITU-R 601-2 luma transform::
872 L = R * 299/1000 + G * 587/1000 + B * 114/1000
874 The default method of converting a greyscale ("L") or "RGB"
875 image into a bilevel (mode "1") image uses Floyd-Steinberg
876 dither to approximate the original image luminosity levels. If
877 dither is ``None``, all values larger than 127 are set to 255 (white),
878 all other values to 0 (black). To use other thresholds, use the
879 :py:meth:`~PIL.Image.Image.point` method.
881 When converting from "RGBA" to "P" without a ``matrix`` argument,
882 this passes the operation to :py:meth:`~PIL.Image.Image.quantize`,
883 and ``dither`` and ``palette`` are ignored.
885 :param mode: The requested mode. See: :ref:`concept-modes`.
886 :param matrix: An optional conversion matrix. If given, this
887 should be 4- or 12-tuple containing floating point values.
888 :param dither: Dithering method, used when converting from
889 mode "RGB" to "P" or from "RGB" or "L" to "1".
890 Available methods are :data:`Dither.NONE` or :data:`Dither.FLOYDSTEINBERG`
891 (default). Note that this is not used when ``matrix`` is supplied.
892 :param palette: Palette to use when converting from mode "RGB"
893 to "P". Available palettes are :data:`Palette.WEB` or
894 :data:`Palette.ADAPTIVE`.
895 :param colors: Number of colors to use for the :data:`Palette.ADAPTIVE`
896 palette. Defaults to 256.
897 :rtype: :py:class:`~PIL.Image.Image`
898 :returns: An :py:class:`~PIL.Image.Image` object.
899 """
901 self.load()
903 has_transparency = self.info.get("transparency") is not None
904 if not mode and self.mode == "P": 904 ↛ 906line 904 didn't jump to line 906, because the condition on line 904 was never true
905 # determine default mode
906 if self.palette:
907 mode = self.palette.mode
908 else:
909 mode = "RGB"
910 if mode == "RGB" and has_transparency:
911 mode = "RGBA"
912 if not mode or (mode == self.mode and not matrix): 912 ↛ 913line 912 didn't jump to line 913, because the condition on line 912 was never true
913 return self.copy()
915 if matrix: 915 ↛ 917line 915 didn't jump to line 917, because the condition on line 915 was never true
916 # matrix conversion
917 if mode not in ("L", "RGB"):
918 raise ValueError("illegal conversion")
919 im = self.im.convert_matrix(mode, matrix)
920 new = self._new(im)
921 if has_transparency and self.im.bands == 3:
922 transparency = new.info["transparency"]
924 def convert_transparency(m, v):
925 v = m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3] * 0.5
926 return max(0, min(255, int(v)))
928 if mode == "L":
929 transparency = convert_transparency(matrix, transparency)
930 elif len(mode) == 3:
931 transparency = tuple(
932 convert_transparency(matrix[i * 4 : i * 4 + 4], transparency)
933 for i in range(0, len(transparency))
934 )
935 new.info["transparency"] = transparency
936 return new
938 if mode == "P" and self.mode == "RGBA": 938 ↛ 939line 938 didn't jump to line 939, because the condition on line 938 was never true
939 return self.quantize(colors)
941 trns = None
942 delete_trns = False
943 # transparency handling
944 if has_transparency: 944 ↛ 945line 944 didn't jump to line 945, because the condition on line 944 was never true
945 if (self.mode in ("1", "L", "I") and mode in ("LA", "RGBA")) or (
946 self.mode == "RGB" and mode == "RGBA"
947 ):
948 # Use transparent conversion to promote from transparent
949 # color to an alpha channel.
950 new_im = self._new(
951 self.im.convert_transparent(mode, self.info["transparency"])
952 )
953 del new_im.info["transparency"]
954 return new_im
955 elif self.mode in ("L", "RGB", "P") and mode in ("L", "RGB", "P"):
956 t = self.info["transparency"]
957 if isinstance(t, bytes):
958 # Dragons. This can't be represented by a single color
959 warnings.warn(
960 "Palette images with Transparency expressed in bytes should be "
961 "converted to RGBA images"
962 )
963 delete_trns = True
964 else:
965 # get the new transparency color.
966 # use existing conversions
967 trns_im = Image()._new(core.new(self.mode, (1, 1)))
968 if self.mode == "P":
969 trns_im.putpalette(self.palette)
970 if isinstance(t, tuple):
971 err = "Couldn't allocate a palette color for transparency"
972 try:
973 t = trns_im.palette.getcolor(t, self)
974 except ValueError as e:
975 if str(e) == "cannot allocate more than 256 colors":
976 # If all 256 colors are in use,
977 # then there is no need for transparency
978 t = None
979 else:
980 raise ValueError(err) from e
981 if t is None:
982 trns = None
983 else:
984 trns_im.putpixel((0, 0), t)
986 if mode in ("L", "RGB"):
987 trns_im = trns_im.convert(mode)
988 else:
989 # can't just retrieve the palette number, got to do it
990 # after quantization.
991 trns_im = trns_im.convert("RGB")
992 trns = trns_im.getpixel((0, 0))
994 elif self.mode == "P" and mode in ("LA", "PA", "RGBA"):
995 t = self.info["transparency"]
996 delete_trns = True
998 if isinstance(t, bytes):
999 self.im.putpalettealphas(t)
1000 elif isinstance(t, int):
1001 self.im.putpalettealpha(t, 0)
1002 else:
1003 raise ValueError("Transparency for P mode should be bytes or int")
1005 if mode == "P" and palette == Palette.ADAPTIVE: 1005 ↛ 1006line 1005 didn't jump to line 1006, because the condition on line 1005 was never true
1006 im = self.im.quantize(colors)
1007 new = self._new(im)
1008 from . import ImagePalette
1010 new.palette = ImagePalette.ImagePalette("RGB", new.im.getpalette("RGB"))
1011 if delete_trns:
1012 # This could possibly happen if we requantize to fewer colors.
1013 # The transparency would be totally off in that case.
1014 del new.info["transparency"]
1015 if trns is not None:
1016 try:
1017 new.info["transparency"] = new.palette.getcolor(trns, new)
1018 except Exception:
1019 # if we can't make a transparent color, don't leave the old
1020 # transparency hanging around to mess us up.
1021 del new.info["transparency"]
1022 warnings.warn("Couldn't allocate palette entry for transparency")
1023 return new
1025 # colorspace conversion
1026 if dither is None: 1026 ↛ 1029line 1026 didn't jump to line 1029, because the condition on line 1026 was never false
1027 dither = Dither.FLOYDSTEINBERG
1029 try:
1030 im = self.im.convert(mode, dither)
1031 except ValueError:
1032 try:
1033 # normalize source image and try again
1034 im = self.im.convert(getmodebase(self.mode))
1035 im = im.convert(mode, dither)
1036 except KeyError as e:
1037 raise ValueError("illegal conversion") from e
1039 new_im = self._new(im)
1040 if mode == "P" and palette != Palette.ADAPTIVE: 1040 ↛ 1041line 1040 didn't jump to line 1041, because the condition on line 1040 was never true
1041 from . import ImagePalette
1043 new_im.palette = ImagePalette.ImagePalette("RGB", list(range(256)) * 3)
1044 if delete_trns: 1044 ↛ 1046line 1044 didn't jump to line 1046, because the condition on line 1044 was never true
1045 # crash fail if we leave a bytes transparency in an rgb/l mode.
1046 del new_im.info["transparency"]
1047 if trns is not None: 1047 ↛ 1048line 1047 didn't jump to line 1048, because the condition on line 1047 was never true
1048 if new_im.mode == "P":
1049 try:
1050 new_im.info["transparency"] = new_im.palette.getcolor(trns, new_im)
1051 except ValueError as e:
1052 del new_im.info["transparency"]
1053 if str(e) != "cannot allocate more than 256 colors":
1054 # If all 256 colors are in use,
1055 # then there is no need for transparency
1056 warnings.warn(
1057 "Couldn't allocate palette entry for transparency"
1058 )
1059 else:
1060 new_im.info["transparency"] = trns
1061 return new_im
1063 def quantize(
1064 self,
1065 colors=256,
1066 method=None,
1067 kmeans=0,
1068 palette=None,
1069 dither=Dither.FLOYDSTEINBERG,
1070 ):
1071 """
1072 Convert the image to 'P' mode with the specified number
1073 of colors.
1075 :param colors: The desired number of colors, <= 256
1076 :param method: :data:`Quantize.MEDIANCUT` (median cut),
1077 :data:`Quantize.MAXCOVERAGE` (maximum coverage),
1078 :data:`Quantize.FASTOCTREE` (fast octree),
1079 :data:`Quantize.LIBIMAGEQUANT` (libimagequant; check support
1080 using :py:func:`PIL.features.check_feature` with
1081 ``feature="libimagequant"``).
1083 By default, :data:`Quantize.MEDIANCUT` will be used.
1085 The exception to this is RGBA images. :data:`Quantize.MEDIANCUT`
1086 and :data:`Quantize.MAXCOVERAGE` do not support RGBA images, so
1087 :data:`Quantize.FASTOCTREE` is used by default instead.
1088 :param kmeans: Integer
1089 :param palette: Quantize to the palette of given
1090 :py:class:`PIL.Image.Image`.
1091 :param dither: Dithering method, used when converting from
1092 mode "RGB" to "P" or from "RGB" or "L" to "1".
1093 Available methods are :data:`Dither.NONE` or :data:`Dither.FLOYDSTEINBERG`
1094 (default).
1095 :returns: A new image
1097 """
1099 self.load()
1101 if method is None:
1102 # defaults:
1103 method = Quantize.MEDIANCUT
1104 if self.mode == "RGBA":
1105 method = Quantize.FASTOCTREE
1107 if self.mode == "RGBA" and method not in (
1108 Quantize.FASTOCTREE,
1109 Quantize.LIBIMAGEQUANT,
1110 ):
1111 # Caller specified an invalid mode.
1112 raise ValueError(
1113 "Fast Octree (method == 2) and libimagequant (method == 3) "
1114 "are the only valid methods for quantizing RGBA images"
1115 )
1117 if palette:
1118 # use palette from reference image
1119 palette.load()
1120 if palette.mode != "P":
1121 raise ValueError("bad mode for palette image")
1122 if self.mode != "RGB" and self.mode != "L":
1123 raise ValueError(
1124 "only RGB or L mode images can be quantized to a palette"
1125 )
1126 im = self.im.convert("P", dither, palette.im)
1127 new_im = self._new(im)
1128 new_im.palette = palette.palette.copy()
1129 return new_im
1131 im = self._new(self.im.quantize(colors, method, kmeans))
1133 from . import ImagePalette
1135 mode = im.im.getpalettemode()
1136 palette = im.im.getpalette(mode, mode)[: colors * len(mode)]
1137 im.palette = ImagePalette.ImagePalette(mode, palette)
1139 return im
1141 def copy(self):
1142 """
1143 Copies this image. Use this method if you wish to paste things
1144 into an image, but still retain the original.
1146 :rtype: :py:class:`~PIL.Image.Image`
1147 :returns: An :py:class:`~PIL.Image.Image` object.
1148 """
1149 self.load()
1150 return self._new(self.im.copy())
1152 __copy__ = copy
1154 def crop(self, box=None):
1155 """
1156 Returns a rectangular region from this image. The box is a
1157 4-tuple defining the left, upper, right, and lower pixel
1158 coordinate. See :ref:`coordinate-system`.
1160 Note: Prior to Pillow 3.4.0, this was a lazy operation.
1162 :param box: The crop rectangle, as a (left, upper, right, lower)-tuple.
1163 :rtype: :py:class:`~PIL.Image.Image`
1164 :returns: An :py:class:`~PIL.Image.Image` object.
1165 """
1167 if box is None:
1168 return self.copy()
1170 if box[2] < box[0]:
1171 raise ValueError("Coordinate 'right' is less than 'left'")
1172 elif box[3] < box[1]:
1173 raise ValueError("Coordinate 'lower' is less than 'upper'")
1175 self.load()
1176 return self._new(self._crop(self.im, box))
1178 def _crop(self, im, box):
1179 """
1180 Returns a rectangular region from the core image object im.
1182 This is equivalent to calling im.crop((x0, y0, x1, y1)), but
1183 includes additional sanity checks.
1185 :param im: a core image object
1186 :param box: The crop rectangle, as a (left, upper, right, lower)-tuple.
1187 :returns: A core image object.
1188 """
1190 x0, y0, x1, y1 = map(int, map(round, box))
1192 absolute_values = (abs(x1 - x0), abs(y1 - y0))
1194 _decompression_bomb_check(absolute_values)
1196 return im.crop((x0, y0, x1, y1))
1198 def draft(self, mode, size):
1199 """
1200 Configures the image file loader so it returns a version of the
1201 image that as closely as possible matches the given mode and
1202 size. For example, you can use this method to convert a color
1203 JPEG to greyscale while loading it.
1205 If any changes are made, returns a tuple with the chosen ``mode`` and
1206 ``box`` with coordinates of the original image within the altered one.
1208 Note that this method modifies the :py:class:`~PIL.Image.Image` object
1209 in place. If the image has already been loaded, this method has no
1210 effect.
1212 Note: This method is not implemented for most images. It is
1213 currently implemented only for JPEG and MPO images.
1215 :param mode: The requested mode.
1216 :param size: The requested size.
1217 """
1218 pass
1220 def _expand(self, xmargin, ymargin=None):
1221 if ymargin is None:
1222 ymargin = xmargin
1223 self.load()
1224 return self._new(self.im.expand(xmargin, ymargin, 0))
1226 def filter(self, filter):
1227 """
1228 Filters this image using the given filter. For a list of
1229 available filters, see the :py:mod:`~PIL.ImageFilter` module.
1231 :param filter: Filter kernel.
1232 :returns: An :py:class:`~PIL.Image.Image` object."""
1234 from . import ImageFilter
1236 self.load()
1238 if isinstance(filter, Callable):
1239 filter = filter()
1240 if not hasattr(filter, "filter"):
1241 raise TypeError(
1242 "filter argument should be ImageFilter.Filter instance or class"
1243 )
1245 multiband = isinstance(filter, ImageFilter.MultibandFilter)
1246 if self.im.bands == 1 or multiband:
1247 return self._new(filter.filter(self.im))
1249 ims = []
1250 for c in range(self.im.bands):
1251 ims.append(self._new(filter.filter(self.im.getband(c))))
1252 return merge(self.mode, ims)
1254 def getbands(self):
1255 """
1256 Returns a tuple containing the name of each band in this image.
1257 For example, ``getbands`` on an RGB image returns ("R", "G", "B").
1259 :returns: A tuple containing band names.
1260 :rtype: tuple
1261 """
1262 return ImageMode.getmode(self.mode).bands
1264 def getbbox(self):
1265 """
1266 Calculates the bounding box of the non-zero regions in the
1267 image.
1269 :returns: The bounding box is returned as a 4-tuple defining the
1270 left, upper, right, and lower pixel coordinate. See
1271 :ref:`coordinate-system`. If the image is completely empty, this
1272 method returns None.
1274 """
1276 self.load()
1277 return self.im.getbbox()
1279 def getcolors(self, maxcolors=256):
1280 """
1281 Returns a list of colors used in this image.
1283 The colors will be in the image's mode. For example, an RGB image will
1284 return a tuple of (red, green, blue) color values, and a P image will
1285 return the index of the color in the palette.
1287 :param maxcolors: Maximum number of colors. If this number is
1288 exceeded, this method returns None. The default limit is
1289 256 colors.
1290 :returns: An unsorted list of (count, pixel) values.
1291 """
1293 self.load()
1294 if self.mode in ("1", "L", "P"):
1295 h = self.im.histogram()
1296 out = []
1297 for i in range(256):
1298 if h[i]:
1299 out.append((h[i], i))
1300 if len(out) > maxcolors:
1301 return None
1302 return out
1303 return self.im.getcolors(maxcolors)
1305 def getdata(self, band=None):
1306 """
1307 Returns the contents of this image as a sequence object
1308 containing pixel values. The sequence object is flattened, so
1309 that values for line one follow directly after the values of
1310 line zero, and so on.
1312 Note that the sequence object returned by this method is an
1313 internal PIL data type, which only supports certain sequence
1314 operations. To convert it to an ordinary sequence (e.g. for
1315 printing), use ``list(im.getdata())``.
1317 :param band: What band to return. The default is to return
1318 all bands. To return a single band, pass in the index
1319 value (e.g. 0 to get the "R" band from an "RGB" image).
1320 :returns: A sequence-like object.
1321 """
1323 self.load()
1324 if band is not None:
1325 return self.im.getband(band)
1326 return self.im # could be abused
1328 def getextrema(self):
1329 """
1330 Gets the minimum and maximum pixel values for each band in
1331 the image.
1333 :returns: For a single-band image, a 2-tuple containing the
1334 minimum and maximum pixel value. For a multi-band image,
1335 a tuple containing one 2-tuple for each band.
1336 """
1338 self.load()
1339 if self.im.bands > 1:
1340 extrema = []
1341 for i in range(self.im.bands):
1342 extrema.append(self.im.getband(i).getextrema())
1343 return tuple(extrema)
1344 return self.im.getextrema()
1346 def _getxmp(self, xmp_tags):
1347 def get_name(tag):
1348 return tag.split("}")[1]
1350 def get_value(element):
1351 value = {get_name(k): v for k, v in element.attrib.items()}
1352 children = list(element)
1353 if children:
1354 for child in children:
1355 name = get_name(child.tag)
1356 child_value = get_value(child)
1357 if name in value:
1358 if not isinstance(value[name], list):
1359 value[name] = [value[name]]
1360 value[name].append(child_value)
1361 else:
1362 value[name] = child_value
1363 elif value:
1364 if element.text:
1365 value["text"] = element.text
1366 else:
1367 return element.text
1368 return value
1370 if ElementTree is None:
1371 warnings.warn("XMP data cannot be read without defusedxml dependency")
1372 return {}
1373 else:
1374 root = ElementTree.fromstring(xmp_tags)
1375 return {get_name(root.tag): get_value(root)}
1377 def getexif(self):
1378 if self._exif is None:
1379 self._exif = Exif()
1380 self._exif._loaded = False
1381 elif self._exif._loaded:
1382 return self._exif
1383 self._exif._loaded = True
1385 exif_info = self.info.get("exif")
1386 if exif_info is None:
1387 if "Raw profile type exif" in self.info:
1388 exif_info = bytes.fromhex(
1389 "".join(self.info["Raw profile type exif"].split("\n")[3:])
1390 )
1391 elif hasattr(self, "tag_v2"):
1392 self._exif.bigtiff = self.tag_v2._bigtiff
1393 self._exif.endian = self.tag_v2._endian
1394 self._exif.load_from_fp(self.fp, self.tag_v2._offset)
1395 if exif_info is not None:
1396 self._exif.load(exif_info)
1398 # XMP tags
1399 if 0x0112 not in self._exif:
1400 xmp_tags = self.info.get("XML:com.adobe.xmp")
1401 if xmp_tags:
1402 match = re.search(r'tiff:Orientation="([0-9])"', xmp_tags)
1403 if match:
1404 self._exif[0x0112] = int(match[1])
1406 return self._exif
1408 def _reload_exif(self):
1409 if self._exif is None or not self._exif._loaded:
1410 return
1411 self._exif._loaded = False
1412 self.getexif()
1414 def getim(self):
1415 """
1416 Returns a capsule that points to the internal image memory.
1418 :returns: A capsule object.
1419 """
1421 self.load()
1422 return self.im.ptr
1424 def getpalette(self, rawmode="RGB"):
1425 """
1426 Returns the image palette as a list.
1428 :param rawmode: The mode in which to return the palette. ``None`` will
1429 return the palette in its current mode.
1431 .. versionadded:: 9.1.0
1433 :returns: A list of color values [r, g, b, ...], or None if the
1434 image has no palette.
1435 """
1437 self.load()
1438 try:
1439 mode = self.im.getpalettemode()
1440 except ValueError:
1441 return None # no palette
1442 if rawmode is None:
1443 rawmode = mode
1444 return list(self.im.getpalette(mode, rawmode))
1446 def apply_transparency(self):
1447 """
1448 If a P mode image has a "transparency" key in the info dictionary,
1449 remove the key and apply the transparency to the palette instead.
1450 """
1451 if self.mode != "P" or "transparency" not in self.info:
1452 return
1454 from . import ImagePalette
1456 palette = self.getpalette("RGBA")
1457 transparency = self.info["transparency"]
1458 if isinstance(transparency, bytes):
1459 for i, alpha in enumerate(transparency):
1460 palette[i * 4 + 3] = alpha
1461 else:
1462 palette[transparency * 4 + 3] = 0
1463 self.palette = ImagePalette.ImagePalette("RGBA", bytes(palette))
1464 self.palette.dirty = 1
1466 del self.info["transparency"]
1468 def getpixel(self, xy):
1469 """
1470 Returns the pixel value at a given position.
1472 :param xy: The coordinate, given as (x, y). See
1473 :ref:`coordinate-system`.
1474 :returns: The pixel value. If the image is a multi-layer image,
1475 this method returns a tuple.
1476 """
1478 self.load()
1479 if self.pyaccess:
1480 return self.pyaccess.getpixel(xy)
1481 return self.im.getpixel(xy)
1483 def getprojection(self):
1484 """
1485 Get projection to x and y axes
1487 :returns: Two sequences, indicating where there are non-zero
1488 pixels along the X-axis and the Y-axis, respectively.
1489 """
1491 self.load()
1492 x, y = self.im.getprojection()
1493 return list(x), list(y)
1495 def histogram(self, mask=None, extrema=None):
1496 """
1497 Returns a histogram for the image. The histogram is returned as a
1498 list of pixel counts, one for each pixel value in the source
1499 image. Counts are grouped into 256 bins for each band, even if
1500 the image has more than 8 bits per band. If the image has more
1501 than one band, the histograms for all bands are concatenated (for
1502 example, the histogram for an "RGB" image contains 768 values).
1504 A bilevel image (mode "1") is treated as a greyscale ("L") image
1505 by this method.
1507 If a mask is provided, the method returns a histogram for those
1508 parts of the image where the mask image is non-zero. The mask
1509 image must have the same size as the image, and be either a
1510 bi-level image (mode "1") or a greyscale image ("L").
1512 :param mask: An optional mask.
1513 :param extrema: An optional tuple of manually-specified extrema.
1514 :returns: A list containing pixel counts.
1515 """
1516 self.load()
1517 if mask:
1518 mask.load()
1519 return self.im.histogram((0, 0), mask.im)
1520 if self.mode in ("I", "F"):
1521 if extrema is None:
1522 extrema = self.getextrema()
1523 return self.im.histogram(extrema)
1524 return self.im.histogram()
1526 def entropy(self, mask=None, extrema=None):
1527 """
1528 Calculates and returns the entropy for the image.
1530 A bilevel image (mode "1") is treated as a greyscale ("L")
1531 image by this method.
1533 If a mask is provided, the method employs the histogram for
1534 those parts of the image where the mask image is non-zero.
1535 The mask image must have the same size as the image, and be
1536 either a bi-level image (mode "1") or a greyscale image ("L").
1538 :param mask: An optional mask.
1539 :param extrema: An optional tuple of manually-specified extrema.
1540 :returns: A float value representing the image entropy
1541 """
1542 self.load()
1543 if mask:
1544 mask.load()
1545 return self.im.entropy((0, 0), mask.im)
1546 if self.mode in ("I", "F"):
1547 if extrema is None:
1548 extrema = self.getextrema()
1549 return self.im.entropy(extrema)
1550 return self.im.entropy()
1552 def paste(self, im, box=None, mask=None):
1553 """
1554 Pastes another image into this image. The box argument is either
1555 a 2-tuple giving the upper left corner, a 4-tuple defining the
1556 left, upper, right, and lower pixel coordinate, or None (same as
1557 (0, 0)). See :ref:`coordinate-system`. If a 4-tuple is given, the size
1558 of the pasted image must match the size of the region.
1560 If the modes don't match, the pasted image is converted to the mode of
1561 this image (see the :py:meth:`~PIL.Image.Image.convert` method for
1562 details).
1564 Instead of an image, the source can be a integer or tuple
1565 containing pixel values. The method then fills the region
1566 with the given color. When creating RGB images, you can
1567 also use color strings as supported by the ImageColor module.
1569 If a mask is given, this method updates only the regions
1570 indicated by the mask. You can use either "1", "L", "LA", "RGBA"
1571 or "RGBa" images (if present, the alpha band is used as mask).
1572 Where the mask is 255, the given image is copied as is. Where
1573 the mask is 0, the current value is preserved. Intermediate
1574 values will mix the two images together, including their alpha
1575 channels if they have them.
1577 See :py:meth:`~PIL.Image.Image.alpha_composite` if you want to
1578 combine images with respect to their alpha channels.
1580 :param im: Source image or pixel value (integer or tuple).
1581 :param box: An optional 4-tuple giving the region to paste into.
1582 If a 2-tuple is used instead, it's treated as the upper left
1583 corner. If omitted or None, the source is pasted into the
1584 upper left corner.
1586 If an image is given as the second argument and there is no
1587 third, the box defaults to (0, 0), and the second argument
1588 is interpreted as a mask image.
1589 :param mask: An optional mask image.
1590 """
1592 if isImageType(box) and mask is None: 1592 ↛ 1594line 1592 didn't jump to line 1594, because the condition on line 1592 was never true
1593 # abbreviated paste(im, mask) syntax
1594 mask = box
1595 box = None
1597 if box is None: 1597 ↛ 1600line 1597 didn't jump to line 1600, because the condition on line 1597 was never false
1598 box = (0, 0)
1600 if len(box) == 2: 1600 ↛ 1611line 1600 didn't jump to line 1611, because the condition on line 1600 was never false
1601 # upper left corner given; get size from image or mask
1602 if isImageType(im): 1602 ↛ 1604line 1602 didn't jump to line 1604, because the condition on line 1602 was never false
1603 size = im.size
1604 elif isImageType(mask):
1605 size = mask.size
1606 else:
1607 # FIXME: use self.size here?
1608 raise ValueError("cannot determine region size; use 4-item box")
1609 box += (box[0] + size[0], box[1] + size[1])
1611 if isinstance(im, str): 1611 ↛ 1612line 1611 didn't jump to line 1612, because the condition on line 1611 was never true
1612 from . import ImageColor
1614 im = ImageColor.getcolor(im, self.mode)
1616 elif isImageType(im): 1616 ↛ 1624line 1616 didn't jump to line 1624, because the condition on line 1616 was never false
1617 im.load()
1618 if self.mode != im.mode: 1618 ↛ 1622line 1618 didn't jump to line 1622, because the condition on line 1618 was never false
1619 if self.mode != "RGB" or im.mode not in ("LA", "RGBA", "RGBa"): 1619 ↛ 1622line 1619 didn't jump to line 1622, because the condition on line 1619 was never false
1620 # should use an adapter for this!
1621 im = im.convert(self.mode)
1622 im = im.im
1624 self._ensure_mutable()
1626 if mask: 1626 ↛ 1627line 1626 didn't jump to line 1627, because the condition on line 1626 was never true
1627 mask.load()
1628 self.im.paste(im, box, mask.im)
1629 else:
1630 self.im.paste(im, box)
1632 def alpha_composite(self, im, dest=(0, 0), source=(0, 0)):
1633 """'In-place' analog of Image.alpha_composite. Composites an image
1634 onto this image.
1636 :param im: image to composite over this one
1637 :param dest: Optional 2 tuple (left, top) specifying the upper
1638 left corner in this (destination) image.
1639 :param source: Optional 2 (left, top) tuple for the upper left
1640 corner in the overlay source image, or 4 tuple (left, top, right,
1641 bottom) for the bounds of the source rectangle
1643 Performance Note: Not currently implemented in-place in the core layer.
1644 """
1646 if not isinstance(source, (list, tuple)):
1647 raise ValueError("Source must be a tuple")
1648 if not isinstance(dest, (list, tuple)):
1649 raise ValueError("Destination must be a tuple")
1650 if not len(source) in (2, 4):
1651 raise ValueError("Source must be a 2 or 4-tuple")
1652 if not len(dest) == 2:
1653 raise ValueError("Destination must be a 2-tuple")
1654 if min(source) < 0:
1655 raise ValueError("Source must be non-negative")
1657 if len(source) == 2:
1658 source = source + im.size
1660 # over image, crop if it's not the whole thing.
1661 if source == (0, 0) + im.size:
1662 overlay = im
1663 else:
1664 overlay = im.crop(source)
1666 # target for the paste
1667 box = dest + (dest[0] + overlay.width, dest[1] + overlay.height)
1669 # destination image. don't copy if we're using the whole image.
1670 if box == (0, 0) + self.size:
1671 background = self
1672 else:
1673 background = self.crop(box)
1675 result = alpha_composite(background, overlay)
1676 self.paste(result, box)
1678 def point(self, lut, mode=None):
1679 """
1680 Maps this image through a lookup table or function.
1682 :param lut: A lookup table, containing 256 (or 65536 if
1683 self.mode=="I" and mode == "L") values per band in the
1684 image. A function can be used instead, it should take a
1685 single argument. The function is called once for each
1686 possible pixel value, and the resulting table is applied to
1687 all bands of the image.
1689 It may also be an :py:class:`~PIL.Image.ImagePointHandler`
1690 object::
1692 class Example(Image.ImagePointHandler):
1693 def point(self, data):
1694 # Return result
1695 :param mode: Output mode (default is same as input). In the
1696 current version, this can only be used if the source image
1697 has mode "L" or "P", and the output has mode "1" or the
1698 source image mode is "I" and the output mode is "L".
1699 :returns: An :py:class:`~PIL.Image.Image` object.
1700 """
1702 self.load()
1704 if isinstance(lut, ImagePointHandler):
1705 return lut.point(self)
1707 if callable(lut):
1708 # if it isn't a list, it should be a function
1709 if self.mode in ("I", "I;16", "F"):
1710 # check if the function can be used with point_transform
1711 # UNDONE wiredfool -- I think this prevents us from ever doing
1712 # a gamma function point transform on > 8bit images.
1713 scale, offset = _getscaleoffset(lut)
1714 return self._new(self.im.point_transform(scale, offset))
1715 # for other modes, convert the function to a table
1716 lut = [lut(i) for i in range(256)] * self.im.bands
1718 if self.mode == "F":
1719 # FIXME: _imaging returns a confusing error message for this case
1720 raise ValueError("point operation not supported for this mode")
1722 if mode != "F":
1723 lut = [round(i) for i in lut]
1724 return self._new(self.im.point(lut, mode))
1726 def putalpha(self, alpha):
1727 """
1728 Adds or replaces the alpha layer in this image. If the image
1729 does not have an alpha layer, it's converted to "LA" or "RGBA".
1730 The new layer must be either "L" or "1".
1732 :param alpha: The new alpha layer. This can either be an "L" or "1"
1733 image having the same size as this image, or an integer or
1734 other color value.
1735 """
1737 self._ensure_mutable()
1739 if self.mode not in ("LA", "PA", "RGBA"):
1740 # attempt to promote self to a matching alpha mode
1741 try:
1742 mode = getmodebase(self.mode) + "A"
1743 try:
1744 self.im.setmode(mode)
1745 except (AttributeError, ValueError) as e:
1746 # do things the hard way
1747 im = self.im.convert(mode)
1748 if im.mode not in ("LA", "PA", "RGBA"):
1749 raise ValueError from e # sanity check
1750 self.im = im
1751 self.pyaccess = None
1752 self.mode = self.im.mode
1753 except KeyError as e:
1754 raise ValueError("illegal image mode") from e
1756 if self.mode in ("LA", "PA"):
1757 band = 1
1758 else:
1759 band = 3
1761 if isImageType(alpha):
1762 # alpha layer
1763 if alpha.mode not in ("1", "L"):
1764 raise ValueError("illegal image mode")
1765 alpha.load()
1766 if alpha.mode == "1":
1767 alpha = alpha.convert("L")
1768 else:
1769 # constant alpha
1770 try:
1771 self.im.fillband(band, alpha)
1772 except (AttributeError, ValueError):
1773 # do things the hard way
1774 alpha = new("L", self.size, alpha)
1775 else:
1776 return
1778 self.im.putband(alpha.im, band)
1780 def putdata(self, data, scale=1.0, offset=0.0):
1781 """
1782 Copies pixel data from a flattened sequence object into the image. The
1783 values should start at the upper left corner (0, 0), continue to the
1784 end of the line, followed directly by the first value of the second
1785 line, and so on. Data will be read until either the image or the
1786 sequence ends. The scale and offset values are used to adjust the
1787 sequence values: **pixel = value*scale + offset**.
1789 :param data: A flattened sequence object.
1790 :param scale: An optional scale value. The default is 1.0.
1791 :param offset: An optional offset value. The default is 0.0.
1792 """
1794 self._ensure_mutable()
1796 self.im.putdata(data, scale, offset)
1798 def putpalette(self, data, rawmode="RGB"):
1799 """
1800 Attaches a palette to this image. The image must be a "P", "PA", "L"
1801 or "LA" image.
1803 The palette sequence must contain at most 256 colors, made up of one
1804 integer value for each channel in the raw mode.
1805 For example, if the raw mode is "RGB", then it can contain at most 768
1806 values, made up of red, green and blue values for the corresponding pixel
1807 index in the 256 colors.
1808 If the raw mode is "RGBA", then it can contain at most 1024 values,
1809 containing red, green, blue and alpha values.
1811 Alternatively, an 8-bit string may be used instead of an integer sequence.
1813 :param data: A palette sequence (either a list or a string).
1814 :param rawmode: The raw mode of the palette. Either "RGB", "RGBA", or a mode
1815 that can be transformed to "RGB" or "RGBA" (e.g. "R", "BGR;15", "RGBA;L").
1816 """
1817 from . import ImagePalette
1819 if self.mode not in ("L", "LA", "P", "PA"): 1819 ↛ 1820line 1819 didn't jump to line 1820, because the condition on line 1819 was never true
1820 raise ValueError("illegal image mode")
1821 if isinstance(data, ImagePalette.ImagePalette): 1821 ↛ 1822line 1821 didn't jump to line 1822, because the condition on line 1821 was never true
1822 palette = ImagePalette.raw(data.rawmode, data.palette)
1823 else:
1824 if not isinstance(data, bytes): 1824 ↛ 1826line 1824 didn't jump to line 1826, because the condition on line 1824 was never false
1825 data = bytes(data)
1826 palette = ImagePalette.raw(rawmode, data)
1827 self.mode = "PA" if "A" in self.mode else "P"
1828 self.palette = palette
1829 self.palette.mode = "RGB"
1830 self.load() # install new palette
1832 def putpixel(self, xy, value):
1833 """
1834 Modifies the pixel at the given position. The color is given as
1835 a single numerical value for single-band images, and a tuple for
1836 multi-band images. In addition to this, RGB and RGBA tuples are
1837 accepted for P images.
1839 Note that this method is relatively slow. For more extensive changes,
1840 use :py:meth:`~PIL.Image.Image.paste` or the :py:mod:`~PIL.ImageDraw`
1841 module instead.
1843 See:
1845 * :py:meth:`~PIL.Image.Image.paste`
1846 * :py:meth:`~PIL.Image.Image.putdata`
1847 * :py:mod:`~PIL.ImageDraw`
1849 :param xy: The pixel coordinate, given as (x, y). See
1850 :ref:`coordinate-system`.
1851 :param value: The pixel value.
1852 """
1854 if self.readonly:
1855 self._copy()
1856 self.load()
1858 if self.pyaccess:
1859 return self.pyaccess.putpixel(xy, value)
1861 if (
1862 self.mode == "P"
1863 and isinstance(value, (list, tuple))
1864 and len(value) in [3, 4]
1865 ):
1866 # RGB or RGBA value for a P image
1867 value = self.palette.getcolor(value, self)
1868 return self.im.putpixel(xy, value)
1870 def remap_palette(self, dest_map, source_palette=None):
1871 """
1872 Rewrites the image to reorder the palette.
1874 :param dest_map: A list of indexes into the original palette.
1875 e.g. ``[1,0]`` would swap a two item palette, and ``list(range(256))``
1876 is the identity transform.
1877 :param source_palette: Bytes or None.
1878 :returns: An :py:class:`~PIL.Image.Image` object.
1880 """
1881 from . import ImagePalette
1883 if self.mode not in ("L", "P"):
1884 raise ValueError("illegal image mode")
1886 bands = 3
1887 palette_mode = "RGB"
1888 if source_palette is None:
1889 if self.mode == "P":
1890 self.load()
1891 palette_mode = self.im.getpalettemode()
1892 if palette_mode == "RGBA":
1893 bands = 4
1894 source_palette = self.im.getpalette(palette_mode, palette_mode)
1895 else: # L-mode
1896 source_palette = bytearray(i // 3 for i in range(768))
1898 palette_bytes = b""
1899 new_positions = [0] * 256
1901 # pick only the used colors from the palette
1902 for i, oldPosition in enumerate(dest_map):
1903 palette_bytes += source_palette[
1904 oldPosition * bands : oldPosition * bands + bands
1905 ]
1906 new_positions[oldPosition] = i
1908 # replace the palette color id of all pixel with the new id
1910 # Palette images are [0..255], mapped through a 1 or 3
1911 # byte/color map. We need to remap the whole image
1912 # from palette 1 to palette 2. New_positions is
1913 # an array of indexes into palette 1. Palette 2 is
1914 # palette 1 with any holes removed.
1916 # We're going to leverage the convert mechanism to use the
1917 # C code to remap the image from palette 1 to palette 2,
1918 # by forcing the source image into 'L' mode and adding a
1919 # mapping 'L' mode palette, then converting back to 'L'
1920 # sans palette thus converting the image bytes, then
1921 # assigning the optimized RGB palette.
1923 # perf reference, 9500x4000 gif, w/~135 colors
1924 # 14 sec prepatch, 1 sec postpatch with optimization forced.
1926 mapping_palette = bytearray(new_positions)
1928 m_im = self.copy()
1929 m_im.mode = "P"
1931 m_im.palette = ImagePalette.ImagePalette(
1932 palette_mode, palette=mapping_palette * bands
1933 )
1934 # possibly set palette dirty, then
1935 # m_im.putpalette(mapping_palette, 'L') # converts to 'P'
1936 # or just force it.
1937 # UNDONE -- this is part of the general issue with palettes
1938 m_im.im.putpalette(palette_mode + ";L", m_im.palette.tobytes())
1940 m_im = m_im.convert("L")
1942 # Internally, we require 256 palette entries.
1943 new_palette_bytes = (
1944 palette_bytes + ((256 * bands) - len(palette_bytes)) * b"\x00"
1945 )
1946 m_im.putpalette(new_palette_bytes, palette_mode)
1947 m_im.palette = ImagePalette.ImagePalette(palette_mode, palette=palette_bytes)
1949 if "transparency" in self.info:
1950 try:
1951 m_im.info["transparency"] = dest_map.index(self.info["transparency"])
1952 except ValueError:
1953 if "transparency" in m_im.info:
1954 del m_im.info["transparency"]
1956 return m_im
1958 def _get_safe_box(self, size, resample, box):
1959 """Expands the box so it includes adjacent pixels
1960 that may be used by resampling with the given resampling filter.
1961 """
1962 filter_support = _filters_support[resample] - 0.5
1963 scale_x = (box[2] - box[0]) / size[0]
1964 scale_y = (box[3] - box[1]) / size[1]
1965 support_x = filter_support * scale_x
1966 support_y = filter_support * scale_y
1968 return (
1969 max(0, int(box[0] - support_x)),
1970 max(0, int(box[1] - support_y)),
1971 min(self.size[0], math.ceil(box[2] + support_x)),
1972 min(self.size[1], math.ceil(box[3] + support_y)),
1973 )
1975 def resize(self, size, resample=None, box=None, reducing_gap=None):
1976 """
1977 Returns a resized copy of this image.
1979 :param size: The requested size in pixels, as a 2-tuple:
1980 (width, height).
1981 :param resample: An optional resampling filter. This can be
1982 one of :py:data:`PIL.Image.Resampling.NEAREST`,
1983 :py:data:`PIL.Image.Resampling.BOX`,
1984 :py:data:`PIL.Image.Resampling.BILINEAR`,
1985 :py:data:`PIL.Image.Resampling.HAMMING`,
1986 :py:data:`PIL.Image.Resampling.BICUBIC` or
1987 :py:data:`PIL.Image.Resampling.LANCZOS`.
1988 If the image has mode "1" or "P", it is always set to
1989 :py:data:`PIL.Image.Resampling.NEAREST`.
1990 If the image mode specifies a number of bits, such as "I;16", then the
1991 default filter is :py:data:`PIL.Image.Resampling.NEAREST`.
1992 Otherwise, the default filter is
1993 :py:data:`PIL.Image.Resampling.BICUBIC`. See: :ref:`concept-filters`.
1994 :param box: An optional 4-tuple of floats providing
1995 the source image region to be scaled.
1996 The values must be within (0, 0, width, height) rectangle.
1997 If omitted or None, the entire source is used.
1998 :param reducing_gap: Apply optimization by resizing the image
1999 in two steps. First, reducing the image by integer times
2000 using :py:meth:`~PIL.Image.Image.reduce`.
2001 Second, resizing using regular resampling. The last step
2002 changes size no less than by ``reducing_gap`` times.
2003 ``reducing_gap`` may be None (no first step is performed)
2004 or should be greater than 1.0. The bigger ``reducing_gap``,
2005 the closer the result to the fair resampling.
2006 The smaller ``reducing_gap``, the faster resizing.
2007 With ``reducing_gap`` greater or equal to 3.0, the result is
2008 indistinguishable from fair resampling in most cases.
2009 The default value is None (no optimization).
2010 :returns: An :py:class:`~PIL.Image.Image` object.
2011 """
2013 if resample is None:
2014 type_special = ";" in self.mode
2015 resample = Resampling.NEAREST if type_special else Resampling.BICUBIC
2016 elif resample not in (
2017 Resampling.NEAREST,
2018 Resampling.BILINEAR,
2019 Resampling.BICUBIC,
2020 Resampling.LANCZOS,
2021 Resampling.BOX,
2022 Resampling.HAMMING,
2023 ):
2024 message = f"Unknown resampling filter ({resample})."
2026 filters = [
2027 f"{filter[1]} ({filter[0]})"
2028 for filter in (
2029 (Resampling.NEAREST, "Image.Resampling.NEAREST"),
2030 (Resampling.LANCZOS, "Image.Resampling.LANCZOS"),
2031 (Resampling.BILINEAR, "Image.Resampling.BILINEAR"),
2032 (Resampling.BICUBIC, "Image.Resampling.BICUBIC"),
2033 (Resampling.BOX, "Image.Resampling.BOX"),
2034 (Resampling.HAMMING, "Image.Resampling.HAMMING"),
2035 )
2036 ]
2037 raise ValueError(
2038 message + " Use " + ", ".join(filters[:-1]) + " or " + filters[-1]
2039 )
2041 if reducing_gap is not None and reducing_gap < 1.0:
2042 raise ValueError("reducing_gap must be 1.0 or greater")
2044 size = tuple(size)
2046 self.load()
2047 if box is None:
2048 box = (0, 0) + self.size
2049 else:
2050 box = tuple(box)
2052 if self.size == size and box == (0, 0) + self.size:
2053 return self.copy()
2055 if self.mode in ("1", "P"):
2056 resample = Resampling.NEAREST
2058 if self.mode in ["LA", "RGBA"] and resample != Resampling.NEAREST:
2059 im = self.convert({"LA": "La", "RGBA": "RGBa"}[self.mode])
2060 im = im.resize(size, resample, box)
2061 return im.convert(self.mode)
2063 self.load()
2065 if reducing_gap is not None and resample != Resampling.NEAREST:
2066 factor_x = int((box[2] - box[0]) / size[0] / reducing_gap) or 1
2067 factor_y = int((box[3] - box[1]) / size[1] / reducing_gap) or 1
2068 if factor_x > 1 or factor_y > 1:
2069 reduce_box = self._get_safe_box(size, resample, box)
2070 factor = (factor_x, factor_y)
2071 if callable(self.reduce):
2072 self = self.reduce(factor, box=reduce_box)
2073 else:
2074 self = Image.reduce(self, factor, box=reduce_box)
2075 box = (
2076 (box[0] - reduce_box[0]) / factor_x,
2077 (box[1] - reduce_box[1]) / factor_y,
2078 (box[2] - reduce_box[0]) / factor_x,
2079 (box[3] - reduce_box[1]) / factor_y,
2080 )
2082 return self._new(self.im.resize(size, resample, box))
2084 def reduce(self, factor, box=None):
2085 """
2086 Returns a copy of the image reduced ``factor`` times.
2087 If the size of the image is not dividable by ``factor``,
2088 the resulting size will be rounded up.
2090 :param factor: A greater than 0 integer or tuple of two integers
2091 for width and height separately.
2092 :param box: An optional 4-tuple of ints providing
2093 the source image region to be reduced.
2094 The values must be within ``(0, 0, width, height)`` rectangle.
2095 If omitted or ``None``, the entire source is used.
2096 """
2097 if not isinstance(factor, (list, tuple)):
2098 factor = (factor, factor)
2100 if box is None:
2101 box = (0, 0) + self.size
2102 else:
2103 box = tuple(box)
2105 if factor == (1, 1) and box == (0, 0) + self.size:
2106 return self.copy()
2108 if self.mode in ["LA", "RGBA"]:
2109 im = self.convert({"LA": "La", "RGBA": "RGBa"}[self.mode])
2110 im = im.reduce(factor, box)
2111 return im.convert(self.mode)
2113 self.load()
2115 return self._new(self.im.reduce(factor, box))
2117 def rotate(
2118 self,
2119 angle,
2120 resample=Resampling.NEAREST,
2121 expand=0,
2122 center=None,
2123 translate=None,
2124 fillcolor=None,
2125 ):
2126 """
2127 Returns a rotated copy of this image. This method returns a
2128 copy of this image, rotated the given number of degrees counter
2129 clockwise around its centre.
2131 :param angle: In degrees counter clockwise.
2132 :param resample: An optional resampling filter. This can be
2133 one of :py:data:`PIL.Image.Resampling.NEAREST` (use nearest neighbour),
2134 :py:data:`PIL.Image.BILINEAR` (linear interpolation in a 2x2
2135 environment), or :py:data:`PIL.Image.Resampling.BICUBIC`
2136 (cubic spline interpolation in a 4x4 environment).
2137 If omitted, or if the image has mode "1" or "P", it is
2138 set to :py:data:`PIL.Image.Resampling.NEAREST`. See :ref:`concept-filters`.
2139 :param expand: Optional expansion flag. If true, expands the output
2140 image to make it large enough to hold the entire rotated image.
2141 If false or omitted, make the output image the same size as the
2142 input image. Note that the expand flag assumes rotation around
2143 the center and no translation.
2144 :param center: Optional center of rotation (a 2-tuple). Origin is
2145 the upper left corner. Default is the center of the image.
2146 :param translate: An optional post-rotate translation (a 2-tuple).
2147 :param fillcolor: An optional color for area outside the rotated image.
2148 :returns: An :py:class:`~PIL.Image.Image` object.
2149 """
2151 angle = angle % 360.0
2153 # Fast paths regardless of filter, as long as we're not
2154 # translating or changing the center.
2155 if not (center or translate):
2156 if angle == 0:
2157 return self.copy()
2158 if angle == 180:
2159 return self.transpose(Transpose.ROTATE_180)
2160 if angle in (90, 270) and (expand or self.width == self.height):
2161 return self.transpose(
2162 Transpose.ROTATE_90 if angle == 90 else Transpose.ROTATE_270
2163 )
2165 # Calculate the affine matrix. Note that this is the reverse
2166 # transformation (from destination image to source) because we
2167 # want to interpolate the (discrete) destination pixel from
2168 # the local area around the (floating) source pixel.
2170 # The matrix we actually want (note that it operates from the right):
2171 # (1, 0, tx) (1, 0, cx) ( cos a, sin a, 0) (1, 0, -cx)
2172 # (0, 1, ty) * (0, 1, cy) * (-sin a, cos a, 0) * (0, 1, -cy)
2173 # (0, 0, 1) (0, 0, 1) ( 0, 0, 1) (0, 0, 1)
2175 # The reverse matrix is thus:
2176 # (1, 0, cx) ( cos -a, sin -a, 0) (1, 0, -cx) (1, 0, -tx)
2177 # (0, 1, cy) * (-sin -a, cos -a, 0) * (0, 1, -cy) * (0, 1, -ty)
2178 # (0, 0, 1) ( 0, 0, 1) (0, 0, 1) (0, 0, 1)
2180 # In any case, the final translation may be updated at the end to
2181 # compensate for the expand flag.
2183 w, h = self.size
2185 if translate is None:
2186 post_trans = (0, 0)
2187 else:
2188 post_trans = translate
2189 if center is None:
2190 # FIXME These should be rounded to ints?
2191 rotn_center = (w / 2.0, h / 2.0)
2192 else:
2193 rotn_center = center
2195 angle = -math.radians(angle)
2196 matrix = [
2197 round(math.cos(angle), 15),
2198 round(math.sin(angle), 15),
2199 0.0,
2200 round(-math.sin(angle), 15),
2201 round(math.cos(angle), 15),
2202 0.0,
2203 ]
2205 def transform(x, y, matrix):
2206 (a, b, c, d, e, f) = matrix
2207 return a * x + b * y + c, d * x + e * y + f
2209 matrix[2], matrix[5] = transform(
2210 -rotn_center[0] - post_trans[0], -rotn_center[1] - post_trans[1], matrix
2211 )
2212 matrix[2] += rotn_center[0]
2213 matrix[5] += rotn_center[1]
2215 if expand:
2216 # calculate output size
2217 xx = []
2218 yy = []
2219 for x, y in ((0, 0), (w, 0), (w, h), (0, h)):
2220 x, y = transform(x, y, matrix)
2221 xx.append(x)
2222 yy.append(y)
2223 nw = math.ceil(max(xx)) - math.floor(min(xx))
2224 nh = math.ceil(max(yy)) - math.floor(min(yy))
2226 # We multiply a translation matrix from the right. Because of its
2227 # special form, this is the same as taking the image of the
2228 # translation vector as new translation vector.
2229 matrix[2], matrix[5] = transform(-(nw - w) / 2.0, -(nh - h) / 2.0, matrix)
2230 w, h = nw, nh
2232 return self.transform(
2233 (w, h), Transform.AFFINE, matrix, resample, fillcolor=fillcolor
2234 )
2236 def save(self, fp, format=None, **params):
2237 """
2238 Saves this image under the given filename. If no format is
2239 specified, the format to use is determined from the filename
2240 extension, if possible.
2242 Keyword options can be used to provide additional instructions
2243 to the writer. If a writer doesn't recognise an option, it is
2244 silently ignored. The available options are described in the
2245 :doc:`image format documentation
2246 <../handbook/image-file-formats>` for each writer.
2248 You can use a file object instead of a filename. In this case,
2249 you must always specify the format. The file object must
2250 implement the ``seek``, ``tell``, and ``write``
2251 methods, and be opened in binary mode.
2253 :param fp: A filename (string), pathlib.Path object or file object.
2254 :param format: Optional format override. If omitted, the
2255 format to use is determined from the filename extension.
2256 If a file object was used instead of a filename, this
2257 parameter should always be used.
2258 :param params: Extra parameters to the image writer.
2259 :returns: None
2260 :exception ValueError: If the output format could not be determined
2261 from the file name. Use the format option to solve this.
2262 :exception OSError: If the file could not be written. The file
2263 may have been created, and may contain partial data.
2264 """
2266 filename = ""
2267 open_fp = False
2268 if isinstance(fp, Path): 2268 ↛ 2269line 2268 didn't jump to line 2269, because the condition on line 2268 was never true
2269 filename = str(fp)
2270 open_fp = True
2271 elif is_path(fp): 2271 ↛ 2272line 2271 didn't jump to line 2272, because the condition on line 2271 was never true
2272 filename = fp
2273 open_fp = True
2274 elif fp == sys.stdout: 2274 ↛ 2275line 2274 didn't jump to line 2275, because the condition on line 2274 was never true
2275 try:
2276 fp = sys.stdout.buffer
2277 except AttributeError:
2278 pass
2279 if not filename and hasattr(fp, "name") and is_path(fp.name): 2279 ↛ 2281line 2279 didn't jump to line 2281, because the condition on line 2279 was never true
2280 # only set the name for metadata purposes
2281 filename = fp.name
2283 # may mutate self!
2284 self._ensure_mutable()
2286 save_all = params.pop("save_all", False)
2287 self.encoderinfo = params
2288 self.encoderconfig = ()
2290 preinit()
2292 ext = os.path.splitext(filename)[1].lower()
2294 if not format: 2294 ↛ 2295line 2294 didn't jump to line 2295, because the condition on line 2294 was never true
2295 if ext not in EXTENSION:
2296 init()
2297 try:
2298 format = EXTENSION[ext]
2299 except KeyError as e:
2300 raise ValueError(f"unknown file extension: {ext}") from e
2302 if format.upper() not in SAVE: 2302 ↛ 2303line 2302 didn't jump to line 2303, because the condition on line 2302 was never true
2303 init()
2304 if save_all: 2304 ↛ 2305line 2304 didn't jump to line 2305, because the condition on line 2304 was never true
2305 save_handler = SAVE_ALL[format.upper()]
2306 else:
2307 save_handler = SAVE[format.upper()]
2309 created = False
2310 if open_fp: 2310 ↛ 2311line 2310 didn't jump to line 2311, because the condition on line 2310 was never true
2311 created = not os.path.exists(filename)
2312 if params.get("append", False):
2313 # Open also for reading ("+"), because TIFF save_all
2314 # writer needs to go back and edit the written data.
2315 fp = builtins.open(filename, "r+b")
2316 else:
2317 fp = builtins.open(filename, "w+b")
2319 try:
2320 save_handler(self, fp, filename)
2321 except Exception:
2322 if open_fp:
2323 fp.close()
2324 if created:
2325 try:
2326 os.remove(filename)
2327 except PermissionError:
2328 pass
2329 raise
2330 if open_fp: 2330 ↛ 2331line 2330 didn't jump to line 2331, because the condition on line 2330 was never true
2331 fp.close()
2333 def seek(self, frame):
2334 """
2335 Seeks to the given frame in this sequence file. If you seek
2336 beyond the end of the sequence, the method raises an
2337 ``EOFError`` exception. When a sequence file is opened, the
2338 library automatically seeks to frame 0.
2340 See :py:meth:`~PIL.Image.Image.tell`.
2342 If defined, :attr:`~PIL.Image.Image.n_frames` refers to the
2343 number of available frames.
2345 :param frame: Frame number, starting at 0.
2346 :exception EOFError: If the call attempts to seek beyond the end
2347 of the sequence.
2348 """
2350 # overridden by file handlers
2351 if frame != 0:
2352 raise EOFError
2354 def show(self, title=None):
2355 """
2356 Displays this image. This method is mainly intended for debugging purposes.
2358 This method calls :py:func:`PIL.ImageShow.show` internally. You can use
2359 :py:func:`PIL.ImageShow.register` to override its default behaviour.
2361 The image is first saved to a temporary file. By default, it will be in
2362 PNG format.
2364 On Unix, the image is then opened using the **display**, **eog** or
2365 **xv** utility, depending on which one can be found.
2367 On macOS, the image is opened with the native Preview application.
2369 On Windows, the image is opened with the standard PNG display utility.
2371 :param title: Optional title to use for the image window, where possible.
2372 """
2374 _show(self, title=title)
2376 def split(self):
2377 """
2378 Split this image into individual bands. This method returns a
2379 tuple of individual image bands from an image. For example,
2380 splitting an "RGB" image creates three new images each
2381 containing a copy of one of the original bands (red, green,
2382 blue).
2384 If you need only one band, :py:meth:`~PIL.Image.Image.getchannel`
2385 method can be more convenient and faster.
2387 :returns: A tuple containing bands.
2388 """
2390 self.load()
2391 if self.im.bands == 1:
2392 ims = [self.copy()]
2393 else:
2394 ims = map(self._new, self.im.split())
2395 return tuple(ims)
2397 def getchannel(self, channel):
2398 """
2399 Returns an image containing a single channel of the source image.
2401 :param channel: What channel to return. Could be index
2402 (0 for "R" channel of "RGB") or channel name
2403 ("A" for alpha channel of "RGBA").
2404 :returns: An image in "L" mode.
2406 .. versionadded:: 4.3.0
2407 """
2408 self.load()
2410 if isinstance(channel, str):
2411 try:
2412 channel = self.getbands().index(channel)
2413 except ValueError as e:
2414 raise ValueError(f'The image has no channel "{channel}"') from e
2416 return self._new(self.im.getband(channel))
2418 def tell(self):
2419 """
2420 Returns the current frame number. See :py:meth:`~PIL.Image.Image.seek`.
2422 If defined, :attr:`~PIL.Image.Image.n_frames` refers to the
2423 number of available frames.
2425 :returns: Frame number, starting with 0.
2426 """
2427 return 0
2429 def thumbnail(self, size, resample=Resampling.BICUBIC, reducing_gap=2.0):
2430 """
2431 Make this image into a thumbnail. This method modifies the
2432 image to contain a thumbnail version of itself, no larger than
2433 the given size. This method calculates an appropriate thumbnail
2434 size to preserve the aspect of the image, calls the
2435 :py:meth:`~PIL.Image.Image.draft` method to configure the file reader
2436 (where applicable), and finally resizes the image.
2438 Note that this function modifies the :py:class:`~PIL.Image.Image`
2439 object in place. If you need to use the full resolution image as well,
2440 apply this method to a :py:meth:`~PIL.Image.Image.copy` of the original
2441 image.
2443 :param size: Requested size.
2444 :param resample: Optional resampling filter. This can be one
2445 of :py:data:`PIL.Image.Resampling.NEAREST`,
2446 :py:data:`PIL.Image.Resampling.BOX`,
2447 :py:data:`PIL.Image.Resampling.BILINEAR`,
2448 :py:data:`PIL.Image.Resampling.HAMMING`,
2449 :py:data:`PIL.Image.Resampling.BICUBIC` or
2450 :py:data:`PIL.Image.Resampling.LANCZOS`.
2451 If omitted, it defaults to :py:data:`PIL.Image.Resampling.BICUBIC`.
2452 (was :py:data:`PIL.Image.Resampling.NEAREST` prior to version 2.5.0).
2453 See: :ref:`concept-filters`.
2454 :param reducing_gap: Apply optimization by resizing the image
2455 in two steps. First, reducing the image by integer times
2456 using :py:meth:`~PIL.Image.Image.reduce` or
2457 :py:meth:`~PIL.Image.Image.draft` for JPEG images.
2458 Second, resizing using regular resampling. The last step
2459 changes size no less than by ``reducing_gap`` times.
2460 ``reducing_gap`` may be None (no first step is performed)
2461 or should be greater than 1.0. The bigger ``reducing_gap``,
2462 the closer the result to the fair resampling.
2463 The smaller ``reducing_gap``, the faster resizing.
2464 With ``reducing_gap`` greater or equal to 3.0, the result is
2465 indistinguishable from fair resampling in most cases.
2466 The default value is 2.0 (very close to fair resampling
2467 while still being faster in many cases).
2468 :returns: None
2469 """
2471 self.load()
2472 x, y = map(math.floor, size)
2473 if x >= self.width and y >= self.height:
2474 return
2476 def round_aspect(number, key):
2477 return max(min(math.floor(number), math.ceil(number), key=key), 1)
2479 # preserve aspect ratio
2480 aspect = self.width / self.height
2481 if x / y >= aspect:
2482 x = round_aspect(y * aspect, key=lambda n: abs(aspect - n / y))
2483 else:
2484 y = round_aspect(
2485 x / aspect, key=lambda n: 0 if n == 0 else abs(aspect - x / n)
2486 )
2487 size = (x, y)
2489 box = None
2490 if reducing_gap is not None:
2491 res = self.draft(None, (size[0] * reducing_gap, size[1] * reducing_gap))
2492 if res is not None:
2493 box = res[1]
2495 if self.size != size:
2496 im = self.resize(size, resample, box=box, reducing_gap=reducing_gap)
2498 self.im = im.im
2499 self._size = size
2500 self.mode = self.im.mode
2502 self.readonly = 0
2503 self.pyaccess = None
2505 # FIXME: the different transform methods need further explanation
2506 # instead of bloating the method docs, add a separate chapter.
2507 def transform(
2508 self,
2509 size,
2510 method,
2511 data=None,
2512 resample=Resampling.NEAREST,
2513 fill=1,
2514 fillcolor=None,
2515 ):
2516 """
2517 Transforms this image. This method creates a new image with the
2518 given size, and the same mode as the original, and copies data
2519 to the new image using the given transform.
2521 :param size: The output size.
2522 :param method: The transformation method. This is one of
2523 :py:data:`PIL.Image.Transform.EXTENT` (cut out a rectangular subregion),
2524 :py:data:`PIL.Image.Transform.AFFINE` (affine transform),
2525 :py:data:`PIL.Image.Transform.PERSPECTIVE` (perspective transform),
2526 :py:data:`PIL.Image.Transform.QUAD` (map a quadrilateral to a rectangle), or
2527 :py:data:`PIL.Image.Transform.MESH` (map a number of source quadrilaterals
2528 in one operation).
2530 It may also be an :py:class:`~PIL.Image.ImageTransformHandler`
2531 object::
2533 class Example(Image.ImageTransformHandler):
2534 def transform(self, size, data, resample, fill=1):
2535 # Return result
2537 It may also be an object with a ``method.getdata`` method
2538 that returns a tuple supplying new ``method`` and ``data`` values::
2540 class Example:
2541 def getdata(self):
2542 method = Image.Transform.EXTENT
2543 data = (0, 0, 100, 100)
2544 return method, data
2545 :param data: Extra data to the transformation method.
2546 :param resample: Optional resampling filter. It can be one of
2547 :py:data:`PIL.Image.Resampling.NEAREST` (use nearest neighbour),
2548 :py:data:`PIL.Image.Resampling.BILINEAR` (linear interpolation in a 2x2
2549 environment), or :py:data:`PIL.Image.BICUBIC` (cubic spline
2550 interpolation in a 4x4 environment). If omitted, or if the image
2551 has mode "1" or "P", it is set to :py:data:`PIL.Image.Resampling.NEAREST`.
2552 See: :ref:`concept-filters`.
2553 :param fill: If ``method`` is an
2554 :py:class:`~PIL.Image.ImageTransformHandler` object, this is one of
2555 the arguments passed to it. Otherwise, it is unused.
2556 :param fillcolor: Optional fill color for the area outside the
2557 transform in the output image.
2558 :returns: An :py:class:`~PIL.Image.Image` object.
2559 """
2561 if self.mode in ("LA", "RGBA") and resample != Resampling.NEAREST:
2562 return (
2563 self.convert({"LA": "La", "RGBA": "RGBa"}[self.mode])
2564 .transform(size, method, data, resample, fill, fillcolor)
2565 .convert(self.mode)
2566 )
2568 if isinstance(method, ImageTransformHandler):
2569 return method.transform(size, self, resample=resample, fill=fill)
2571 if hasattr(method, "getdata"):
2572 # compatibility w. old-style transform objects
2573 method, data = method.getdata()
2575 if data is None:
2576 raise ValueError("missing method data")
2578 im = new(self.mode, size, fillcolor)
2579 if self.mode == "P" and self.palette:
2580 im.palette = self.palette.copy()
2581 im.info = self.info.copy()
2582 if method == Transform.MESH:
2583 # list of quads
2584 for box, quad in data:
2585 im.__transformer(
2586 box, self, Transform.QUAD, quad, resample, fillcolor is None
2587 )
2588 else:
2589 im.__transformer(
2590 (0, 0) + size, self, method, data, resample, fillcolor is None
2591 )
2593 return im
2595 def __transformer(
2596 self, box, image, method, data, resample=Resampling.NEAREST, fill=1
2597 ):
2598 w = box[2] - box[0]
2599 h = box[3] - box[1]
2601 if method == Transform.AFFINE:
2602 data = data[:6]
2604 elif method == Transform.EXTENT:
2605 # convert extent to an affine transform
2606 x0, y0, x1, y1 = data
2607 xs = (x1 - x0) / w
2608 ys = (y1 - y0) / h
2609 method = Transform.AFFINE
2610 data = (xs, 0, x0, 0, ys, y0)
2612 elif method == Transform.PERSPECTIVE:
2613 data = data[:8]
2615 elif method == Transform.QUAD:
2616 # quadrilateral warp. data specifies the four corners
2617 # given as NW, SW, SE, and NE.
2618 nw = data[:2]
2619 sw = data[2:4]
2620 se = data[4:6]
2621 ne = data[6:8]
2622 x0, y0 = nw
2623 As = 1.0 / w
2624 At = 1.0 / h
2625 data = (
2626 x0,
2627 (ne[0] - x0) * As,
2628 (sw[0] - x0) * At,
2629 (se[0] - sw[0] - ne[0] + x0) * As * At,
2630 y0,
2631 (ne[1] - y0) * As,
2632 (sw[1] - y0) * At,
2633 (se[1] - sw[1] - ne[1] + y0) * As * At,
2634 )
2636 else:
2637 raise ValueError("unknown transformation method")
2639 if resample not in (
2640 Resampling.NEAREST,
2641 Resampling.BILINEAR,
2642 Resampling.BICUBIC,
2643 ):
2644 if resample in (Resampling.BOX, Resampling.HAMMING, Resampling.LANCZOS):
2645 message = {
2646 Resampling.BOX: "Image.Resampling.BOX",
2647 Resampling.HAMMING: "Image.Resampling.HAMMING",
2648 Resampling.LANCZOS: "Image.Resampling.LANCZOS",
2649 }[resample] + f" ({resample}) cannot be used."
2650 else:
2651 message = f"Unknown resampling filter ({resample})."
2653 filters = [
2654 f"{filter[1]} ({filter[0]})"
2655 for filter in (
2656 (Resampling.NEAREST, "Image.Resampling.NEAREST"),
2657 (Resampling.BILINEAR, "Image.Resampling.BILINEAR"),
2658 (Resampling.BICUBIC, "Image.Resampling.BICUBIC"),
2659 )
2660 ]
2661 raise ValueError(
2662 message + " Use " + ", ".join(filters[:-1]) + " or " + filters[-1]
2663 )
2665 image.load()
2667 self.load()
2669 if image.mode in ("1", "P"):
2670 resample = Resampling.NEAREST
2672 self.im.transform2(box, image.im, method, data, resample, fill)
2674 def transpose(self, method):
2675 """
2676 Transpose image (flip or rotate in 90 degree steps)
2678 :param method: One of :py:data:`PIL.Image.Transpose.FLIP_LEFT_RIGHT`,
2679 :py:data:`PIL.Image.Transpose.FLIP_TOP_BOTTOM`,
2680 :py:data:`PIL.Image.Transpose.ROTATE_90`,
2681 :py:data:`PIL.Image.Transpose.ROTATE_180`,
2682 :py:data:`PIL.Image.Transpose.ROTATE_270`,
2683 :py:data:`PIL.Image.Transpose.TRANSPOSE` or
2684 :py:data:`PIL.Image.Transpose.TRANSVERSE`.
2685 :returns: Returns a flipped or rotated copy of this image.
2686 """
2688 self.load()
2689 return self._new(self.im.transpose(method))
2691 def effect_spread(self, distance):
2692 """
2693 Randomly spread pixels in an image.
2695 :param distance: Distance to spread pixels.
2696 """
2697 self.load()
2698 return self._new(self.im.effect_spread(distance))
2700 def toqimage(self):
2701 """Returns a QImage copy of this image"""
2702 from . import ImageQt
2704 if not ImageQt.qt_is_installed:
2705 raise ImportError("Qt bindings are not installed")
2706 return ImageQt.toqimage(self)
2708 def toqpixmap(self):
2709 """Returns a QPixmap copy of this image"""
2710 from . import ImageQt
2712 if not ImageQt.qt_is_installed:
2713 raise ImportError("Qt bindings are not installed")
2714 return ImageQt.toqpixmap(self)
2717# --------------------------------------------------------------------
2718# Abstract handlers.
2721class ImagePointHandler:
2722 """
2723 Used as a mixin by point transforms
2724 (for use with :py:meth:`~PIL.Image.Image.point`)
2725 """
2727 pass
2730class ImageTransformHandler:
2731 """
2732 Used as a mixin by geometry transforms
2733 (for use with :py:meth:`~PIL.Image.Image.transform`)
2734 """
2736 pass
2739# --------------------------------------------------------------------
2740# Factories
2742#
2743# Debugging
2746def _wedge():
2747 """Create greyscale wedge (for debugging only)"""
2749 return Image()._new(core.wedge("L"))
2752def _check_size(size):
2753 """
2754 Common check to enforce type and sanity check on size tuples
2756 :param size: Should be a 2 tuple of (width, height)
2757 :returns: True, or raises a ValueError
2758 """
2760 if not isinstance(size, (list, tuple)): 2760 ↛ 2761line 2760 didn't jump to line 2761, because the condition on line 2760 was never true
2761 raise ValueError("Size must be a tuple")
2762 if len(size) != 2: 2762 ↛ 2763line 2762 didn't jump to line 2763, because the condition on line 2762 was never true
2763 raise ValueError("Size must be a tuple of length 2")
2764 if size[0] < 0 or size[1] < 0: 2764 ↛ 2765line 2764 didn't jump to line 2765, because the condition on line 2764 was never true
2765 raise ValueError("Width and height must be >= 0")
2767 return True
2770def new(mode, size, color=0):
2771 """
2772 Creates a new image with the given mode and size.
2774 :param mode: The mode to use for the new image. See:
2775 :ref:`concept-modes`.
2776 :param size: A 2-tuple, containing (width, height) in pixels.
2777 :param color: What color to use for the image. Default is black.
2778 If given, this should be a single integer or floating point value
2779 for single-band modes, and a tuple for multi-band modes (one value
2780 per band). When creating RGB images, you can also use color
2781 strings as supported by the ImageColor module. If the color is
2782 None, the image is not initialised.
2783 :returns: An :py:class:`~PIL.Image.Image` object.
2784 """
2786 _check_size(size)
2788 if color is None: 2788 ↛ 2790line 2788 didn't jump to line 2790, because the condition on line 2788 was never true
2789 # don't initialize
2790 return Image()._new(core.new(mode, size))
2792 if isinstance(color, str):
2793 # css3-style specifier
2795 from . import ImageColor
2797 color = ImageColor.getcolor(color, mode)
2799 im = Image()
2800 if mode == "P" and isinstance(color, (list, tuple)) and len(color) in [3, 4]: 2800 ↛ 2802line 2800 didn't jump to line 2802, because the condition on line 2800 was never true
2801 # RGB or RGBA value for a P image
2802 from . import ImagePalette
2804 im.palette = ImagePalette.ImagePalette()
2805 color = im.palette.getcolor(color)
2806 return im._new(core.fill(mode, size, color))
2809def frombytes(mode, size, data, decoder_name="raw", *args):
2810 """
2811 Creates a copy of an image memory from pixel data in a buffer.
2813 In its simplest form, this function takes three arguments
2814 (mode, size, and unpacked pixel data).
2816 You can also use any pixel decoder supported by PIL. For more
2817 information on available decoders, see the section
2818 :ref:`Writing Your Own File Codec <file-codecs>`.
2820 Note that this function decodes pixel data only, not entire images.
2821 If you have an entire image in a string, wrap it in a
2822 :py:class:`~io.BytesIO` object, and use :py:func:`~PIL.Image.open` to load
2823 it.
2825 :param mode: The image mode. See: :ref:`concept-modes`.
2826 :param size: The image size.
2827 :param data: A byte buffer containing raw data for the given mode.
2828 :param decoder_name: What decoder to use.
2829 :param args: Additional parameters for the given decoder.
2830 :returns: An :py:class:`~PIL.Image.Image` object.
2831 """
2833 _check_size(size)
2835 # may pass tuple instead of argument list
2836 if len(args) == 1 and isinstance(args[0], tuple):
2837 args = args[0]
2839 if decoder_name == "raw" and args == ():
2840 args = mode
2842 im = new(mode, size)
2843 im.frombytes(data, decoder_name, args)
2844 return im
2847def frombuffer(mode, size, data, decoder_name="raw", *args):
2848 """
2849 Creates an image memory referencing pixel data in a byte buffer.
2851 This function is similar to :py:func:`~PIL.Image.frombytes`, but uses data
2852 in the byte buffer, where possible. This means that changes to the
2853 original buffer object are reflected in this image). Not all modes can
2854 share memory; supported modes include "L", "RGBX", "RGBA", and "CMYK".
2856 Note that this function decodes pixel data only, not entire images.
2857 If you have an entire image file in a string, wrap it in a
2858 :py:class:`~io.BytesIO` object, and use :py:func:`~PIL.Image.open` to load it.
2860 In the current version, the default parameters used for the "raw" decoder
2861 differs from that used for :py:func:`~PIL.Image.frombytes`. This is a
2862 bug, and will probably be fixed in a future release. The current release
2863 issues a warning if you do this; to disable the warning, you should provide
2864 the full set of parameters. See below for details.
2866 :param mode: The image mode. See: :ref:`concept-modes`.
2867 :param size: The image size.
2868 :param data: A bytes or other buffer object containing raw
2869 data for the given mode.
2870 :param decoder_name: What decoder to use.
2871 :param args: Additional parameters for the given decoder. For the
2872 default encoder ("raw"), it's recommended that you provide the
2873 full set of parameters::
2875 frombuffer(mode, size, data, "raw", mode, 0, 1)
2877 :returns: An :py:class:`~PIL.Image.Image` object.
2879 .. versionadded:: 1.1.4
2880 """
2882 _check_size(size)
2884 # may pass tuple instead of argument list
2885 if len(args) == 1 and isinstance(args[0], tuple):
2886 args = args[0]
2888 if decoder_name == "raw":
2889 if args == ():
2890 args = mode, 0, 1
2891 if args[0] in _MAPMODES:
2892 im = new(mode, (1, 1))
2893 im = im._new(core.map_buffer(data, size, decoder_name, 0, args))
2894 if mode == "P":
2895 from . import ImagePalette
2897 im.palette = ImagePalette.ImagePalette("RGB", im.im.getpalette("RGB"))
2898 im.readonly = 1
2899 return im
2901 return frombytes(mode, size, data, decoder_name, args)
2904def fromarray(obj, mode=None):
2905 """
2906 Creates an image memory from an object exporting the array interface
2907 (using the buffer protocol).
2909 If ``obj`` is not contiguous, then the ``tobytes`` method is called
2910 and :py:func:`~PIL.Image.frombuffer` is used.
2912 If you have an image in NumPy::
2914 from PIL import Image
2915 import numpy as np
2916 im = Image.open("hopper.jpg")
2917 a = np.asarray(im)
2919 Then this can be used to convert it to a Pillow image::
2921 im = Image.fromarray(a)
2923 :param obj: Object with array interface
2924 :param mode: Optional mode to use when reading ``obj``. Will be determined from
2925 type if ``None``.
2927 This will not be used to convert the data after reading, but will be used to
2928 change how the data is read::
2930 from PIL import Image
2931 import numpy as np
2932 a = np.full((1, 1), 300)
2933 im = Image.fromarray(a, mode="L")
2934 im.getpixel((0, 0)) # 44
2935 im = Image.fromarray(a, mode="RGB")
2936 im.getpixel((0, 0)) # (44, 1, 0)
2938 See: :ref:`concept-modes` for general information about modes.
2939 :returns: An image object.
2941 .. versionadded:: 1.1.6
2942 """
2943 arr = obj.__array_interface__
2944 shape = arr["shape"]
2945 ndim = len(shape)
2946 strides = arr.get("strides", None)
2947 if mode is None:
2948 try:
2949 typekey = (1, 1) + shape[2:], arr["typestr"]
2950 except KeyError as e:
2951 raise TypeError("Cannot handle this data type") from e
2952 try:
2953 mode, rawmode = _fromarray_typemap[typekey]
2954 except KeyError as e:
2955 raise TypeError("Cannot handle this data type: %s, %s" % typekey) from e
2956 else:
2957 rawmode = mode
2958 if mode in ["1", "L", "I", "P", "F"]:
2959 ndmax = 2
2960 elif mode == "RGB":
2961 ndmax = 3
2962 else:
2963 ndmax = 4
2964 if ndim > ndmax:
2965 raise ValueError(f"Too many dimensions: {ndim} > {ndmax}.")
2967 size = 1 if ndim == 1 else shape[1], shape[0]
2968 if strides is not None:
2969 if hasattr(obj, "tobytes"):
2970 obj = obj.tobytes()
2971 else:
2972 obj = obj.tostring()
2974 return frombuffer(mode, size, obj, "raw", rawmode, 0, 1)
2977def fromqimage(im):
2978 """Creates an image instance from a QImage image"""
2979 from . import ImageQt
2981 if not ImageQt.qt_is_installed:
2982 raise ImportError("Qt bindings are not installed")
2983 return ImageQt.fromqimage(im)
2986def fromqpixmap(im):
2987 """Creates an image instance from a QPixmap image"""
2988 from . import ImageQt
2990 if not ImageQt.qt_is_installed:
2991 raise ImportError("Qt bindings are not installed")
2992 return ImageQt.fromqpixmap(im)
2995_fromarray_typemap = {
2996 # (shape, typestr) => mode, rawmode
2997 # first two members of shape are set to one
2998 ((1, 1), "|b1"): ("1", "1;8"),
2999 ((1, 1), "|u1"): ("L", "L"),
3000 ((1, 1), "|i1"): ("I", "I;8"),
3001 ((1, 1), "<u2"): ("I", "I;16"),
3002 ((1, 1), ">u2"): ("I", "I;16B"),
3003 ((1, 1), "<i2"): ("I", "I;16S"),
3004 ((1, 1), ">i2"): ("I", "I;16BS"),
3005 ((1, 1), "<u4"): ("I", "I;32"),
3006 ((1, 1), ">u4"): ("I", "I;32B"),
3007 ((1, 1), "<i4"): ("I", "I;32S"),
3008 ((1, 1), ">i4"): ("I", "I;32BS"),
3009 ((1, 1), "<f4"): ("F", "F;32F"),
3010 ((1, 1), ">f4"): ("F", "F;32BF"),
3011 ((1, 1), "<f8"): ("F", "F;64F"),
3012 ((1, 1), ">f8"): ("F", "F;64BF"),
3013 ((1, 1, 2), "|u1"): ("LA", "LA"),
3014 ((1, 1, 3), "|u1"): ("RGB", "RGB"),
3015 ((1, 1, 4), "|u1"): ("RGBA", "RGBA"),
3016 # shortcuts:
3017 ((1, 1), _ENDIAN + "i4"): ("I", "I"),
3018 ((1, 1), _ENDIAN + "f4"): ("F", "F"),
3019}
3022def _decompression_bomb_check(size):
3023 if MAX_IMAGE_PIXELS is None: 3023 ↛ 3024line 3023 didn't jump to line 3024, because the condition on line 3023 was never true
3024 return
3026 pixels = size[0] * size[1]
3028 if pixels > 2 * MAX_IMAGE_PIXELS: 3028 ↛ 3029line 3028 didn't jump to line 3029, because the condition on line 3028 was never true
3029 raise DecompressionBombError(
3030 f"Image size ({pixels} pixels) exceeds limit of {2 * MAX_IMAGE_PIXELS} "
3031 "pixels, could be decompression bomb DOS attack."
3032 )
3034 if pixels > MAX_IMAGE_PIXELS: 3034 ↛ 3035line 3034 didn't jump to line 3035, because the condition on line 3034 was never true
3035 warnings.warn(
3036 f"Image size ({pixels} pixels) exceeds limit of {MAX_IMAGE_PIXELS} pixels, "
3037 "could be decompression bomb DOS attack.",
3038 DecompressionBombWarning,
3039 )
3042def open(fp, mode="r", formats=None):
3043 """
3044 Opens and identifies the given image file.
3046 This is a lazy operation; this function identifies the file, but
3047 the file remains open and the actual image data is not read from
3048 the file until you try to process the data (or call the
3049 :py:meth:`~PIL.Image.Image.load` method). See
3050 :py:func:`~PIL.Image.new`. See :ref:`file-handling`.
3052 :param fp: A filename (string), pathlib.Path object or a file object.
3053 The file object must implement ``file.read``,
3054 ``file.seek``, and ``file.tell`` methods,
3055 and be opened in binary mode.
3056 :param mode: The mode. If given, this argument must be "r".
3057 :param formats: A list or tuple of formats to attempt to load the file in.
3058 This can be used to restrict the set of formats checked.
3059 Pass ``None`` to try all supported formats. You can print the set of
3060 available formats by running ``python3 -m PIL`` or using
3061 the :py:func:`PIL.features.pilinfo` function.
3062 :returns: An :py:class:`~PIL.Image.Image` object.
3063 :exception FileNotFoundError: If the file cannot be found.
3064 :exception PIL.UnidentifiedImageError: If the image cannot be opened and
3065 identified.
3066 :exception ValueError: If the ``mode`` is not "r", or if a ``StringIO``
3067 instance is used for ``fp``.
3068 :exception TypeError: If ``formats`` is not ``None``, a list or a tuple.
3069 """
3071 if mode != "r": 3071 ↛ 3072line 3071 didn't jump to line 3072, because the condition on line 3071 was never true
3072 raise ValueError(f"bad mode {repr(mode)}")
3073 elif isinstance(fp, io.StringIO): 3073 ↛ 3074line 3073 didn't jump to line 3074, because the condition on line 3073 was never true
3074 raise ValueError(
3075 "StringIO cannot be used to open an image. "
3076 "Binary data must be used instead."
3077 )
3079 if formats is None: 3079 ↛ 3081line 3079 didn't jump to line 3081, because the condition on line 3079 was never false
3080 formats = ID
3081 elif not isinstance(formats, (list, tuple)):
3082 raise TypeError("formats must be a list or tuple")
3084 exclusive_fp = False
3085 filename = ""
3086 if isinstance(fp, Path): 3086 ↛ 3087line 3086 didn't jump to line 3087, because the condition on line 3086 was never true
3087 filename = str(fp.resolve())
3088 elif is_path(fp): 3088 ↛ 3089line 3088 didn't jump to line 3089, because the condition on line 3088 was never true
3089 filename = fp
3091 if filename: 3091 ↛ 3092line 3091 didn't jump to line 3092, because the condition on line 3091 was never true
3092 fp = builtins.open(filename, "rb")
3093 exclusive_fp = True
3095 try:
3096 fp.seek(0)
3097 except (AttributeError, io.UnsupportedOperation):
3098 fp = io.BytesIO(fp.read())
3099 exclusive_fp = True
3101 prefix = fp.read(16)
3103 preinit()
3105 accept_warnings = []
3107 def _open_core(fp, filename, prefix, formats):
3108 for i in formats: 3108 ↛ 3131line 3108 didn't jump to line 3131, because the loop on line 3108 didn't complete
3109 i = i.upper()
3110 if i not in OPEN: 3110 ↛ 3111line 3110 didn't jump to line 3111, because the condition on line 3110 was never true
3111 init()
3112 try:
3113 factory, accept = OPEN[i]
3114 result = not accept or accept(prefix)
3115 if type(result) in [str, bytes]: 3115 ↛ 3116line 3115 didn't jump to line 3116, because the condition on line 3115 was never true
3116 accept_warnings.append(result)
3117 elif result:
3118 fp.seek(0)
3119 im = factory(fp, filename)
3120 _decompression_bomb_check(im.size)
3121 return im
3122 except (SyntaxError, IndexError, TypeError, struct.error):
3123 # Leave disabled by default, spams the logs with image
3124 # opening failures that are entirely expected.
3125 # logger.debug("", exc_info=True)
3126 continue
3127 except BaseException:
3128 if exclusive_fp:
3129 fp.close()
3130 raise
3131 return None
3133 im = _open_core(fp, filename, prefix, formats)
3135 if im is None: 3135 ↛ 3136line 3135 didn't jump to line 3136, because the condition on line 3135 was never true
3136 if init():
3137 im = _open_core(fp, filename, prefix, formats)
3139 if im: 3139 ↛ 3143line 3139 didn't jump to line 3143, because the condition on line 3139 was never false
3140 im._exclusive_fp = exclusive_fp
3141 return im
3143 if exclusive_fp:
3144 fp.close()
3145 for message in accept_warnings:
3146 warnings.warn(message)
3147 raise UnidentifiedImageError(
3148 "cannot identify image file %r" % (filename if filename else fp)
3149 )
3152#
3153# Image processing.
3156def alpha_composite(im1, im2):
3157 """
3158 Alpha composite im2 over im1.
3160 :param im1: The first image. Must have mode RGBA.
3161 :param im2: The second image. Must have mode RGBA, and the same size as
3162 the first image.
3163 :returns: An :py:class:`~PIL.Image.Image` object.
3164 """
3166 im1.load()
3167 im2.load()
3168 return im1._new(core.alpha_composite(im1.im, im2.im))
3171def blend(im1, im2, alpha):
3172 """
3173 Creates a new image by interpolating between two input images, using
3174 a constant alpha::
3176 out = image1 * (1.0 - alpha) + image2 * alpha
3178 :param im1: The first image.
3179 :param im2: The second image. Must have the same mode and size as
3180 the first image.
3181 :param alpha: The interpolation alpha factor. If alpha is 0.0, a
3182 copy of the first image is returned. If alpha is 1.0, a copy of
3183 the second image is returned. There are no restrictions on the
3184 alpha value. If necessary, the result is clipped to fit into
3185 the allowed output range.
3186 :returns: An :py:class:`~PIL.Image.Image` object.
3187 """
3189 im1.load()
3190 im2.load()
3191 return im1._new(core.blend(im1.im, im2.im, alpha))
3194def composite(image1, image2, mask):
3195 """
3196 Create composite image by blending images using a transparency mask.
3198 :param image1: The first image.
3199 :param image2: The second image. Must have the same mode and
3200 size as the first image.
3201 :param mask: A mask image. This image can have mode
3202 "1", "L", or "RGBA", and must have the same size as the
3203 other two images.
3204 """
3206 image = image2.copy()
3207 image.paste(image1, None, mask)
3208 return image
3211def eval(image, *args):
3212 """
3213 Applies the function (which should take one argument) to each pixel
3214 in the given image. If the image has more than one band, the same
3215 function is applied to each band. Note that the function is
3216 evaluated once for each possible pixel value, so you cannot use
3217 random components or other generators.
3219 :param image: The input image.
3220 :param function: A function object, taking one integer argument.
3221 :returns: An :py:class:`~PIL.Image.Image` object.
3222 """
3224 return image.point(args[0])
3227def merge(mode, bands):
3228 """
3229 Merge a set of single band images into a new multiband image.
3231 :param mode: The mode to use for the output image. See:
3232 :ref:`concept-modes`.
3233 :param bands: A sequence containing one single-band image for
3234 each band in the output image. All bands must have the
3235 same size.
3236 :returns: An :py:class:`~PIL.Image.Image` object.
3237 """
3239 if getmodebands(mode) != len(bands) or "*" in mode:
3240 raise ValueError("wrong number of bands")
3241 for band in bands[1:]:
3242 if band.mode != getmodetype(mode):
3243 raise ValueError("mode mismatch")
3244 if band.size != bands[0].size:
3245 raise ValueError("size mismatch")
3246 for band in bands:
3247 band.load()
3248 return bands[0]._new(core.merge(mode, *[b.im for b in bands]))
3251# --------------------------------------------------------------------
3252# Plugin registry
3255def register_open(id, factory, accept=None):
3256 """
3257 Register an image file plugin. This function should not be used
3258 in application code.
3260 :param id: An image format identifier.
3261 :param factory: An image file factory method.
3262 :param accept: An optional function that can be used to quickly
3263 reject images having another format.
3264 """
3265 id = id.upper()
3266 ID.append(id)
3267 OPEN[id] = factory, accept
3270def register_mime(id, mimetype):
3271 """
3272 Registers an image MIME type. This function should not be used
3273 in application code.
3275 :param id: An image format identifier.
3276 :param mimetype: The image MIME type for this format.
3277 """
3278 MIME[id.upper()] = mimetype
3281def register_save(id, driver):
3282 """
3283 Registers an image save function. This function should not be
3284 used in application code.
3286 :param id: An image format identifier.
3287 :param driver: A function to save images in this format.
3288 """
3289 SAVE[id.upper()] = driver
3292def register_save_all(id, driver):
3293 """
3294 Registers an image function to save all the frames
3295 of a multiframe format. This function should not be
3296 used in application code.
3298 :param id: An image format identifier.
3299 :param driver: A function to save images in this format.
3300 """
3301 SAVE_ALL[id.upper()] = driver
3304def register_extension(id, extension):
3305 """
3306 Registers an image extension. This function should not be
3307 used in application code.
3309 :param id: An image format identifier.
3310 :param extension: An extension used for this format.
3311 """
3312 EXTENSION[extension.lower()] = id.upper()
3315def register_extensions(id, extensions):
3316 """
3317 Registers image extensions. This function should not be
3318 used in application code.
3320 :param id: An image format identifier.
3321 :param extensions: A list of extensions used for this format.
3322 """
3323 for extension in extensions:
3324 register_extension(id, extension)
3327def registered_extensions():
3328 """
3329 Returns a dictionary containing all file extensions belonging
3330 to registered plugins
3331 """
3332 if not EXTENSION:
3333 init()
3334 return EXTENSION
3337def register_decoder(name, decoder):
3338 """
3339 Registers an image decoder. This function should not be
3340 used in application code.
3342 :param name: The name of the decoder
3343 :param decoder: A callable(mode, args) that returns an
3344 ImageFile.PyDecoder object
3346 .. versionadded:: 4.1.0
3347 """
3348 DECODERS[name] = decoder
3351def register_encoder(name, encoder):
3352 """
3353 Registers an image encoder. This function should not be
3354 used in application code.
3356 :param name: The name of the encoder
3357 :param encoder: A callable(mode, args) that returns an
3358 ImageFile.PyEncoder object
3360 .. versionadded:: 4.1.0
3361 """
3362 ENCODERS[name] = encoder
3365# --------------------------------------------------------------------
3366# Simple display support.
3369def _show(image, **options):
3370 from . import ImageShow
3372 ImageShow.show(image, **options)
3375# --------------------------------------------------------------------
3376# Effects
3379def effect_mandelbrot(size, extent, quality):
3380 """
3381 Generate a Mandelbrot set covering the given extent.
3383 :param size: The requested size in pixels, as a 2-tuple:
3384 (width, height).
3385 :param extent: The extent to cover, as a 4-tuple:
3386 (x0, y0, x1, y1).
3387 :param quality: Quality.
3388 """
3389 return Image()._new(core.effect_mandelbrot(size, extent, quality))
3392def effect_noise(size, sigma):
3393 """
3394 Generate Gaussian noise centered around 128.
3396 :param size: The requested size in pixels, as a 2-tuple:
3397 (width, height).
3398 :param sigma: Standard deviation of noise.
3399 """
3400 return Image()._new(core.effect_noise(size, sigma))
3403def linear_gradient(mode):
3404 """
3405 Generate 256x256 linear gradient from black to white, top to bottom.
3407 :param mode: Input mode.
3408 """
3409 return Image()._new(core.linear_gradient(mode))
3412def radial_gradient(mode):
3413 """
3414 Generate 256x256 radial gradient from black to white, centre to edge.
3416 :param mode: Input mode.
3417 """
3418 return Image()._new(core.radial_gradient(mode))
3421# --------------------------------------------------------------------
3422# Resources
3425def _apply_env_variables(env=None):
3426 if env is None: 3426 ↛ 3429line 3426 didn't jump to line 3429, because the condition on line 3426 was never false
3427 env = os.environ
3429 for var_name, setter in [
3430 ("PILLOW_ALIGNMENT", core.set_alignment),
3431 ("PILLOW_BLOCK_SIZE", core.set_block_size),
3432 ("PILLOW_BLOCKS_MAX", core.set_blocks_max),
3433 ]:
3434 if var_name not in env: 3434 ↛ 3437line 3434 didn't jump to line 3437, because the condition on line 3434 was never false
3435 continue
3437 var = env[var_name].lower()
3439 units = 1
3440 for postfix, mul in [("k", 1024), ("m", 1024 * 1024)]:
3441 if var.endswith(postfix):
3442 units = mul
3443 var = var[: -len(postfix)]
3445 try:
3446 var = int(var) * units
3447 except ValueError:
3448 warnings.warn(f"{var_name} is not int")
3449 continue
3451 try:
3452 setter(var)
3453 except ValueError as e:
3454 warnings.warn(f"{var_name}: {e}")
3457_apply_env_variables()
3458atexit.register(core.clear_cache)
3461class Exif(MutableMapping):
3462 endian = None
3463 bigtiff = False
3465 def __init__(self):
3466 self._data = {}
3467 self._ifds = {}
3468 self._info = None
3469 self._loaded_exif = None
3471 def _fixup(self, value):
3472 try:
3473 if len(value) == 1 and isinstance(value, tuple):
3474 return value[0]
3475 except Exception:
3476 pass
3477 return value
3479 def _fixup_dict(self, src_dict):
3480 # Helper function
3481 # returns a dict with any single item tuples/lists as individual values
3482 return {k: self._fixup(v) for k, v in src_dict.items()}
3484 def _get_ifd_dict(self, offset):
3485 try:
3486 # an offset pointer to the location of the nested embedded IFD.
3487 # It should be a long, but may be corrupted.
3488 self.fp.seek(offset)
3489 except (KeyError, TypeError):
3490 pass
3491 else:
3492 from . import TiffImagePlugin
3494 info = TiffImagePlugin.ImageFileDirectory_v2(self.head)
3495 info.load(self.fp)
3496 return self._fixup_dict(info)
3498 def _get_head(self):
3499 version = b"\x2B" if self.bigtiff else b"\x2A"
3500 if self.endian == "<":
3501 head = b"II" + version + b"\x00" + o32le(8)
3502 else:
3503 head = b"MM\x00" + version + o32be(8)
3504 if self.bigtiff:
3505 head += o32le(8) if self.endian == "<" else o32be(8)
3506 head += b"\x00\x00\x00\x00"
3507 return head
3509 def load(self, data):
3510 # Extract EXIF information. This is highly experimental,
3511 # and is likely to be replaced with something better in a future
3512 # version.
3514 # The EXIF record consists of a TIFF file embedded in a JPEG
3515 # application marker (!).
3516 if data == self._loaded_exif:
3517 return
3518 self._loaded_exif = data
3519 self._data.clear()
3520 self._ifds.clear()
3521 if data and data.startswith(b"Exif\x00\x00"):
3522 data = data[6:]
3523 if not data:
3524 self._info = None
3525 return
3527 self.fp = io.BytesIO(data)
3528 self.head = self.fp.read(8)
3529 # process dictionary
3530 from . import TiffImagePlugin
3532 self._info = TiffImagePlugin.ImageFileDirectory_v2(self.head)
3533 self.endian = self._info._endian
3534 self.fp.seek(self._info.next)
3535 self._info.load(self.fp)
3537 def load_from_fp(self, fp, offset=None):
3538 self._loaded_exif = None
3539 self._data.clear()
3540 self._ifds.clear()
3542 # process dictionary
3543 from . import TiffImagePlugin
3545 self.fp = fp
3546 if offset is not None:
3547 self.head = self._get_head()
3548 else:
3549 self.head = self.fp.read(8)
3550 self._info = TiffImagePlugin.ImageFileDirectory_v2(self.head)
3551 if self.endian is None:
3552 self.endian = self._info._endian
3553 if offset is None:
3554 offset = self._info.next
3555 self.fp.seek(offset)
3556 self._info.load(self.fp)
3558 def _get_merged_dict(self):
3559 merged_dict = dict(self)
3561 # get EXIF extension
3562 if 0x8769 in self:
3563 ifd = self._get_ifd_dict(self[0x8769])
3564 if ifd:
3565 merged_dict.update(ifd)
3567 # GPS
3568 if 0x8825 in self:
3569 merged_dict[0x8825] = self._get_ifd_dict(self[0x8825])
3571 return merged_dict
3573 def tobytes(self, offset=8):
3574 from . import TiffImagePlugin
3576 head = self._get_head()
3577 ifd = TiffImagePlugin.ImageFileDirectory_v2(ifh=head)
3578 for tag, value in self.items():
3579 if tag in [0x8769, 0x8225, 0x8825] and not isinstance(value, dict):
3580 value = self.get_ifd(tag)
3581 if (
3582 tag == 0x8769
3583 and 0xA005 in value
3584 and not isinstance(value[0xA005], dict)
3585 ):
3586 value = value.copy()
3587 value[0xA005] = self.get_ifd(0xA005)
3588 ifd[tag] = value
3589 return b"Exif\x00\x00" + head + ifd.tobytes(offset)
3591 def get_ifd(self, tag):
3592 if tag not in self._ifds:
3593 if tag in [0x8769, 0x8825]:
3594 # exif, gpsinfo
3595 if tag in self:
3596 self._ifds[tag] = self._get_ifd_dict(self[tag])
3597 elif tag in [0xA005, 0x927C]:
3598 # interop, makernote
3599 if 0x8769 not in self._ifds:
3600 self.get_ifd(0x8769)
3601 tag_data = self._ifds[0x8769][tag]
3602 if tag == 0x927C:
3603 # makernote
3604 from .TiffImagePlugin import ImageFileDirectory_v2
3606 if tag_data[:8] == b"FUJIFILM":
3607 ifd_offset = i32le(tag_data, 8)
3608 ifd_data = tag_data[ifd_offset:]
3610 makernote = {}
3611 for i in range(0, struct.unpack("<H", ifd_data[:2])[0]):
3612 ifd_tag, typ, count, data = struct.unpack(
3613 "<HHL4s", ifd_data[i * 12 + 2 : (i + 1) * 12 + 2]
3614 )
3615 try:
3616 (
3617 unit_size,
3618 handler,
3619 ) = ImageFileDirectory_v2._load_dispatch[typ]
3620 except KeyError:
3621 continue
3622 size = count * unit_size
3623 if size > 4:
3624 (offset,) = struct.unpack("<L", data)
3625 data = ifd_data[offset - 12 : offset + size - 12]
3626 else:
3627 data = data[:size]
3629 if len(data) != size:
3630 warnings.warn(
3631 "Possibly corrupt EXIF MakerNote data. "
3632 f"Expecting to read {size} bytes but only got "
3633 f"{len(data)}. Skipping tag {ifd_tag}"
3634 )
3635 continue
3637 if not data:
3638 continue
3640 makernote[ifd_tag] = handler(
3641 ImageFileDirectory_v2(), data, False
3642 )
3643 self._ifds[tag] = dict(self._fixup_dict(makernote))
3644 elif self.get(0x010F) == "Nintendo":
3645 makernote = {}
3646 for i in range(0, struct.unpack(">H", tag_data[:2])[0]):
3647 ifd_tag, typ, count, data = struct.unpack(
3648 ">HHL4s", tag_data[i * 12 + 2 : (i + 1) * 12 + 2]
3649 )
3650 if ifd_tag == 0x1101:
3651 # CameraInfo
3652 (offset,) = struct.unpack(">L", data)
3653 self.fp.seek(offset)
3655 camerainfo = {"ModelID": self.fp.read(4)}
3657 self.fp.read(4)
3658 # Seconds since 2000
3659 camerainfo["TimeStamp"] = i32le(self.fp.read(12))
3661 self.fp.read(4)
3662 camerainfo["InternalSerialNumber"] = self.fp.read(4)
3664 self.fp.read(12)
3665 parallax = self.fp.read(4)
3666 handler = ImageFileDirectory_v2._load_dispatch[
3667 TiffTags.FLOAT
3668 ][1]
3669 camerainfo["Parallax"] = handler(
3670 ImageFileDirectory_v2(), parallax, False
3671 )
3673 self.fp.read(4)
3674 camerainfo["Category"] = self.fp.read(2)
3676 makernote = {0x1101: dict(self._fixup_dict(camerainfo))}
3677 self._ifds[tag] = makernote
3678 else:
3679 # interop
3680 self._ifds[tag] = self._get_ifd_dict(tag_data)
3681 return self._ifds.get(tag, {})
3683 def __str__(self):
3684 if self._info is not None:
3685 # Load all keys into self._data
3686 for tag in self._info.keys():
3687 self[tag]
3689 return str(self._data)
3691 def __len__(self):
3692 keys = set(self._data)
3693 if self._info is not None:
3694 keys.update(self._info)
3695 return len(keys)
3697 def __getitem__(self, tag):
3698 if self._info is not None and tag not in self._data and tag in self._info:
3699 self._data[tag] = self._fixup(self._info[tag])
3700 del self._info[tag]
3701 return self._data[tag]
3703 def __contains__(self, tag):
3704 return tag in self._data or (self._info is not None and tag in self._info)
3706 def __setitem__(self, tag, value):
3707 if self._info is not None and tag in self._info:
3708 del self._info[tag]
3709 self._data[tag] = value
3711 def __delitem__(self, tag):
3712 if self._info is not None and tag in self._info:
3713 del self._info[tag]
3714 else:
3715 del self._data[tag]
3717 def __iter__(self):
3718 keys = set(self._data)
3719 if self._info is not None:
3720 keys.update(self._info)
3721 return iter(keys)