codekingpro/portable-devtools
115k
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(
