CoolFace
Apppublic

Aluode/PerceptionLabPortable

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
Image.py4247 linesDownload Raw Back to PIL
1#
2# The Python Imaging Library.
3# $Id$
4#
5# the Image class wrapper
6#
7# partial release history:
8# 1995-09-09 fl   Created
9# 1996-03-11 fl   PIL release 0.0 (proof of concept)
10# 1996-04-30 fl   PIL release 0.1b1
11# 1999-07-28 fl   PIL release 1.0 final
12# 2000-06-07 fl   PIL release 1.1
13# 2000-10-20 fl   PIL release 1.1.1
14# 2001-05-07 fl   PIL release 1.1.2
15# 2002-03-15 fl   PIL release 1.1.3
16# 2003-05-10 fl   PIL release 1.1.4
17# 2005-03-28 fl   PIL release 1.1.5
18# 2006-12-02 fl   PIL release 1.1.6
19# 2009-11-15 fl   PIL release 1.1.7
20#
21# Copyright (c) 1997-2009 by Secret Labs AB.  All rights reserved.
22# Copyright (c) 1995-2009 by Fredrik Lundh.
23#
24# See the README file for information on usage and redistribution.
25#
26
27from __future__ import annotations
28
29import abc
30import atexit
31import builtins
32import io
33import logging
34import math
35import os
36import re
37import struct
38import sys
39import tempfile
40import warnings
41from collections.abc import MutableMapping
42from enum import IntEnum
43from typing import IO, Protocol, cast
44
45# VERSION was removed in Pillow 6.0.0.
46# PILLOW_VERSION was removed in Pillow 9.0.0.
47# Use __version__ instead.
48from . import (
49    ExifTags,
50    ImageMode,
51    TiffTags,
52    UnidentifiedImageError,
53    __version__,
54    _plugins,
55)
56from ._binary import i32le, o32be, o32le
57from ._deprecate import deprecate
58from ._util import DeferredError, is_path
59
60ElementTree: ModuleType | None
61try:
62    from defusedxml import ElementTree
63except ImportError:
64    ElementTree = None
65
66TYPE_CHECKING = False
67if TYPE_CHECKING:
68    from collections.abc import Callable, Iterator, Sequence
69    from types import ModuleType
70    from typing import Any, Literal
71
72logger = logging.getLogger(__name__)
73
74
75class DecompressionBombWarning(RuntimeWarning):
76    pass
77
78
79class DecompressionBombError(Exception):
80    pass
81
82
83WARN_POSSIBLE_FORMATS: bool = False
84
85# Limit to around a quarter gigabyte for a 24-bit (3 bpp) image
86MAX_IMAGE_PIXELS: int | None = int(1024 * 1024 * 1024 // 4 // 3)
87
88
89try:
90    # If the _imaging C module is not present, Pillow will not load.
91    # Note that other modules should not refer to _imaging directly;
92    # import Image and use the Image.core variable instead.
93    # Also note that Image.core is not a publicly documented interface,
94    # and should be considered private and subject to change.
95    from . import _imaging as core
96
97    if __version__ != getattr(core, "PILLOW_VERSION", None):
98        msg = (
99            "The _imaging extension was built for another version of Pillow or PIL:\n"
100            f"Core version: {getattr(core, 'PILLOW_VERSION', None)}\n"
101            f"Pillow version: {__version__}"
102        )
103        raise ImportError(msg)
104
105except ImportError as v:
106    # Explanations for ways that we know we might have an import error
107    if str(v).startswith("Module use of python"):
108        # The _imaging C module is present, but not compiled for
109        # the right version (windows only).  Print a warning, if
110        # possible.
111        warnings.warn(
112            "The _imaging extension was built for another version of Python.",
113            RuntimeWarning,
114        )
115    elif str(v).startswith("The _imaging extension"):
116        warnings.warn(str(v), RuntimeWarning)
117    # Fail here anyway. Don't let people run with a mostly broken Pillow.
118    # see docs/porting.rst
119    raise
120
121
122#
123# Constants
124
125
126# transpose
127class Transpose(IntEnum):
128    FLIP_LEFT_RIGHT = 0
129    FLIP_TOP_BOTTOM = 1
130    ROTATE_90 = 2
131    ROTATE_180 = 3
132    ROTATE_270 = 4
133    TRANSPOSE = 5
134    TRANSVERSE = 6
135
136
137# transforms (also defined in Imaging.h)
138class Transform(IntEnum):
139    AFFINE = 0
140    EXTENT = 1
141    PERSPECTIVE = 2
142    QUAD = 3
143    MESH = 4
144
145
146# resampling filters (also defined in Imaging.h)
147class Resampling(IntEnum):
148    NEAREST = 0
149    BOX = 4
150    BILINEAR = 2
151    HAMMING = 5
152    BICUBIC = 3
153    LANCZOS = 1
154
155
156_filters_support = {
157    Resampling.BOX: 0.5,
158    Resampling.BILINEAR: 1.0,
159    Resampling.HAMMING: 1.0,
160    Resampling.BICUBIC: 2.0,
161    Resampling.LANCZOS: 3.0,
162}
163
164
165# dithers
166class Dither(IntEnum):
167    NONE = 0
168    ORDERED = 1  # Not yet implemented
169    RASTERIZE = 2  # Not yet implemented
170    FLOYDSTEINBERG = 3  # default
171
172
173# palettes/quantizers
174class Palette(IntEnum):
175    WEB = 0
176    ADAPTIVE = 1
177
178
179class Quantize(IntEnum):
180    MEDIANCUT = 0
181    MAXCOVERAGE = 1
182    FASTOCTREE = 2
183    LIBIMAGEQUANT = 3
184
185
186module = sys.modules[__name__]
187for enum in (Transpose, Transform, Resampling, Dither, Palette, Quantize):
188    for item in enum:
189        setattr(module, item.name, item.value)
190
191
192if hasattr(core, "DEFAULT_STRATEGY"):
193    DEFAULT_STRATEGY = core.DEFAULT_STRATEGY
194    FILTERED = core.FILTERED
195    HUFFMAN_ONLY = core.HUFFMAN_ONLY
196    RLE = core.RLE
197    FIXED = core.FIXED
198
199
200# --------------------------------------------------------------------
201# Registries
202
203TYPE_CHECKING = False
204if TYPE_CHECKING:
205    import mmap
206    from xml.etree.ElementTree import Element
207
208    from IPython.lib.pretty import PrettyPrinter
209
210    from . import ImageFile, ImageFilter, ImagePalette, ImageQt, TiffImagePlugin
211    from ._typing import CapsuleType, NumpyArray, StrOrBytesPath
212ID: list[str] = []
213OPEN: dict[
214    str,
215    tuple[
216        Callable[[IO[bytes], str | bytes], ImageFile.ImageFile],
217        Callable[[bytes], bool | str] | None,
218    ],
219] = {}
220MIME: dict[str, str] = {}
221SAVE: dict[str, Callable[[Image, IO[bytes], str | bytes], None]] = {}
222SAVE_ALL: dict[str, Callable[[Image, IO[bytes], str | bytes], None]] = {}
223EXTENSION: dict[str, str] = {}
224DECODERS: dict[str, type[ImageFile.PyDecoder]] = {}
225ENCODERS: dict[str, type[ImageFile.PyEncoder]] = {}
226
227# --------------------------------------------------------------------
228# Modes
229
230_ENDIAN = "<" if sys.byteorder == "little" else ">"
231
232
233def _conv_type_shape(im: Image) -> tuple[tuple[int, ...], str]:
234    m = ImageMode.getmode(im.mode)
235    shape: tuple[int, ...] = (im.height, im.width)
236    extra = len(m.bands)
237    if extra != 1:
238        shape += (extra,)
239    return shape, m.typestr
240
241
242MODES = [
243    "1",
244    "CMYK",
245    "F",
246    "HSV",
247    "I",
248    "I;16",
249    "I;16B",
250    "I;16L",
251    "I;16N",
252    "L",
253    "LA",
254    "La",
255    "LAB",
256    "P",
257    "PA",
258    "RGB",
259    "RGBA",
260    "RGBa",
261    "RGBX",
262    "YCbCr",
263]
264
265# raw modes that may be memory mapped.  NOTE: if you change this, you
266# may have to modify the stride calculation in map.c too!
267_MAPMODES = ("L", "P", "RGBX", "RGBA", "CMYK", "I;16", "I;16L", "I;16B")
268
269
270def getmodebase(mode: str) -> str:
271    """
272    Gets the "base" mode for given mode.  This function returns "L" for
273    images that contain grayscale data, and "RGB" for images that
274    contain color data.
275
276    :param mode: Input mode.
277    :returns: "L" or "RGB".
278    :exception KeyError: If the input mode was not a standard mode.
279    """
280    return ImageMode.getmode(mode).basemode
281
282
283def getmodetype(mode: str) -> str:
284    """
285    Gets the storage type mode.  Given a mode, this function returns a
286    single-layer mode suitable for storing individual bands.
287
288    :param mode: Input mode.
289    :returns: "L", "I", or "F".
290    :exception KeyError: If the input mode was not a standard mode.
291    """
292    return ImageMode.getmode(mode).basetype
293
294
295def getmodebandnames(mode: str) -> tuple[str, ...]:
296    """
297    Gets a list of individual band names.  Given a mode, this function returns
298    a tuple containing the names of individual bands (use
299    :py:method:`~PIL.Image.getmodetype` to get the mode used to store each
300    individual band.
301
302    :param mode: Input mode.
303    :returns: A tuple containing band names.  The length of the tuple
304        gives the number of bands in an image of the given mode.
305    :exception KeyError: If the input mode was not a standard mode.
306    """
307    return ImageMode.getmode(mode).bands
308
309
310def getmodebands(mode: str) -> int:
311    """
312    Gets the number of individual bands for this mode.
313
314    :param mode: Input mode.
315    :returns: The number of bands in this mode.
316    :exception KeyError: If the input mode was not a standard mode.
317    """
318    return len(ImageMode.getmode(mode).bands)
319
320
321# --------------------------------------------------------------------
322# Helpers
323
324_initialized = 0
325
326
327def preinit() -> None:
328    """
329    Explicitly loads BMP, GIF, JPEG, PPM and PPM file format drivers.
330
331    It is called when opening or saving images.
332    """
333
334    global _initialized
335    if _initialized >= 1:
336        return
337
338    try:
339        from . import BmpImagePlugin
340
341        assert BmpImagePlugin
342    except ImportError:
343        pass
344    try:
345        from . import GifImagePlugin
346
347        assert GifImagePlugin
348    except ImportError:
349        pass
350    try:
351        from . import JpegImagePlugin
352
353        assert JpegImagePlugin
354    except ImportError:
355        pass
356    try:
357        from . import PpmImagePlugin
358
359        assert PpmImagePlugin
360    except ImportError:
361        pass
362    try:
363        from . import PngImagePlugin
364
365        assert PngImagePlugin
366    except ImportError:
367        pass
368
369    _initialized = 1
370
371
372def init() -> bool:
373    """
374    Explicitly initializes the Python Imaging Library. This function
375    loads all available file format drivers.
376
377    It is called when opening or saving images if :py:meth:`~preinit()` is
378    insufficient, and by :py:meth:`~PIL.features.pilinfo`.
379    """
380
381    global _initialized
382    if _initialized >= 2:
383        return False
384
385    parent_name = __name__.rpartition(".")[0]
386    for plugin in _plugins:
387        try:
388            logger.debug("Importing %s", plugin)
389            __import__(f"{parent_name}.{plugin}", globals(), locals(), [])
390        except ImportError as e:
391            logger.debug("Image: failed to import %s: %s", plugin, e)
392
393    if OPEN or SAVE:
394        _initialized = 2
395        return True
396    return False
397
398
399# --------------------------------------------------------------------
400# Codec factories (used by tobytes/frombytes and ImageFile.load)
401
402
403def _getdecoder(
404    mode: str, decoder_name: str, args: Any, extra: tuple[Any, ...] = ()
405) -> core.ImagingDecoder | ImageFile.PyDecoder:
406    # tweak arguments
407    if args is None:
408        args = ()
409    elif not isinstance(args, tuple):
410        args = (args,)
411
412    try:
413        decoder = DECODERS[decoder_name]
414    except KeyError:
415        pass
416    else:
417        return decoder(mode, *args + extra)
418
419    try:
420        # get decoder
421        decoder = getattr(core, f"{decoder_name}_decoder")
422    except AttributeError as e:
423        msg = f"decoder {decoder_name} not available"
424        raise OSError(msg) from e
425    return decoder(mode, *args + extra)
426
427
428def _getencoder(
429    mode: str, encoder_name: str, args: Any, extra: tuple[Any, ...] = ()
430) -> core.ImagingEncoder | ImageFile.PyEncoder:
431    # tweak arguments
432    if args is None:
433        args = ()
434    elif not isinstance(args, tuple):
435        args = (args,)
436
437    try:
438        encoder = ENCODERS[encoder_name]
439    except KeyError:
440        pass
441    else:
442        return encoder(mode, *args + extra)
443
444    try:
445        # get encoder
446        encoder = getattr(core, f"{encoder_name}_encoder")
447    except AttributeError as e:
448        msg = f"encoder {encoder_name} not available"
449        raise OSError(msg) from e
450    return encoder(mode, *args + extra)
451
452
453# --------------------------------------------------------------------
454# Simple expression analyzer
455
456
457class ImagePointTransform:
458    """
459    Used with :py:meth:`~PIL.Image.Image.point` for single band images with more than
460    8 bits, this represents an affine transformation, where the value is multiplied by
461    ``scale`` and ``offset`` is added.
462    """
463
464    def __init__(self, scale: float, offset: float) -> None:
465        self.scale = scale
466        self.offset = offset
467
468    def __neg__(self) -> ImagePointTransform:
469        return ImagePointTransform(-self.scale, -self.offset)
470
471    def __add__(self, other: ImagePointTransform | float) -> ImagePointTransform:
472        if isinstance(other, ImagePointTransform):
473            return ImagePointTransform(
474                self.scale + other.scale, self.offset + other.offset
475            )
476        return ImagePointTransform(self.scale, self.offset + other)
477
478    __radd__ = __add__
479
480    def __sub__(self, other: ImagePointTransform | float) -> ImagePointTransform:
481        return self + -other
482
483    def __rsub__(self, other: ImagePointTransform | float) -> ImagePointTransform:
484        return other + -self
485
486    def __mul__(self, other: ImagePointTransform | float) -> ImagePointTransform:
487        if isinstance(other, ImagePointTransform):
488            return NotImplemented
489        return ImagePointTransform(self.scale * other, self.offset * other)
490
491    __rmul__ = __mul__
492
493    def __truediv__(self, other: ImagePointTransform | float) -> ImagePointTransform:
494        if isinstance(other, ImagePointTransform):
495            return NotImplemented
496        return ImagePointTransform(self.scale / other, self.offset / other)
497
498
499def _getscaleoffset(
500    expr: Callable[[ImagePointTransform], ImagePointTransform | float],
501) -> tuple[float, float]:
502    a = expr(ImagePointTransform(1, 0))
503    return (a.scale, a.offset) if isinstance(a, ImagePointTransform) else (0, a)
504
505
506# --------------------------------------------------------------------
507# Implementation wrapper
508
509
510class SupportsGetData(Protocol):
511    def getdata(
512        self,
513    ) -> tuple[Transform, Sequence[int]]: ...
514
515
516class Image:
517    """
518    This class represents an image object.  To create
519    :py:class:`~PIL.Image.Image` objects, use the appropriate factory
520    functions.  There's hardly ever any reason to call the Image constructor
521    directly.
522
523    * :py:func:`~PIL.Image.open`
524    * :py:func:`~PIL.Image.new`
525    * :py:func:`~PIL.Image.frombytes`
526    """
527
528    format: str | None = None
529    format_description: str | None = None
530    _close_exclusive_fp_after_loading = True
531
532    def __init__(self) -> None:
533        # FIXME: take "new" parameters / other image?
534        self._im: core.ImagingCore | DeferredError | None = None
535        self._mode = ""
536        self._size = (0, 0)
537        self.palette: ImagePalette.ImagePalette | None = None
538        self.info: dict[str | tuple[int, int], Any] = {}
539        self.readonly = 0
540        self._exif: Exif | None = None
541
542    @property
543    def im(self) -> core.ImagingCore:
544        if isinstance(self._im, DeferredError):
545            raise self._im.ex
546        assert self._im is not None
547        return self._im
548
549    @im.setter
550    def im(self, im: core.ImagingCore) -> None:
551        self._im = im
552
553    @property
554    def width(self) -> int:
555        return self.size[0]
556
557    @property
558    def height(self) -> int:
559        return self.size[1]
560
561    @property
562    def size(self) -> tuple[int, int]:
563        return self._size
564
565    @property
566    def mode(self) -> str:
567        return self._mode
568
569    @property
570    def readonly(self) -> int:
571        return (self._im and self._im.readonly) or self._readonly
572
573    @readonly.setter
574    def readonly(self, readonly: int) -> None:
575        self._readonly = readonly
576
577    def _new(self, im: core.ImagingCore) -> Image:
578        new = Image()
579        new.im = im
580        new._mode = im.mode
581        new._size = im.size
582        if im.mode in ("P", "PA"):
583            if self.palette:
584                new.palette = self.palette.copy()
585            else:
586                from . import ImagePalette
587
588                new.palette = ImagePalette.ImagePalette()
589        new.info = self.info.copy()
590        return new
591
592    # Context manager support
593    def __enter__(self) -> Image:
594        return self
595
596    def __exit__(self, *args: object) -> None:
597        pass
598
599    def close(self) -> None:
600        """
601        This operation will destroy the image core and release its memory.
602        The image data will be unusable afterward.
603
604        This function is required to close images that have multiple frames or
605        have not had their file read and closed by the
606        :py:meth:`~PIL.Image.Image.load` method. See :ref:`file-handling` for
607        more information.
608        """
609        if getattr(self, "map", None):
610            if sys.platform == "win32" and hasattr(sys, "pypy_version_info"):
611                self.map.close()
612            self.map: mmap.mmap | None = None
613
614        # Instead of simply setting to None, we're setting up a
615        # deferred error that will better explain that the core image
616        # object is gone.
617        self._im = DeferredError(ValueError("Operation on closed image"))
618
619    def _copy(self) -> None:
620        self.load()
621        self.im = self.im.copy()
622        self.readonly = 0
623
624    def _ensure_mutable(self) -> None:
625        if self.readonly:
626            self._copy()
627        else:
628            self.load()
629
630    def _dump(
631        self, file: str | None = None, format: str | None = None, **options: Any
632    ) -> str:
633        suffix = ""
634        if format:
635            suffix = f".{format}"
636
637        if not file:
638            f, filename = tempfile.mkstemp(suffix)
639            os.close(f)
640        else:
641            filename = file
642            if not filename.endswith(suffix):
643                filename = filename + suffix
644
645        self.load()
646
647        if not format or format == "PPM":
648            self.im.save_ppm(filename)
649        else:
650            self.save(filename, format, **options)
651
652        return filename
653
654    def __eq__(self, other: object) -> bool:
655        if self.__class__ is not other.__class__:
656            return False
657        assert isinstance(other, Image)
658        return (
659            self.mode == other.mode
660            and self.size == other.size
661            and self.info == other.info
662            and self.getpalette() == other.getpalette()
663            and self.tobytes() == other.tobytes()
664        )
665
666    def __repr__(self) -> str:
667        return (
668            f"<{self.__class__.__module__}.{self.__class__.__name__} "
669            f"image mode={self.mode} size={self.size[0]}x{self.size[1]} "
670            f"at 0x{id(self):X}>"
671        )
672
673    def _repr_pretty_(self, p: PrettyPrinter, cycle: bool) -> None:
674        """IPython plain text display support"""
675
676        # Same as __repr__ but without unpredictable id(self),
677        # to keep Jupyter notebook `text/plain` output stable.
678        p.text(
679            f"<{self.__class__.__module__}.{self.__class__.__name__} "
680            f"image mode={self.mode} size={self.size[0]}x{self.size[1]}>"
681        )
682
683    def _repr_image(self, image_format: str, **kwargs: Any) -> bytes | None:
684        """Helper function for iPython display hook.
685
686        :param image_format: Image format.
687        :returns: image as bytes, saved into the given format.
688        """
689        b = io.BytesIO()
690        try:
691            self.save(b, image_format, **kwargs)
692        except Exception:
693            return None
694        return b.getvalue()
695
696    def _repr_png_(self) -> bytes | None:
697        """iPython display hook support for PNG format.
698
699        :returns: PNG version of the image as bytes
700        """
701        return self._repr_image("PNG", compress_level=1)
702
703    def _repr_jpeg_(self) -> bytes | None:
704        """iPython display hook support for JPEG format.
705
706        :returns: JPEG version of the image as bytes
707        """
708        return self._repr_image("JPEG")
709
710    @property
711    def __array_interface__(self) -> dict[str, str | bytes | int | tuple[int, ...]]:
712        # numpy array interface support
713        new: dict[str, str | bytes | int | tuple[int, ...]] = {"version": 3}
714        if self.mode == "1":
715            # Binary images need to be extended from bits to bytes
716            # See: https://github.com/python-pillow/Pillow/issues/350
717            new["data"] = self.tobytes("raw", "L")
718        else:
719            new["data"] = self.tobytes()
720        new["shape"], new["typestr"] = _conv_type_shape(self)
721        return new
722
723    def __arrow_c_schema__(self) -> object:
724        self.load()
725        return self.im.__arrow_c_schema__()
726
727    def __arrow_c_array__(
728        self, requested_schema: object | None = None
729    ) -> tuple[object, object]:
730        self.load()
731        return (self.im.__arrow_c_schema__(), self.im.__arrow_c_array__())
732
733    def __getstate__(self) -> list[Any]:
734        im_data = self.tobytes()  # load image first
735        return [self.info, self.mode, self.size, self.getpalette(), im_data]
736
737    def __setstate__(self, state: list[Any]) -> None:
738        Image.__init__(self)
739        info, mode, size, palette, data = state[:5]
740        self.info = info
741        self._mode = mode
742        self._size = size
743        self.im = core.new(mode, size)
744        if mode in ("L", "LA", "P", "PA") and palette:
745            self.putpalette(palette)
746        self.frombytes(data)
747
748    def tobytes(self, encoder_name: str = "raw", *args: Any) -> bytes:
749        """
750        Return image as a bytes object.
751
752        .. warning::
753
754            This method returns raw image data derived from Pillow's internal
755            storage. For compressed image data (e.g. PNG, JPEG) use
756            :meth:`~.save`, with a BytesIO parameter for in-memory data.
757
758        :param encoder_name: What encoder to use.
759
760                             The default is to use the standard "raw" encoder.
761                             To see how this packs pixel data into the returned
762                             bytes, see :file:`libImaging/Pack.c`.
763
764                             A list of C encoders can be seen under codecs
765                             section of the function array in
766                             :file:`_imaging.c`. Python encoders are registered
767                             within the relevant plugins.
768        :param args: Extra arguments to the encoder.
769        :returns: A :py:class:`bytes` object.
770        """
771
772        encoder_args: Any = args
773        if len(encoder_args) == 1 and isinstance(encoder_args[0], tuple):
774            # may pass tuple instead of argument list
775            encoder_args = encoder_args[0]
776
777        if encoder_name == "raw" and encoder_args == ():
778            encoder_args = self.mode
779
780        self.load()
781
782        if self.width == 0 or self.height == 0:
783            return b""
784
785        # unpack data
786        e = _getencoder(self.mode, encoder_name, encoder_args)
787        e.setimage(self.im)
788
789        from . import ImageFile
790
791        bufsize = max(ImageFile.MAXBLOCK, self.size[0] * 4)  # see RawEncode.c
792
793        output = []
794        while True:
795            bytes_consumed, errcode, data = e.encode(bufsize)
796            output.append(data)
797            if errcode:
798                break
799        if errcode < 0:
800            msg = f"encoder error {errcode} in tobytes"
801            raise RuntimeError(msg)
802
803        return b"".join(output)
804
805    def tobitmap(self, name: str = "image") -> bytes:
806        """
807        Returns the image converted to an X11 bitmap.
808
809        .. note:: This method only works for mode "1" images.
810
811        :param name: The name prefix to use for the bitmap variables.
812        :returns: A string containing an X11 bitmap.
813        :raises ValueError: If the mode is not "1"
814        """
815
816        self.load()
817        if self.mode != "1":
818            msg = "not a bitmap"
819            raise ValueError(msg)
820        data = self.tobytes("xbm")
821        return b"".join(
822            [
823                f"#define {name}_width {self.size[0]}\n".encode("ascii"),
824                f"#define {name}_height {self.size[1]}\n".encode("ascii"),
825                f"static char {name}_bits[] = {{\n".encode("ascii"),
826                data,
827                b"};",
828            ]
829        )
830
831    def frombytes(
832        self,
833        data: bytes | bytearray | SupportsArrayInterface,
834        decoder_name: str = "raw",
835        *args: Any,
836    ) -> None:
837        """
838        Loads this image with pixel data from a bytes object.
839
840        This method is similar to the :py:func:`~PIL.Image.frombytes` function,
841        but loads data into this image instead of creating a new image object.
842        """
843
844        if self.width == 0 or self.height == 0:
845            return
846
847        decoder_args: Any = args
848        if len(decoder_args) == 1 and isinstance(decoder_args[0], tuple):
849            # may pass tuple instead of argument list
850            decoder_args = decoder_args[0]
851
852        # default format
853        if decoder_name == "raw" and decoder_args == ():
854            decoder_args = self.mode
855
856        # unpack data
857        d = _getdecoder(self.mode, decoder_name, decoder_args)
858        d.setimage(self.im)
859        s = d.decode(data)
860
861        if s[0] >= 0:
862            msg = "not enough image data"
863            raise ValueError(msg)
864        if s[1] != 0:
865            msg = "cannot decode image data"
866            raise ValueError(msg)
867
868    def load(self) -> core.PixelAccess | None:
869        """
870        Allocates storage for the image and loads the pixel data.  In
871        normal cases, you don't need to call this method, since the
872        Image class automatically loads an opened image when it is
873        accessed for the first time.
874
875        If the file associated with the image was opened by Pillow, then this
876        method will close it. The exception to this is if the image has
877        multiple frames, in which case the file will be left open for seek
878        operations. See :ref:`file-handling` for more information.
879
880        :returns: An image access object.
881        :rtype: :py:class:`.PixelAccess`
882        """
883        if self._im is not None and self.palette and self.palette.dirty:
884            # realize palette
885            mode, arr = self.palette.getdata()
886            self.im.putpalette(self.palette.mode, mode, arr)
887            self.palette.dirty = 0
888            self.palette.rawmode = None
889            if "transparency" in self.info and mode in ("LA", "PA"):
890                if isinstance(self.info["transparency"], int):
891                    self.im.putpalettealpha(self.info["transparency"], 0)
892                else:
893                    self.im.putpalettealphas(self.info["transparency"])
894                self.palette.mode = "RGBA"
895            else:
896                self.palette.palette = self.im.getpalette(
897                    self.palette.mode, self.palette.mode
898                )
899
900        if self._im is not None:
901            return self.im.pixel_access(self.readonly)
902        return None
903
904    def verify(self) -> None:
905        """
906        Verifies the contents of a file. For data read from a file, this
907        method attempts to determine if the file is broken, without
908        actually decoding the image data.  If this method finds any
909        problems, it raises suitable exceptions.  If you need to load
910        the image after using this method, you must reopen the image
911        file.
912        """
913        pass
914
915    def convert(
916        self,
917        mode: str | None = None,
918        matrix: tuple[float, ...] | None = None,
919        dither: Dither | None = None,
920        palette: Palette = Palette.WEB,
921        colors: int = 256,
922    ) -> Image:
923        """
924        Returns a converted copy of this image. For the "P" mode, this
925        method translates pixels through the palette.  If mode is
926        omitted, a mode is chosen so that all information in the image
927        and the palette can be represented without a palette.
928
929        This supports all possible conversions between "L", "RGB" and "CMYK". The
930        ``matrix`` argument only supports "L" and "RGB".
931
932        When translating a color image to grayscale (mode "L"),
933        the library uses the ITU-R 601-2 luma transform::
934
935            L = R * 299/1000 + G * 587/1000 + B * 114/1000
936
937        The default method of converting a grayscale ("L") or "RGB"
938        image into a bilevel (mode "1") image uses Floyd-Steinberg
939        dither to approximate the original image luminosity levels. If
940        dither is ``None``, all values larger than 127 are set to 255 (white),
941        all other values to 0 (black). To use other thresholds, use the
942        :py:meth:`~PIL.Image.Image.point` method.
943
944        When converting from "RGBA" to "P" without a ``matrix`` argument,
945        this passes the operation to :py:meth:`~PIL.Image.Image.quantize`,
946        and ``dither`` and ``palette`` are ignored.
947
948        When converting from "PA", if an "RGBA" palette is present, the alpha
949        channel from the image will be used instead of the values from the palette.
950
951        :param mode: The requested mode. See: :ref:`concept-modes`.
952        :param matrix: An optional conversion matrix.  If given, this
953           should be 4- or 12-tuple containing floating point values.
954        :param dither: Dithering method, used when converting from
955           mode "RGB" to "P" or from "RGB" or "L" to "1".
956           Available methods are :data:`Dither.NONE` or :data:`Dither.FLOYDSTEINBERG`
957           (default). Note that this is not used when ``matrix`` is supplied.
958        :param palette: Palette to use when converting from mode "RGB"
959           to "P".  Available palettes are :data:`Palette.WEB` or
960           :data:`Palette.ADAPTIVE`.
961        :param colors: Number of colors to use for the :data:`Palette.ADAPTIVE`
962           palette. Defaults to 256.
963        :rtype: :py:class:`~PIL.Image.Image`
964        :returns: An :py:class:`~PIL.Image.Image` object.
965        """
966
967        self.load()
968
969        has_transparency = "transparency" in self.info
970        if not mode and self.mode == "P":
971            # determine default mode
972            if self.palette:
973                mode = self.palette.mode
974            else:
975                mode = "RGB"
976            if mode == "RGB" and has_transparency:
977                mode = "RGBA"
978        if not mode or (mode == self.mode and not matrix):
979            return self.copy()
980
981        if matrix:
982            # matrix conversion
983            if mode not in ("L", "RGB"):
984                msg = "illegal conversion"
985                raise ValueError(msg)
986            im = self.im.convert_matrix(mode, matrix)
987            new_im = self._new(im)
988            if has_transparency and self.im.bands == 3:
989                transparency = new_im.info["transparency"]
990
991                def convert_transparency(
992                    m: tuple[float, ...], v: tuple[int, int, int]
993                ) -> int:
994                    value = m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3] * 0.5
995                    return max(0, min(255, int(value)))
996
997                if mode == "L":
998                    transparency = convert_transparency(matrix, transparency)
999                elif len(mode) == 3:
1000                    transparency = tuple(
1001                        convert_transparency(matrix[i * 4 : i * 4 + 4], transparency)
1002                        for i in range(len(transparency))
1003                    )
1004                new_im.info["transparency"] = transparency
1005            return new_im
1006
1007        if self.mode == "RGBA":
1008            if mode == "P":
1009                return self.quantize(colors)
1010            elif mode == "PA":
1011                r, g, b, a = self.split()
1012                rgb = merge("RGB", (r, g, b))
1013                p = rgb.quantize(colors)
1014                return merge("PA", (p, a))
1015
1016        trns = None
1017        delete_trns = False
1018        # transparency handling
1019        if has_transparency:
1020            if (self.mode in ("1", "L", "I", "I;16") and mode in ("LA", "RGBA")) or (
1021                self.mode == "RGB" and mode in ("La", "LA", "RGBa", "RGBA")
1022            ):
1023                # Use transparent conversion to promote from transparent
1024                # color to an alpha channel.
1025                new_im = self._new(
1026                    self.im.convert_transparent(mode, self.info["transparency"])
1027                )
1028                del new_im.info["transparency"]
1029                return new_im
1030            elif self.mode in ("L", "RGB", "P") and mode in ("L", "RGB", "P"):
1031                t = self.info["transparency"]
1032                if isinstance(t, bytes):
1033                    # Dragons. This can't be represented by a single color
1034                    warnings.warn(
1035                        "Palette images with Transparency expressed in bytes should be "
1036                        "converted to RGBA images"
1037                    )
1038                    delete_trns = True
1039                else:
1040                    # get the new transparency color.
1041                    # use existing conversions
1042                    trns_im = new(self.mode, (1, 1))
1043                    if self.mode == "P":
1044                        assert self.palette is not None
1045                        trns_im.putpalette(self.palette, self.palette.mode)
1046                        if isinstance(t, tuple):
1047                            err = "Couldn't allocate a palette color for transparency"
1048                            assert trns_im.palette is not None
1049                            try:
1050                                t = trns_im.palette.getcolor(t, self)
1051                            except ValueError as e:
1052                                if str(e) == "cannot allocate more than 256 colors":
1053                                    # If all 256 colors are in use,
1054                                    # then there is no need for transparency
1055                                    t = None
1056                                else:
1057                                    raise ValueError(err) from e
1058                    if t is None:
1059                        trns = None
1060                    else:
1061                        trns_im.putpixel((0, 0), t)
1062
1063                        if mode in ("L", "RGB"):
1064                            trns_im = trns_im.convert(mode)
1065                        else:
1066                            # can't just retrieve the palette number, got to do it
1067                            # after quantization.
1068                            trns_im = trns_im.convert("RGB")
1069                        trns = trns_im.getpixel((0, 0))
1070
1071            elif self.mode == "P" and mode in ("LA", "PA", "RGBA"):
1072                t = self.info["transparency"]
1073                delete_trns = True
1074
1075                if isinstance(t, bytes):
1076                    self.im.putpalettealphas(t)
1077                elif isinstance(t, int):
1078                    self.im.putpalettealpha(t, 0)
1079                else:
1080                    msg = "Transparency for P mode should be bytes or int"
1081                    raise ValueError(msg)
1082
1083        if mode == "P" and palette == Palette.ADAPTIVE:
1084            im = self.im.quantize(colors)
1085            new_im = self._new(im)
1086            from . import ImagePalette
1087
1088            new_im.palette = ImagePalette.ImagePalette(
1089                "RGB", new_im.im.getpalette("RGB")
1090            )
1091            if delete_trns:
1092                # This could possibly happen if we requantize to fewer colors.
1093                # The transparency would be totally off in that case.
1094                del new_im.info["transparency"]
1095            if trns is not None:
1096                try:
1097                    new_im.info["transparency"] = new_im.palette.getcolor(
1098                        cast(tuple[int, ...], trns),  # trns was converted to RGB
1099                        new_im,
1100                    )
1101                except Exception:
1102                    # if we can't make a transparent color, don't leave the old
1103                    # transparency hanging around to mess us up.
1104                    del new_im.info["transparency"]
1105                    warnings.warn("Couldn't allocate palette entry for transparency")
1106            return new_im
1107
1108        if "LAB" in (self.mode, mode):
1109            im = self
1110            if mode == "LAB":
1111                if im.mode not in ("RGB", "RGBA", "RGBX"):
1112                    im = im.convert("RGBA")
1113                other_mode = im.mode
1114            else:
1115                other_mode = mode
1116            if other_mode in ("RGB", "RGBA", "RGBX"):
1117                from . import ImageCms
1118
1119                srgb = ImageCms.createProfile("sRGB")
1120                lab = ImageCms.createProfile("LAB")
1121                profiles = [lab, srgb] if im.mode == "LAB" else [srgb, lab]
1122                transform = ImageCms.buildTransform(
1123                    profiles[0], profiles[1], im.mode, mode
1124                )
1125                return transform.apply(im)
1126
1127        # colorspace conversion
1128        if dither is None:
1129            dither = Dither.FLOYDSTEINBERG
1130
1131        try:
1132            im = self.im.convert(mode, dither)
1133        except ValueError:
1134            try:
1135                # normalize source image and try again
1136                modebase = getmodebase(self.mode)
1137                if modebase == self.mode:
1138                    raise
1139                im = self.im.convert(modebase)
1140                im = im.convert(mode, dither)
1141            except KeyError as e:
1142                msg = "illegal conversion"
1143                raise ValueError(msg) from e
1144
1145        new_im = self._new(im)
1146        if mode in ("P", "PA") and palette != Palette.ADAPTIVE:
1147            from . import ImagePalette
1148
1149            new_im.palette = ImagePalette.ImagePalette("RGB", im.getpalette("RGB"))
1150        if delete_trns:
1151            # crash fail if we leave a bytes transparency in an rgb/l mode.
1152            del new_im.info["transparency"]
1153        if trns is not None:
1154            if new_im.mode == "P" and new_im.palette:
1155                try:
1156                    new_im.info["transparency"] = new_im.palette.getcolor(
1157                        cast(tuple[int, ...], trns), new_im  # trns was converted to RGB
1158                    )
1159                except ValueError as e:
1160                    del new_im.info["transparency"]
1161                    if str(e) != "cannot allocate more than 256 colors":
1162                        # If all 256 colors are in use,
1163                        # then there is no need for transparency
1164                        warnings.warn(
1165                            "Couldn't allocate palette entry for transparency"
1166                        )
1167            else:
1168                new_im.info["transparency"] = trns
1169        return new_im
1170
1171    def quantize(
1172        self,
1173        colors: int = 256,
1174        method: int | None = None,
1175        kmeans: int = 0,
1176        palette: Image | None = None,
1177        dither: Dither = Dither.FLOYDSTEINBERG,
1178    ) -> Image:
1179        """
1180        Convert the image to 'P' mode with the specified number
1181        of colors.
1182
1183        :param colors: The desired number of colors, <= 256
1184        :param method: :data:`Quantize.MEDIANCUT` (median cut),
1185                       :data:`Quantize.MAXCOVERAGE` (maximum coverage),
1186                       :data:`Quantize.FASTOCTREE` (fast octree),
1187                       :data:`Quantize.LIBIMAGEQUANT` (libimagequant; check support
1188                       using :py:func:`PIL.features.check_feature` with
1189                       ``feature="libimagequant"``).
1190
1191                       By default, :data:`Quantize.MEDIANCUT` will be used.
1192
1193                       The exception to this is RGBA images. :data:`Quantize.MEDIANCUT`
1194                       and :data:`Quantize.MAXCOVERAGE` do not support RGBA images, so
1195                       :data:`Quantize.FASTOCTREE` is used by default instead.
1196        :param kmeans: Integer greater than or equal to zero.
1197        :param palette: Quantize to the palette of given
1198                        :py:class:`PIL.Image.Image`.
1199        :param dither: Dithering method, used when converting from
1200           mode "RGB" to "P" or from "RGB" or "L" to "1".

Showing the first 1,200 of 4247 lines. Download the file for the rest.

Aluode/PerceptionLabPortable · CoolFace