Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
Image.py4382 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# Mapping from file extension to plugin module name for lazy importing
327_EXTENSION_PLUGIN: dict[str, str] = {
328    # Common formats (preinit)
329    ".bmp": "BmpImagePlugin",
330    ".dib": "BmpImagePlugin",
331    ".gif": "GifImagePlugin",
332    ".jfif": "JpegImagePlugin",
333    ".jpe": "JpegImagePlugin",
334    ".jpg": "JpegImagePlugin",
335    ".jpeg": "JpegImagePlugin",
336    ".pbm": "PpmImagePlugin",
337    ".pgm": "PpmImagePlugin",
338    ".pnm": "PpmImagePlugin",
339    ".ppm": "PpmImagePlugin",
340    ".pfm": "PpmImagePlugin",
341    ".png": "PngImagePlugin",
342    ".apng": "PngImagePlugin",
343    # Less common formats (init)
344    ".avif": "AvifImagePlugin",
345    ".avifs": "AvifImagePlugin",
346    ".blp": "BlpImagePlugin",
347    ".bufr": "BufrStubImagePlugin",
348    ".cur": "CurImagePlugin",
349    ".dcx": "DcxImagePlugin",
350    ".dds": "DdsImagePlugin",
351    ".ps": "EpsImagePlugin",
352    ".eps": "EpsImagePlugin",
353    ".fit": "FitsImagePlugin",
354    ".fits": "FitsImagePlugin",
355    ".fli": "FliImagePlugin",
356    ".flc": "FliImagePlugin",
357    ".fpx": "FpxImagePlugin",
358    ".ftc": "FtexImagePlugin",
359    ".ftu": "FtexImagePlugin",
360    ".gbr": "GbrImagePlugin",
361    ".grib": "GribStubImagePlugin",
362    ".h5": "Hdf5StubImagePlugin",
363    ".hdf": "Hdf5StubImagePlugin",
364    ".icns": "IcnsImagePlugin",
365    ".ico": "IcoImagePlugin",
366    ".im": "ImImagePlugin",
367    ".iim": "IptcImagePlugin",
368    ".jp2": "Jpeg2KImagePlugin",
369    ".j2k": "Jpeg2KImagePlugin",
370    ".jpc": "Jpeg2KImagePlugin",
371    ".jpf": "Jpeg2KImagePlugin",
372    ".jpx": "Jpeg2KImagePlugin",
373    ".j2c": "Jpeg2KImagePlugin",
374    ".mic": "MicImagePlugin",
375    ".mpg": "MpegImagePlugin",
376    ".mpeg": "MpegImagePlugin",
377    ".mpo": "MpoImagePlugin",
378    ".msp": "MspImagePlugin",
379    ".palm": "PalmImagePlugin",
380    ".pcd": "PcdImagePlugin",
381    ".pcx": "PcxImagePlugin",
382    ".pdf": "PdfImagePlugin",
383    ".pxr": "PixarImagePlugin",
384    ".psd": "PsdImagePlugin",
385    ".qoi": "QoiImagePlugin",
386    ".bw": "SgiImagePlugin",
387    ".rgb": "SgiImagePlugin",
388    ".rgba": "SgiImagePlugin",
389    ".sgi": "SgiImagePlugin",
390    ".ras": "SunImagePlugin",
391    ".tga": "TgaImagePlugin",
392    ".icb": "TgaImagePlugin",
393    ".vda": "TgaImagePlugin",
394    ".vst": "TgaImagePlugin",
395    ".tif": "TiffImagePlugin",
396    ".tiff": "TiffImagePlugin",
397    ".webp": "WebPImagePlugin",
398    ".wmf": "WmfImagePlugin",
399    ".emf": "WmfImagePlugin",
400    ".xbm": "XbmImagePlugin",
401    ".xpm": "XpmImagePlugin",
402}
403
404
405def _import_plugin_for_extension(ext: str | bytes) -> bool:
406    """Import only the plugin needed for a specific file extension."""
407    if not ext:
408        return False
409
410    if isinstance(ext, bytes):
411        ext = ext.decode()
412    ext = ext.lower()
413    if ext in EXTENSION:
414        return True
415
416    plugin = _EXTENSION_PLUGIN.get(ext)
417    if plugin is None:
418        return False
419
420    try:
421        logger.debug("Importing %s", plugin)
422        __import__(f"{__spec__.parent}.{plugin}", globals(), locals(), [])
423        return True
424    except ImportError as e:
425        logger.debug("Image: failed to import %s: %s", plugin, e)
426        return False
427
428
429def preinit() -> None:
430    """
431    Explicitly loads BMP, GIF, JPEG, PPM and PNG file format drivers.
432
433    It is called when opening or saving images.
434    """
435
436    global _initialized
437    if _initialized >= 1:
438        return
439
440    try:
441        from . import BmpImagePlugin
442
443        assert BmpImagePlugin
444    except ImportError:
445        pass
446    try:
447        from . import GifImagePlugin
448
449        assert GifImagePlugin
450    except ImportError:
451        pass
452    try:
453        from . import JpegImagePlugin
454
455        assert JpegImagePlugin
456    except ImportError:
457        pass
458    try:
459        from . import PpmImagePlugin
460
461        assert PpmImagePlugin
462    except ImportError:
463        pass
464    try:
465        from . import PngImagePlugin
466
467        assert PngImagePlugin
468    except ImportError:
469        pass
470
471    _initialized = 1
472
473
474def init() -> bool:
475    """
476    Explicitly initializes the Python Imaging Library. This function
477    loads all available file format drivers.
478
479    It is called when opening or saving images if :py:meth:`~preinit()` is
480    insufficient, and by :py:meth:`~PIL.features.pilinfo`.
481    """
482
483    global _initialized
484    if _initialized >= 2:
485        return False
486
487    for plugin in _plugins:
488        try:
489            logger.debug("Importing %s", plugin)
490            __import__(f"{__spec__.parent}.{plugin}", globals(), locals(), [])
491        except ImportError as e:  # noqa: PERF203
492            logger.debug("Image: failed to import %s: %s", plugin, e)
493
494    if OPEN or SAVE:
495        _initialized = 2
496        return True
497    return False
498
499
500# --------------------------------------------------------------------
501# Codec factories (used by tobytes/frombytes and ImageFile.load)
502
503
504def _getdecoder(
505    mode: str, decoder_name: str, args: Any, extra: tuple[Any, ...] = ()
506) -> core.ImagingDecoder | ImageFile.PyDecoder:
507    # tweak arguments
508    if args is None:
509        args = ()
510    elif not isinstance(args, tuple):
511        args = (args,)
512
513    try:
514        decoder = DECODERS[decoder_name]
515    except KeyError:
516        pass
517    else:
518        return decoder(mode, *args + extra)
519
520    try:
521        # get decoder
522        decoder = getattr(core, f"{decoder_name}_decoder")
523    except AttributeError as e:
524        msg = f"decoder {decoder_name} not available"
525        raise OSError(msg) from e
526    return decoder(mode, *args + extra)
527
528
529def _getencoder(
530    mode: str, encoder_name: str, args: Any, extra: tuple[Any, ...] = ()
531) -> core.ImagingEncoder | ImageFile.PyEncoder:
532    # tweak arguments
533    if args is None:
534        args = ()
535    elif not isinstance(args, tuple):
536        args = (args,)
537
538    try:
539        encoder = ENCODERS[encoder_name]
540    except KeyError:
541        pass
542    else:
543        return encoder(mode, *args + extra)
544
545    try:
546        # get encoder
547        encoder = getattr(core, f"{encoder_name}_encoder")
548    except AttributeError as e:
549        msg = f"encoder {encoder_name} not available"
550        raise OSError(msg) from e
551    return encoder(mode, *args + extra)
552
553
554# --------------------------------------------------------------------
555# Simple expression analyzer
556
557
558class ImagePointTransform:
559    """
560    Used with :py:meth:`~PIL.Image.Image.point` for single band images with more than
561    8 bits, this represents an affine transformation, where the value is multiplied by
562    ``scale`` and ``offset`` is added.
563    """
564
565    def __init__(self, scale: float, offset: float) -> None:
566        self.scale = scale
567        self.offset = offset
568
569    def __neg__(self) -> ImagePointTransform:
570        return ImagePointTransform(-self.scale, -self.offset)
571
572    def __add__(self, other: ImagePointTransform | float) -> ImagePointTransform:
573        if isinstance(other, ImagePointTransform):
574            return ImagePointTransform(
575                self.scale + other.scale, self.offset + other.offset
576            )
577        return ImagePointTransform(self.scale, self.offset + other)
578
579    __radd__ = __add__
580
581    def __sub__(self, other: ImagePointTransform | float) -> ImagePointTransform:
582        return self + -other
583
584    def __rsub__(self, other: ImagePointTransform | float) -> ImagePointTransform:
585        return other + -self
586
587    def __mul__(self, other: ImagePointTransform | float) -> ImagePointTransform:
588        if isinstance(other, ImagePointTransform):
589            return NotImplemented
590        return ImagePointTransform(self.scale * other, self.offset * other)
591
592    __rmul__ = __mul__
593
594    def __truediv__(self, other: ImagePointTransform | float) -> ImagePointTransform:
595        if isinstance(other, ImagePointTransform):
596            return NotImplemented
597        return ImagePointTransform(self.scale / other, self.offset / other)
598
599
600def _getscaleoffset(
601    expr: Callable[[ImagePointTransform], ImagePointTransform | float],
602) -> tuple[float, float]:
603    a = expr(ImagePointTransform(1, 0))
604    return (a.scale, a.offset) if isinstance(a, ImagePointTransform) else (0, a)
605
606
607# --------------------------------------------------------------------
608# Implementation wrapper
609
610
611class SupportsGetData(Protocol):
612    def getdata(
613        self,
614    ) -> tuple[Transform, Sequence[int]]: ...
615
616
617class Image:
618    """
619    This class represents an image object.  To create
620    :py:class:`~PIL.Image.Image` objects, use the appropriate factory
621    functions.  There's hardly ever any reason to call the Image constructor
622    directly.
623
624    * :py:func:`~PIL.Image.open`
625    * :py:func:`~PIL.Image.new`
626    * :py:func:`~PIL.Image.frombytes`
627    """
628
629    format: str | None = None
630    format_description: str | None = None
631    _close_exclusive_fp_after_loading = True
632
633    def __init__(self) -> None:
634        # FIXME: take "new" parameters / other image?
635        self._im: core.ImagingCore | DeferredError | None = None
636        self._mode = ""
637        self._size = (0, 0)
638        self.palette: ImagePalette.ImagePalette | None = None
639        self.info: dict[str | tuple[int, int], Any] = {}
640        self.readonly = 0
641        self._exif: Exif | None = None
642
643    @property
644    def im(self) -> core.ImagingCore:
645        if isinstance(self._im, DeferredError):
646            raise self._im.ex
647        assert self._im is not None
648        return self._im
649
650    @im.setter
651    def im(self, im: core.ImagingCore) -> None:
652        self._im = im
653
654    @property
655    def width(self) -> int:
656        return self.size[0]
657
658    @property
659    def height(self) -> int:
660        return self.size[1]
661
662    @property
663    def size(self) -> tuple[int, int]:
664        return self._size
665
666    @property
667    def mode(self) -> str:
668        return self._mode
669
670    @property
671    def readonly(self) -> int:
672        return (self._im and self._im.readonly) or self._readonly
673
674    @readonly.setter
675    def readonly(self, readonly: int) -> None:
676        self._readonly = readonly
677
678    def _new(self, im: core.ImagingCore) -> Image:
679        new = Image()
680        new.im = im
681        new._mode = im.mode
682        new._size = im.size
683        if im.mode in ("P", "PA"):
684            if self.palette:
685                new.palette = self.palette.copy()
686            else:
687                from . import ImagePalette
688
689                new.palette = ImagePalette.ImagePalette()
690        new.info = self.info.copy()
691        return new
692
693    # Context manager support
694    def __enter__(self) -> Image:
695        return self
696
697    def __exit__(self, *args: object) -> None:
698        pass
699
700    def close(self) -> None:
701        """
702        This operation will destroy the image core and release its memory.
703        The image data will be unusable afterward.
704
705        This function is required to close images that have multiple frames or
706        have not had their file read and closed by the
707        :py:meth:`~PIL.Image.Image.load` method. See :ref:`file-handling` for
708        more information.
709        """
710        if getattr(self, "map", None):
711            if sys.platform == "win32" and hasattr(sys, "pypy_version_info"):
712                self.map.close()
713            self.map: mmap.mmap | None = None
714
715        # Instead of simply setting to None, we're setting up a
716        # deferred error that will better explain that the core image
717        # object is gone.
718        self._im = DeferredError(ValueError("Operation on closed image"))
719
720    def _copy(self) -> None:
721        self.load()
722        self.im = self.im.copy()
723        self.readonly = 0
724
725    def _ensure_mutable(self) -> None:
726        if self.readonly:
727            self._copy()
728        else:
729            self.load()
730
731    def _dump(
732        self, file: str | None = None, format: str | None = None, **options: Any
733    ) -> str:
734        suffix = ""
735        if format:
736            suffix = f".{format}"
737
738        if not file:
739            f, filename = tempfile.mkstemp(suffix)
740            os.close(f)
741        else:
742            filename = file
743            if not filename.endswith(suffix):
744                filename = filename + suffix
745
746        self.load()
747
748        if not format or format == "PPM":
749            self.im.save_ppm(filename)
750        else:
751            self.save(filename, format, **options)
752
753        return filename
754
755    def __eq__(self, other: object) -> bool:
756        if self.__class__ is not other.__class__:
757            return False
758        assert isinstance(other, Image)
759        return (
760            self.mode == other.mode
761            and self.size == other.size
762            and self.info == other.info
763            and self.getpalette() == other.getpalette()
764            and self.tobytes() == other.tobytes()
765        )
766
767    def __repr__(self) -> str:
768        return (
769            f"<{self.__class__.__module__}.{self.__class__.__name__} "
770            f"image mode={self.mode} size={self.size[0]}x{self.size[1]} "
771            f"at 0x{id(self):X}>"
772        )
773
774    def _repr_pretty_(self, p: PrettyPrinter, cycle: bool) -> None:
775        """IPython plain text display support"""
776
777        # Same as __repr__ but without unpredictable id(self),
778        # to keep Jupyter notebook `text/plain` output stable.
779        p.text(
780            f"<{self.__class__.__module__}.{self.__class__.__name__} "
781            f"image mode={self.mode} size={self.size[0]}x{self.size[1]}>"
782        )
783
784    def _repr_image(self, image_format: str, **kwargs: Any) -> bytes | None:
785        """Helper function for iPython display hook.
786
787        :param image_format: Image format.
788        :returns: image as bytes, saved into the given format.
789        """
790        b = io.BytesIO()
791        try:
792            self.save(b, image_format, **kwargs)
793        except Exception:
794            return None
795        return b.getvalue()
796
797    def _repr_png_(self) -> bytes | None:
798        """iPython display hook support for PNG format.
799
800        :returns: PNG version of the image as bytes
801        """
802        return self._repr_image("PNG", compress_level=1)
803
804    def _repr_jpeg_(self) -> bytes | None:
805        """iPython display hook support for JPEG format.
806
807        :returns: JPEG version of the image as bytes
808        """
809        return self._repr_image("JPEG")
810
811    @property
812    def __array_interface__(self) -> dict[str, str | bytes | int | tuple[int, ...]]:
813        # numpy array interface support
814        new: dict[str, str | bytes | int | tuple[int, ...]] = {"version": 3}
815        if self.mode == "1":
816            # Binary images need to be extended from bits to bytes
817            # See: https://github.com/python-pillow/Pillow/issues/350
818            new["data"] = self.tobytes("raw", "L")
819        else:
820            new["data"] = self.tobytes()
821        new["shape"], new["typestr"] = _conv_type_shape(self)
822        return new
823
824    def __arrow_c_schema__(self) -> object:
825        self.load()
826        return self.im.__arrow_c_schema__()
827
828    def __arrow_c_array__(
829        self, requested_schema: object | None = None
830    ) -> tuple[object, object]:
831        self.load()
832        return (self.im.__arrow_c_schema__(), self.im.__arrow_c_array__())
833
834    def __getstate__(self) -> list[Any]:
835        im_data = self.tobytes()  # load image first
836        return [self.info, self.mode, self.size, self.getpalette(), im_data]
837
838    def __setstate__(self, state: list[Any]) -> None:
839        Image.__init__(self)
840        info, mode, size, palette, data = state[:5]
841        self.info = info
842        self._mode = mode
843        self._size = size
844        self.im = core.new(mode, size)
845        if mode in ("L", "LA", "P", "PA") and palette:
846            self.putpalette(palette)
847        self.frombytes(data)
848
849    def tobytes(self, encoder_name: str = "raw", *args: Any) -> bytes:
850        """
851        Return image as a bytes object.
852
853        .. warning::
854
855            This method returns raw image data derived from Pillow's internal
856            storage. For compressed image data (e.g. PNG, JPEG) use
857            :meth:`~.save`, with a BytesIO parameter for in-memory data.
858
859        :param encoder_name: What encoder to use.
860
861                             The default is to use the standard "raw" encoder.
862                             To see how this packs pixel data into the returned
863                             bytes, see :file:`libImaging/Pack.c`.
864
865                             A list of C encoders can be seen under codecs
866                             section of the function array in
867                             :file:`_imaging.c`. Python encoders are registered
868                             within the relevant plugins.
869        :param args: Extra arguments to the encoder.
870        :returns: A :py:class:`bytes` object.
871        """
872
873        encoder_args: Any = args
874        if len(encoder_args) == 1 and isinstance(encoder_args[0], tuple):
875            # may pass tuple instead of argument list
876            encoder_args = encoder_args[0]
877
878        if encoder_name == "raw" and encoder_args == ():
879            encoder_args = self.mode
880
881        self.load()
882
883        if self.width == 0 or self.height == 0:
884            return b""
885
886        # unpack data
887        e = _getencoder(self.mode, encoder_name, encoder_args)
888        e.setimage(self.im, (0, 0) + self.size)
889
890        from . import ImageFile
891
892        bufsize = max(ImageFile.MAXBLOCK, self.size[0] * 4)  # see RawEncode.c
893
894        output = []
895        while True:
896            bytes_consumed, errcode, data = e.encode(bufsize)
897            output.append(data)
898            if errcode:
899                break
900        if errcode < 0:
901            msg = f"encoder error {errcode} in tobytes"
902            raise RuntimeError(msg)
903
904        return b"".join(output)
905
906    def tobitmap(self, name: str = "image") -> bytes:
907        """
908        Returns the image converted to an X11 bitmap.
909
910        .. note:: This method only works for mode "1" images.
911
912        :param name: The name prefix to use for the bitmap variables.
913        :returns: A string containing an X11 bitmap.
914        :raises ValueError: If the mode is not "1"
915        """
916
917        self.load()
918        if self.mode != "1":
919            msg = "not a bitmap"
920            raise ValueError(msg)
921        data = self.tobytes("xbm")
922        return b"".join(
923            [
924                f"#define {name}_width {self.size[0]}\n".encode("ascii"),
925                f"#define {name}_height {self.size[1]}\n".encode("ascii"),
926                f"static char {name}_bits[] = {{\n".encode("ascii"),
927                data,
928                b"};",
929            ]
930        )
931
932    def frombytes(
933        self,
934        data: bytes | bytearray | SupportsArrayInterface,
935        decoder_name: str = "raw",
936        *args: Any,
937    ) -> None:
938        """
939        Loads this image with pixel data from a bytes object.
940
941        This method is similar to the :py:func:`~PIL.Image.frombytes` function,
942        but loads data into this image instead of creating a new image object.
943        """
944
945        if self.width == 0 or self.height == 0:
946            return
947
948        decoder_args: Any = args
949        if len(decoder_args) == 1 and isinstance(decoder_args[0], tuple):
950            # may pass tuple instead of argument list
951            decoder_args = decoder_args[0]
952
953        # default format
954        if decoder_name == "raw" and decoder_args == ():
955            decoder_args = self.mode
956
957        # unpack data
958        d = _getdecoder(self.mode, decoder_name, decoder_args)
959        d.setimage(self.im, (0, 0) + self.size)
960        s = d.decode(data)
961
962        if s[0] >= 0:
963            msg = "not enough image data"
964            raise ValueError(msg)
965        if s[1] != 0:
966            msg = "cannot decode image data"
967            raise ValueError(msg)
968
969    def load(self) -> core.PixelAccess | None:
970        """
971        Allocates storage for the image and loads the pixel data.  In
972        normal cases, you don't need to call this method, since the
973        Image class automatically loads an opened image when it is
974        accessed for the first time.
975
976        If the file associated with the image was opened by Pillow, then this
977        method will close it. The exception to this is if the image has
978        multiple frames, in which case the file will be left open for seek
979        operations. See :ref:`file-handling` for more information.
980
981        :returns: An image access object.
982        :rtype: :py:class:`.PixelAccess`
983        """
984        if self._im is not None and self.palette and self.palette.dirty:
985            # realize palette
986            mode, arr = self.palette.getdata()
987            self.im.putpalette(self.palette.mode, mode, arr)
988            self.palette.dirty = 0
989            self.palette.rawmode = None
990            if "transparency" in self.info and mode in ("LA", "PA"):
991                if isinstance(self.info["transparency"], int):
992                    self.im.putpalettealpha(self.info["transparency"], 0)
993                else:
994                    self.im.putpalettealphas(self.info["transparency"])
995                self.palette.mode = "RGBA"
996            elif self.palette.mode != mode:
997                # If the palette rawmode is different to the mode,
998                # then update the Python palette data
999                self.palette.palette = self.im.getpalette(
1000                    self.palette.mode, self.palette.mode
1001                )
1002
1003        if self._im is not None:
1004            return self.im.pixel_access(self.readonly)
1005        return None
1006
1007    def verify(self) -> None:
1008        """
1009        Verifies the contents of a file. For data read from a file, this
1010        method attempts to determine if the file is broken, without
1011        actually decoding the image data.  If this method finds any
1012        problems, it raises suitable exceptions.  If you need to load
1013        the image after using this method, you must reopen the image
1014        file.
1015        """
1016        pass
1017
1018    def convert(
1019        self,
1020        mode: str | None = None,
1021        matrix: tuple[float, ...] | None = None,
1022        dither: Dither | None = None,
1023        palette: Palette = Palette.WEB,
1024        colors: int = 256,
1025    ) -> Image:
1026        """
1027        Returns a converted copy of this image. For the "P" mode, this
1028        method translates pixels through the palette.  If mode is
1029        omitted, a mode is chosen so that all information in the image
1030        and the palette can be represented without a palette.
1031
1032        This supports all possible conversions between "L", "RGB" and "CMYK". The
1033        ``matrix`` argument only supports "L" and "RGB".
1034
1035        When translating a color image to grayscale (mode "L"),
1036        the library uses the ITU-R 601-2 luma transform::
1037
1038            L = R * 299/1000 + G * 587/1000 + B * 114/1000
1039
1040        The default method of converting a grayscale ("L") or "RGB"
1041        image into a bilevel (mode "1") image uses Floyd-Steinberg
1042        dither to approximate the original image luminosity levels. If
1043        dither is ``None``, all values larger than 127 are set to 255 (white),
1044        all other values to 0 (black). To use other thresholds, use the
1045        :py:meth:`~PIL.Image.Image.point` method.
1046
1047        When converting from "RGBA" to "P" without a ``matrix`` argument,
1048        this passes the operation to :py:meth:`~PIL.Image.Image.quantize`,
1049        and ``dither`` and ``palette`` are ignored.
1050
1051        When converting from "PA", if an "RGBA" palette is present, the alpha
1052        channel from the image will be used instead of the values from the palette.
1053
1054        :param mode: The requested mode. See: :ref:`concept-modes`.
1055        :param matrix: An optional conversion matrix.  If given, this
1056           should be 4- or 12-tuple containing floating point values.
1057        :param dither: Dithering method, used when converting from
1058           mode "RGB" to "P" or from "RGB" or "L" to "1".
1059           Available methods are :data:`Dither.NONE` or :data:`Dither.FLOYDSTEINBERG`
1060           (default). Note that this is not used when ``matrix`` is supplied.
1061        :param palette: Palette to use when converting from mode "RGB"
1062           to "P".  Available palettes are :data:`Palette.WEB` or
1063           :data:`Palette.ADAPTIVE`.
1064        :param colors: Number of colors to use for the :data:`Palette.ADAPTIVE`
1065           palette. Defaults to 256.
1066        :rtype: :py:class:`~PIL.Image.Image`
1067        :returns: An :py:class:`~PIL.Image.Image` object.
1068        """
1069
1070        self.load()
1071
1072        has_transparency = "transparency" in self.info
1073        if not mode and self.mode == "P":
1074            # determine default mode
1075            if self.palette:
1076                mode = self.palette.mode
1077            else:
1078                mode = "RGB"
1079            if mode == "RGB" and has_transparency:
1080                mode = "RGBA"
1081        if not mode or (mode == self.mode and not matrix):
1082            return self.copy()
1083
1084        if matrix:
1085            # matrix conversion
1086            if mode not in ("L", "RGB"):
1087                msg = "illegal conversion"
1088                raise ValueError(msg)
1089            im = self.im.convert_matrix(mode, matrix)
1090            new_im = self._new(im)
1091            if has_transparency and self.im.bands == 3:
1092                transparency = new_im.info["transparency"]
1093
1094                def convert_transparency(
1095                    m: tuple[float, ...], v: tuple[int, int, int]
1096                ) -> int:
1097                    value = m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3] * 0.5
1098                    return max(0, min(255, int(value)))
1099
1100                if mode == "L":
1101                    transparency = convert_transparency(matrix, transparency)
1102                elif len(mode) == 3:
1103                    transparency = tuple(
1104                        convert_transparency(matrix[i * 4 : i * 4 + 4], transparency)
1105                        for i in range(len(transparency))
1106                    )
1107                new_im.info["transparency"] = transparency
1108            return new_im
1109
1110        if self.mode == "RGBA":
1111            if mode == "P":
1112                return self.quantize(colors)
1113            elif mode == "PA":
1114                r, g, b, a = self.split()
1115                rgb = merge("RGB", (r, g, b))
1116                p = rgb.quantize(colors)
1117                return merge("PA", (p, a))
1118
1119        trns = None
1120        delete_trns = False
1121        # transparency handling
1122        if has_transparency:
1123            if (self.mode in ("1", "L", "I", "I;16") and mode in ("LA", "RGBA")) or (
1124                self.mode == "RGB" and mode in ("La", "LA", "RGBa", "RGBA")
1125            ):
1126                # Use transparent conversion to promote from transparent
1127                # color to an alpha channel.
1128                new_im = self._new(
1129                    self.im.convert_transparent(mode, self.info["transparency"])
1130                )
1131                del new_im.info["transparency"]
1132                return new_im
1133            elif self.mode in ("L", "RGB", "P") and mode in ("L", "RGB", "P"):
1134                t = self.info["transparency"]
1135                if isinstance(t, bytes):
1136                    # Dragons. This can't be represented by a single color
1137                    warnings.warn(
1138                        "Palette images with Transparency expressed in bytes should be "
1139                        "converted to RGBA images"
1140                    )
1141                    delete_trns = True
1142                else:
1143                    # get the new transparency color.
1144                    # use existing conversions
1145                    trns_im = new(self.mode, (1, 1))
1146                    if self.mode == "P":
1147                        assert self.palette is not None
1148                        trns_im.putpalette(self.palette, self.palette.mode)
1149                        if isinstance(t, tuple):
1150                            err = "Couldn't allocate a palette color for transparency"
1151                            assert trns_im.palette is not None
1152                            try:
1153                                t = trns_im.palette.getcolor(t, self)
1154                            except ValueError as e:
1155                                if str(e) == "cannot allocate more than 256 colors":
1156                                    # If all 256 colors are in use,
1157                                    # then there is no need for transparency
1158                                    t = None
1159                                else:
1160                                    raise ValueError(err) from e
1161                    if t is None:
1162                        trns = None
1163                    else:
1164                        trns_im.putpixel((0, 0), t)
1165
1166                        if mode in ("L", "RGB"):
1167                            trns_im = trns_im.convert(mode)
1168                        else:
1169                            # can't just retrieve the palette number, got to do it
1170                            # after quantization.
1171                            trns_im = trns_im.convert("RGB")
1172                        trns = trns_im.getpixel((0, 0))
1173
1174            elif self.mode == "P" and mode in ("LA", "PA", "RGBA"):
1175                t = self.info["transparency"]
1176                delete_trns = True
1177
1178                if isinstance(t, bytes):
1179                    self.im.putpalettealphas(t)
1180                elif isinstance(t, int):
1181                    self.im.putpalettealpha(t, 0)
1182                else:
1183                    msg = "Transparency for P mode should be bytes or int"
1184                    raise ValueError(msg)
1185
1186        if mode == "P" and palette == Palette.ADAPTIVE:
1187            im = self.im.quantize(colors)
1188            new_im = self._new(im)
1189            from . import ImagePalette
1190
1191            new_im.palette = ImagePalette.ImagePalette(
1192                "RGB", new_im.im.getpalette("RGB")
1193            )
1194            if delete_trns:
1195                # This could possibly happen if we requantize to fewer colors.
1196                # The transparency would be totally off in that case.
1197                del new_im.info["transparency"]
1198            if trns is not None:
1199                try:
1200                    new_im.info["transparency"] = new_im.palette.getcolor(

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

codekingpro/portable-devtools · Team Ai