mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-26 01:46:18 +03:00
Merge pull request #8066 from radarhere/type_hint
This commit is contained in:
commit
b8532e508b
|
@ -57,6 +57,10 @@ Classes
|
||||||
:undoc-members:
|
:undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
.. autoclass:: PIL.ImageFile.StubHandler()
|
||||||
|
:members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
.. autoclass:: PIL.ImageFile.StubImageFile()
|
.. autoclass:: PIL.ImageFile.StubImageFile()
|
||||||
:members:
|
:members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
|
@ -55,7 +55,7 @@ class AlphaEncoding(IntEnum):
|
||||||
DXT5 = 7
|
DXT5 = 7
|
||||||
|
|
||||||
|
|
||||||
def unpack_565(i):
|
def unpack_565(i: int) -> tuple[int, int, int]:
|
||||||
return ((i >> 11) & 0x1F) << 3, ((i >> 5) & 0x3F) << 2, (i & 0x1F) << 3
|
return ((i >> 11) & 0x1F) << 3, ((i >> 5) & 0x3F) << 2, (i & 0x1F) << 3
|
||||||
|
|
||||||
|
|
||||||
|
@ -284,7 +284,8 @@ class _BLPBaseDecoder(ImageFile.PyDecoder):
|
||||||
raise OSError(msg) from e
|
raise OSError(msg) from e
|
||||||
return -1, 0
|
return -1, 0
|
||||||
|
|
||||||
def _read_blp_header(self):
|
def _read_blp_header(self) -> None:
|
||||||
|
assert self.fd is not None
|
||||||
self.fd.seek(4)
|
self.fd.seek(4)
|
||||||
(self._blp_compression,) = struct.unpack("<i", self._safe_read(4))
|
(self._blp_compression,) = struct.unpack("<i", self._safe_read(4))
|
||||||
|
|
||||||
|
@ -303,10 +304,10 @@ class _BLPBaseDecoder(ImageFile.PyDecoder):
|
||||||
self._blp_offsets = struct.unpack("<16I", self._safe_read(16 * 4))
|
self._blp_offsets = struct.unpack("<16I", self._safe_read(16 * 4))
|
||||||
self._blp_lengths = struct.unpack("<16I", self._safe_read(16 * 4))
|
self._blp_lengths = struct.unpack("<16I", self._safe_read(16 * 4))
|
||||||
|
|
||||||
def _safe_read(self, length):
|
def _safe_read(self, length: int) -> bytes:
|
||||||
return ImageFile._safe_read(self.fd, length)
|
return ImageFile._safe_read(self.fd, length)
|
||||||
|
|
||||||
def _read_palette(self):
|
def _read_palette(self) -> list[tuple[int, int, int, int]]:
|
||||||
ret = []
|
ret = []
|
||||||
for i in range(256):
|
for i in range(256):
|
||||||
try:
|
try:
|
||||||
|
@ -349,29 +350,30 @@ class BLP1Decoder(_BLPBaseDecoder):
|
||||||
msg = f"Unsupported BLP compression {repr(self._blp_encoding)}"
|
msg = f"Unsupported BLP compression {repr(self._blp_encoding)}"
|
||||||
raise BLPFormatError(msg)
|
raise BLPFormatError(msg)
|
||||||
|
|
||||||
def _decode_jpeg_stream(self):
|
def _decode_jpeg_stream(self) -> None:
|
||||||
from .JpegImagePlugin import JpegImageFile
|
from .JpegImagePlugin import JpegImageFile
|
||||||
|
|
||||||
(jpeg_header_size,) = struct.unpack("<I", self._safe_read(4))
|
(jpeg_header_size,) = struct.unpack("<I", self._safe_read(4))
|
||||||
jpeg_header = self._safe_read(jpeg_header_size)
|
jpeg_header = self._safe_read(jpeg_header_size)
|
||||||
|
assert self.fd is not None
|
||||||
self._safe_read(self._blp_offsets[0] - self.fd.tell()) # What IS this?
|
self._safe_read(self._blp_offsets[0] - self.fd.tell()) # What IS this?
|
||||||
data = self._safe_read(self._blp_lengths[0])
|
data = self._safe_read(self._blp_lengths[0])
|
||||||
data = jpeg_header + data
|
data = jpeg_header + data
|
||||||
data = BytesIO(data)
|
image = JpegImageFile(BytesIO(data))
|
||||||
image = JpegImageFile(data)
|
|
||||||
Image._decompression_bomb_check(image.size)
|
Image._decompression_bomb_check(image.size)
|
||||||
if image.mode == "CMYK":
|
if image.mode == "CMYK":
|
||||||
decoder_name, extents, offset, args = image.tile[0]
|
decoder_name, extents, offset, args = image.tile[0]
|
||||||
image.tile = [(decoder_name, extents, offset, (args[0], "CMYK"))]
|
image.tile = [(decoder_name, extents, offset, (args[0], "CMYK"))]
|
||||||
r, g, b = image.convert("RGB").split()
|
r, g, b = image.convert("RGB").split()
|
||||||
image = Image.merge("RGB", (b, g, r))
|
reversed_image = Image.merge("RGB", (b, g, r))
|
||||||
self.set_as_raw(image.tobytes())
|
self.set_as_raw(reversed_image.tobytes())
|
||||||
|
|
||||||
|
|
||||||
class BLP2Decoder(_BLPBaseDecoder):
|
class BLP2Decoder(_BLPBaseDecoder):
|
||||||
def _load(self):
|
def _load(self) -> None:
|
||||||
palette = self._read_palette()
|
palette = self._read_palette()
|
||||||
|
|
||||||
|
assert self.fd is not None
|
||||||
self.fd.seek(self._blp_offsets[0])
|
self.fd.seek(self._blp_offsets[0])
|
||||||
|
|
||||||
if self._blp_compression == 1:
|
if self._blp_compression == 1:
|
||||||
|
|
|
@ -15,7 +15,7 @@ from . import Image, ImageFile
|
||||||
_handler = None
|
_handler = None
|
||||||
|
|
||||||
|
|
||||||
def register_handler(handler):
|
def register_handler(handler: ImageFile.StubHandler) -> None:
|
||||||
"""
|
"""
|
||||||
Install application-specific BUFR image handler.
|
Install application-specific BUFR image handler.
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ class BufrStubImageFile(ImageFile.StubImageFile):
|
||||||
if loader:
|
if loader:
|
||||||
loader.open(self)
|
loader.open(self)
|
||||||
|
|
||||||
def _load(self):
|
def _load(self) -> ImageFile.StubHandler | None:
|
||||||
return _handler
|
return _handler
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ class DcxImageFile(PcxImageFile):
|
||||||
format_description = "Intel DCX"
|
format_description = "Intel DCX"
|
||||||
_close_exclusive_fp_after_loading = False
|
_close_exclusive_fp_after_loading = False
|
||||||
|
|
||||||
def _open(self):
|
def _open(self) -> None:
|
||||||
# Header
|
# Header
|
||||||
s = self.fp.read(4)
|
s = self.fp.read(4)
|
||||||
if not _accept(s):
|
if not _accept(s):
|
||||||
|
@ -58,7 +58,7 @@ class DcxImageFile(PcxImageFile):
|
||||||
self._offset.append(offset)
|
self._offset.append(offset)
|
||||||
|
|
||||||
self._fp = self.fp
|
self._fp = self.fp
|
||||||
self.frame = None
|
self.frame = -1
|
||||||
self.n_frames = len(self._offset)
|
self.n_frames = len(self._offset)
|
||||||
self.is_animated = self.n_frames > 1
|
self.is_animated = self.n_frames > 1
|
||||||
self.seek(0)
|
self.seek(0)
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
from typing import IO
|
||||||
|
|
||||||
from ._binary import o8
|
from ._binary import o8
|
||||||
|
|
||||||
|
@ -25,8 +26,8 @@ class GimpPaletteFile:
|
||||||
|
|
||||||
rawmode = "RGB"
|
rawmode = "RGB"
|
||||||
|
|
||||||
def __init__(self, fp):
|
def __init__(self, fp: IO[bytes]) -> None:
|
||||||
self.palette = [o8(i) * 3 for i in range(256)]
|
palette = [o8(i) * 3 for i in range(256)]
|
||||||
|
|
||||||
if fp.readline()[:12] != b"GIMP Palette":
|
if fp.readline()[:12] != b"GIMP Palette":
|
||||||
msg = "not a GIMP palette file"
|
msg = "not a GIMP palette file"
|
||||||
|
@ -49,9 +50,9 @@ class GimpPaletteFile:
|
||||||
msg = "bad palette entry"
|
msg = "bad palette entry"
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
self.palette[i] = o8(v[0]) + o8(v[1]) + o8(v[2])
|
palette[i] = o8(v[0]) + o8(v[1]) + o8(v[2])
|
||||||
|
|
||||||
self.palette = b"".join(self.palette)
|
self.palette = b"".join(palette)
|
||||||
|
|
||||||
def getpalette(self) -> tuple[bytes, str]:
|
def getpalette(self) -> tuple[bytes, str]:
|
||||||
return self.palette, self.rawmode
|
return self.palette, self.rawmode
|
||||||
|
|
|
@ -15,7 +15,7 @@ from . import Image, ImageFile
|
||||||
_handler = None
|
_handler = None
|
||||||
|
|
||||||
|
|
||||||
def register_handler(handler):
|
def register_handler(handler: ImageFile.StubHandler) -> None:
|
||||||
"""
|
"""
|
||||||
Install application-specific GRIB image handler.
|
Install application-specific GRIB image handler.
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ class GribStubImageFile(ImageFile.StubImageFile):
|
||||||
if loader:
|
if loader:
|
||||||
loader.open(self)
|
loader.open(self)
|
||||||
|
|
||||||
def _load(self):
|
def _load(self) -> ImageFile.StubHandler | None:
|
||||||
return _handler
|
return _handler
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,12 +10,14 @@
|
||||||
#
|
#
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import IO
|
||||||
|
|
||||||
from . import Image, ImageFile
|
from . import Image, ImageFile
|
||||||
|
|
||||||
_handler = None
|
_handler = None
|
||||||
|
|
||||||
|
|
||||||
def register_handler(handler):
|
def register_handler(handler: ImageFile.StubHandler) -> None:
|
||||||
"""
|
"""
|
||||||
Install application-specific HDF5 image handler.
|
Install application-specific HDF5 image handler.
|
||||||
|
|
||||||
|
@ -54,11 +56,11 @@ class HDF5StubImageFile(ImageFile.StubImageFile):
|
||||||
if loader:
|
if loader:
|
||||||
loader.open(self)
|
loader.open(self)
|
||||||
|
|
||||||
def _load(self):
|
def _load(self) -> ImageFile.StubHandler | None:
|
||||||
return _handler
|
return _handler
|
||||||
|
|
||||||
|
|
||||||
def _save(im, fp, filename):
|
def _save(im: Image.Image, fp: IO[bytes], filename: str) -> None:
|
||||||
if _handler is None or not hasattr(_handler, "save"):
|
if _handler is None or not hasattr(_handler, "save"):
|
||||||
msg = "HDF5 save handler not installed"
|
msg = "HDF5 save handler not installed"
|
||||||
raise OSError(msg)
|
raise OSError(msg)
|
||||||
|
|
|
@ -1946,7 +1946,9 @@ class Image:
|
||||||
|
|
||||||
self.im.putband(alpha.im, band)
|
self.im.putband(alpha.im, band)
|
||||||
|
|
||||||
def putdata(self, data, scale=1.0, offset=0.0):
|
def putdata(
|
||||||
|
self, data: Sequence[float], scale: float = 1.0, offset: float = 0.0
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Copies pixel data from a flattened sequence object into the image. The
|
Copies pixel data from a flattened sequence object into the image. The
|
||||||
values should start at the upper left corner (0, 0), continue to the
|
values should start at the upper left corner (0, 0), continue to the
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#
|
#
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import abc
|
||||||
import io
|
import io
|
||||||
import itertools
|
import itertools
|
||||||
import struct
|
import struct
|
||||||
|
@ -347,6 +348,15 @@ class ImageFile(Image.Image):
|
||||||
return self.tell() != frame
|
return self.tell() != frame
|
||||||
|
|
||||||
|
|
||||||
|
class StubHandler:
|
||||||
|
def open(self, im: StubImageFile) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def load(self, im: StubImageFile) -> Image.Image:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class StubImageFile(ImageFile):
|
class StubImageFile(ImageFile):
|
||||||
"""
|
"""
|
||||||
Base class for stub image loaders.
|
Base class for stub image loaders.
|
||||||
|
|
|
@ -18,6 +18,7 @@ from __future__ import annotations
|
||||||
|
|
||||||
import abc
|
import abc
|
||||||
import functools
|
import functools
|
||||||
|
from typing import Sequence
|
||||||
|
|
||||||
|
|
||||||
class Filter:
|
class Filter:
|
||||||
|
@ -79,7 +80,7 @@ class RankFilter(Filter):
|
||||||
|
|
||||||
name = "Rank"
|
name = "Rank"
|
||||||
|
|
||||||
def __init__(self, size, rank):
|
def __init__(self, size: int, rank: int) -> None:
|
||||||
self.size = size
|
self.size = size
|
||||||
self.rank = rank
|
self.rank = rank
|
||||||
|
|
||||||
|
@ -101,7 +102,7 @@ class MedianFilter(RankFilter):
|
||||||
|
|
||||||
name = "Median"
|
name = "Median"
|
||||||
|
|
||||||
def __init__(self, size=3):
|
def __init__(self, size: int = 3) -> None:
|
||||||
self.size = size
|
self.size = size
|
||||||
self.rank = size * size // 2
|
self.rank = size * size // 2
|
||||||
|
|
||||||
|
@ -116,7 +117,7 @@ class MinFilter(RankFilter):
|
||||||
|
|
||||||
name = "Min"
|
name = "Min"
|
||||||
|
|
||||||
def __init__(self, size=3):
|
def __init__(self, size: int = 3) -> None:
|
||||||
self.size = size
|
self.size = size
|
||||||
self.rank = 0
|
self.rank = 0
|
||||||
|
|
||||||
|
@ -131,7 +132,7 @@ class MaxFilter(RankFilter):
|
||||||
|
|
||||||
name = "Max"
|
name = "Max"
|
||||||
|
|
||||||
def __init__(self, size=3):
|
def __init__(self, size: int = 3) -> None:
|
||||||
self.size = size
|
self.size = size
|
||||||
self.rank = size * size - 1
|
self.rank = size * size - 1
|
||||||
|
|
||||||
|
@ -147,7 +148,7 @@ class ModeFilter(Filter):
|
||||||
|
|
||||||
name = "Mode"
|
name = "Mode"
|
||||||
|
|
||||||
def __init__(self, size=3):
|
def __init__(self, size: int = 3) -> None:
|
||||||
self.size = size
|
self.size = size
|
||||||
|
|
||||||
def filter(self, image):
|
def filter(self, image):
|
||||||
|
@ -165,7 +166,7 @@ class GaussianBlur(MultibandFilter):
|
||||||
|
|
||||||
name = "GaussianBlur"
|
name = "GaussianBlur"
|
||||||
|
|
||||||
def __init__(self, radius=2):
|
def __init__(self, radius: float | Sequence[float] = 2) -> None:
|
||||||
self.radius = radius
|
self.radius = radius
|
||||||
|
|
||||||
def filter(self, image):
|
def filter(self, image):
|
||||||
|
@ -228,7 +229,9 @@ class UnsharpMask(MultibandFilter):
|
||||||
|
|
||||||
name = "UnsharpMask"
|
name = "UnsharpMask"
|
||||||
|
|
||||||
def __init__(self, radius=2, percent=150, threshold=3):
|
def __init__(
|
||||||
|
self, radius: float = 2, percent: int = 150, threshold: int = 3
|
||||||
|
) -> None:
|
||||||
self.radius = radius
|
self.radius = radius
|
||||||
self.percent = percent
|
self.percent = percent
|
||||||
self.threshold = threshold
|
self.threshold = threshold
|
||||||
|
|
|
@ -257,7 +257,7 @@ class FreeTypeFont:
|
||||||
"""
|
"""
|
||||||
return self.font.family, self.font.style
|
return self.font.family, self.font.style
|
||||||
|
|
||||||
def getmetrics(self):
|
def getmetrics(self) -> tuple[int, int]:
|
||||||
"""
|
"""
|
||||||
:return: A tuple of the font ascent (the distance from the baseline to
|
:return: A tuple of the font ascent (the distance from the baseline to
|
||||||
the highest outline point) and descent (the distance from the
|
the highest outline point) and descent (the distance from the
|
||||||
|
@ -624,7 +624,7 @@ class FreeTypeFont:
|
||||||
layout_engine=layout_engine or self.layout_engine,
|
layout_engine=layout_engine or self.layout_engine,
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_variation_names(self):
|
def get_variation_names(self) -> list[bytes]:
|
||||||
"""
|
"""
|
||||||
:returns: A list of the named styles in a variation font.
|
:returns: A list of the named styles in a variation font.
|
||||||
:exception OSError: If the font is not a variation font.
|
:exception OSError: If the font is not a variation font.
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import array
|
import array
|
||||||
from typing import Sequence
|
from typing import IO, Sequence
|
||||||
|
|
||||||
from . import GimpGradientFile, GimpPaletteFile, ImageColor, PaletteFile
|
from . import GimpGradientFile, GimpPaletteFile, ImageColor, PaletteFile
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ class ImagePalette:
|
||||||
msg = f"unknown color specifier: {repr(color)}"
|
msg = f"unknown color specifier: {repr(color)}"
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
def save(self, fp):
|
def save(self, fp: str | IO[str]) -> None:
|
||||||
"""Save palette to text file.
|
"""Save palette to text file.
|
||||||
|
|
||||||
.. warning:: This method is experimental.
|
.. warning:: This method is experimental.
|
||||||
|
@ -213,29 +213,29 @@ def make_linear_lut(black, white):
|
||||||
raise NotImplementedError(msg) # FIXME
|
raise NotImplementedError(msg) # FIXME
|
||||||
|
|
||||||
|
|
||||||
def make_gamma_lut(exp):
|
def make_gamma_lut(exp: float) -> list[int]:
|
||||||
return [int(((i / 255.0) ** exp) * 255.0 + 0.5) for i in range(256)]
|
return [int(((i / 255.0) ** exp) * 255.0 + 0.5) for i in range(256)]
|
||||||
|
|
||||||
|
|
||||||
def negative(mode="RGB"):
|
def negative(mode: str = "RGB") -> ImagePalette:
|
||||||
palette = list(range(256 * len(mode)))
|
palette = list(range(256 * len(mode)))
|
||||||
palette.reverse()
|
palette.reverse()
|
||||||
return ImagePalette(mode, [i // len(mode) for i in palette])
|
return ImagePalette(mode, [i // len(mode) for i in palette])
|
||||||
|
|
||||||
|
|
||||||
def random(mode="RGB"):
|
def random(mode: str = "RGB") -> ImagePalette:
|
||||||
from random import randint
|
from random import randint
|
||||||
|
|
||||||
palette = [randint(0, 255) for _ in range(256 * len(mode))]
|
palette = [randint(0, 255) for _ in range(256 * len(mode))]
|
||||||
return ImagePalette(mode, palette)
|
return ImagePalette(mode, palette)
|
||||||
|
|
||||||
|
|
||||||
def sepia(white="#fff0c0"):
|
def sepia(white: str = "#fff0c0") -> ImagePalette:
|
||||||
bands = [make_linear_lut(0, band) for band in ImageColor.getrgb(white)]
|
bands = [make_linear_lut(0, band) for band in ImageColor.getrgb(white)]
|
||||||
return ImagePalette("RGB", [bands[i % 3][i // 3] for i in range(256 * 3)])
|
return ImagePalette("RGB", [bands[i % 3][i // 3] for i in range(256 * 3)])
|
||||||
|
|
||||||
|
|
||||||
def wedge(mode="RGB"):
|
def wedge(mode: str = "RGB") -> ImagePalette:
|
||||||
palette = list(range(256 * len(mode)))
|
palette = list(range(256 * len(mode)))
|
||||||
return ImagePalette(mode, [i // len(mode) for i in palette])
|
return ImagePalette(mode, [i // len(mode) for i in palette])
|
||||||
|
|
||||||
|
|
|
@ -28,10 +28,10 @@ class HDC:
|
||||||
methods.
|
methods.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, dc):
|
def __init__(self, dc: int) -> None:
|
||||||
self.dc = dc
|
self.dc = dc
|
||||||
|
|
||||||
def __int__(self):
|
def __int__(self) -> int:
|
||||||
return self.dc
|
return self.dc
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,10 +42,10 @@ class HWND:
|
||||||
methods, instead of a DC.
|
methods, instead of a DC.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, wnd):
|
def __init__(self, wnd: int) -> None:
|
||||||
self.wnd = wnd
|
self.wnd = wnd
|
||||||
|
|
||||||
def __int__(self):
|
def __int__(self) -> int:
|
||||||
return self.wnd
|
return self.wnd
|
||||||
|
|
||||||
|
|
||||||
|
@ -149,7 +149,9 @@ class Dib:
|
||||||
result = self.image.query_palette(handle)
|
result = self.image.query_palette(handle)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def paste(self, im, box=None):
|
def paste(
|
||||||
|
self, im: Image.Image, box: tuple[int, int, int, int] | None = None
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Paste a PIL image into the bitmap image.
|
Paste a PIL image into the bitmap image.
|
||||||
|
|
||||||
|
@ -169,16 +171,16 @@ class Dib:
|
||||||
else:
|
else:
|
||||||
self.image.paste(im.im)
|
self.image.paste(im.im)
|
||||||
|
|
||||||
def frombytes(self, buffer):
|
def frombytes(self, buffer: bytes) -> None:
|
||||||
"""
|
"""
|
||||||
Load display memory contents from byte data.
|
Load display memory contents from byte data.
|
||||||
|
|
||||||
:param buffer: A buffer containing display data (usually
|
:param buffer: A buffer containing display data (usually
|
||||||
data returned from :py:func:`~PIL.ImageWin.Dib.tobytes`)
|
data returned from :py:func:`~PIL.ImageWin.Dib.tobytes`)
|
||||||
"""
|
"""
|
||||||
return self.image.frombytes(buffer)
|
self.image.frombytes(buffer)
|
||||||
|
|
||||||
def tobytes(self):
|
def tobytes(self) -> bytes:
|
||||||
"""
|
"""
|
||||||
Copy display memory contents to bytes object.
|
Copy display memory contents to bytes object.
|
||||||
|
|
||||||
|
@ -190,7 +192,9 @@ class Dib:
|
||||||
class Window:
|
class Window:
|
||||||
"""Create a Window with the given title size."""
|
"""Create a Window with the given title size."""
|
||||||
|
|
||||||
def __init__(self, title="PIL", width=None, height=None):
|
def __init__(
|
||||||
|
self, title: str = "PIL", width: int | None = None, height: int | None = None
|
||||||
|
) -> None:
|
||||||
self.hwnd = Image.core.createwindow(
|
self.hwnd = Image.core.createwindow(
|
||||||
title, self.__dispatcher, width or 0, height or 0
|
title, self.__dispatcher, width or 0, height or 0
|
||||||
)
|
)
|
||||||
|
|
|
@ -42,6 +42,7 @@ import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import warnings
|
import warnings
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from . import Image, ImageFile
|
from . import Image, ImageFile
|
||||||
from ._binary import i16be as i16
|
from ._binary import i16be as i16
|
||||||
|
@ -54,7 +55,7 @@ from .JpegPresets import presets
|
||||||
# Parser
|
# Parser
|
||||||
|
|
||||||
|
|
||||||
def Skip(self, marker):
|
def Skip(self: JpegImageFile, marker: int) -> None:
|
||||||
n = i16(self.fp.read(2)) - 2
|
n = i16(self.fp.read(2)) - 2
|
||||||
ImageFile._safe_read(self.fp, n)
|
ImageFile._safe_read(self.fp, n)
|
||||||
|
|
||||||
|
@ -191,7 +192,7 @@ def APP(self, marker):
|
||||||
self.info["dpi"] = 72, 72
|
self.info["dpi"] = 72, 72
|
||||||
|
|
||||||
|
|
||||||
def COM(self, marker):
|
def COM(self: JpegImageFile, marker: int) -> None:
|
||||||
#
|
#
|
||||||
# Comment marker. Store these in the APP dictionary.
|
# Comment marker. Store these in the APP dictionary.
|
||||||
n = i16(self.fp.read(2)) - 2
|
n = i16(self.fp.read(2)) - 2
|
||||||
|
@ -202,7 +203,7 @@ def COM(self, marker):
|
||||||
self.applist.append(("COM", s))
|
self.applist.append(("COM", s))
|
||||||
|
|
||||||
|
|
||||||
def SOF(self, marker):
|
def SOF(self: JpegImageFile, marker: int) -> None:
|
||||||
#
|
#
|
||||||
# Start of frame marker. Defines the size and mode of the
|
# Start of frame marker. Defines the size and mode of the
|
||||||
# image. JPEG is colour blind, so we use some simple
|
# image. JPEG is colour blind, so we use some simple
|
||||||
|
@ -250,7 +251,7 @@ def SOF(self, marker):
|
||||||
self.layer.append((t[0], t[1] // 16, t[1] & 15, t[2]))
|
self.layer.append((t[0], t[1] // 16, t[1] & 15, t[2]))
|
||||||
|
|
||||||
|
|
||||||
def DQT(self, marker):
|
def DQT(self: JpegImageFile, marker: int) -> None:
|
||||||
#
|
#
|
||||||
# Define quantization table. Note that there might be more
|
# Define quantization table. Note that there might be more
|
||||||
# than one table in each marker.
|
# than one table in each marker.
|
||||||
|
@ -493,13 +494,13 @@ class JpegImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
self.tile = []
|
self.tile = []
|
||||||
|
|
||||||
def _getexif(self):
|
def _getexif(self) -> dict[str, Any] | None:
|
||||||
return _getexif(self)
|
return _getexif(self)
|
||||||
|
|
||||||
def _getmp(self):
|
def _getmp(self):
|
||||||
return _getmp(self)
|
return _getmp(self)
|
||||||
|
|
||||||
def getxmp(self):
|
def getxmp(self) -> dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Returns a dictionary containing the XMP tags.
|
Returns a dictionary containing the XMP tags.
|
||||||
Requires defusedxml to be installed.
|
Requires defusedxml to be installed.
|
||||||
|
@ -515,7 +516,7 @@ class JpegImageFile(ImageFile.ImageFile):
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
def _getexif(self):
|
def _getexif(self) -> dict[str, Any] | None:
|
||||||
if "exif" not in self.info:
|
if "exif" not in self.info:
|
||||||
return None
|
return None
|
||||||
return self.getexif()._get_merged_dict()
|
return self.getexif()._get_merged_dict()
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from . import EpsImagePlugin
|
from . import EpsImagePlugin
|
||||||
|
|
||||||
|
@ -38,7 +39,7 @@ class PSDraw:
|
||||||
fp = sys.stdout
|
fp = sys.stdout
|
||||||
self.fp = fp
|
self.fp = fp
|
||||||
|
|
||||||
def begin_document(self, id=None):
|
def begin_document(self, id: str | None = None) -> None:
|
||||||
"""Set up printing of a document. (Write PostScript DSC header.)"""
|
"""Set up printing of a document. (Write PostScript DSC header.)"""
|
||||||
# FIXME: incomplete
|
# FIXME: incomplete
|
||||||
self.fp.write(
|
self.fp.write(
|
||||||
|
@ -52,7 +53,7 @@ class PSDraw:
|
||||||
self.fp.write(EDROFF_PS)
|
self.fp.write(EDROFF_PS)
|
||||||
self.fp.write(VDI_PS)
|
self.fp.write(VDI_PS)
|
||||||
self.fp.write(b"%%EndProlog\n")
|
self.fp.write(b"%%EndProlog\n")
|
||||||
self.isofont = {}
|
self.isofont: dict[bytes, int] = {}
|
||||||
|
|
||||||
def end_document(self) -> None:
|
def end_document(self) -> None:
|
||||||
"""Ends printing. (Write PostScript DSC footer.)"""
|
"""Ends printing. (Write PostScript DSC footer.)"""
|
||||||
|
@ -60,22 +61,24 @@ class PSDraw:
|
||||||
if hasattr(self.fp, "flush"):
|
if hasattr(self.fp, "flush"):
|
||||||
self.fp.flush()
|
self.fp.flush()
|
||||||
|
|
||||||
def setfont(self, font, size):
|
def setfont(self, font: str, size: int) -> None:
|
||||||
"""
|
"""
|
||||||
Selects which font to use.
|
Selects which font to use.
|
||||||
|
|
||||||
:param font: A PostScript font name
|
:param font: A PostScript font name
|
||||||
:param size: Size in points.
|
:param size: Size in points.
|
||||||
"""
|
"""
|
||||||
font = bytes(font, "UTF-8")
|
font_bytes = bytes(font, "UTF-8")
|
||||||
if font not in self.isofont:
|
if font_bytes not in self.isofont:
|
||||||
# reencode font
|
# reencode font
|
||||||
self.fp.write(b"/PSDraw-%s ISOLatin1Encoding /%s E\n" % (font, font))
|
self.fp.write(
|
||||||
self.isofont[font] = 1
|
b"/PSDraw-%s ISOLatin1Encoding /%s E\n" % (font_bytes, font_bytes)
|
||||||
|
)
|
||||||
|
self.isofont[font_bytes] = 1
|
||||||
# rough
|
# rough
|
||||||
self.fp.write(b"/F0 %d /PSDraw-%s F\n" % (size, font))
|
self.fp.write(b"/F0 %d /PSDraw-%s F\n" % (size, font_bytes))
|
||||||
|
|
||||||
def line(self, xy0, xy1):
|
def line(self, xy0: tuple[int, int], xy1: tuple[int, int]) -> None:
|
||||||
"""
|
"""
|
||||||
Draws a line between the two points. Coordinates are given in
|
Draws a line between the two points. Coordinates are given in
|
||||||
PostScript point coordinates (72 points per inch, (0, 0) is the lower
|
PostScript point coordinates (72 points per inch, (0, 0) is the lower
|
||||||
|
@ -83,7 +86,7 @@ class PSDraw:
|
||||||
"""
|
"""
|
||||||
self.fp.write(b"%d %d %d %d Vl\n" % (*xy0, *xy1))
|
self.fp.write(b"%d %d %d %d Vl\n" % (*xy0, *xy1))
|
||||||
|
|
||||||
def rectangle(self, box):
|
def rectangle(self, box: tuple[int, int, int, int]) -> None:
|
||||||
"""
|
"""
|
||||||
Draws a rectangle.
|
Draws a rectangle.
|
||||||
|
|
||||||
|
@ -92,18 +95,22 @@ class PSDraw:
|
||||||
"""
|
"""
|
||||||
self.fp.write(b"%d %d M 0 %d %d Vr\n" % box)
|
self.fp.write(b"%d %d M 0 %d %d Vr\n" % box)
|
||||||
|
|
||||||
def text(self, xy, text):
|
def text(self, xy: tuple[int, int], text: str) -> None:
|
||||||
"""
|
"""
|
||||||
Draws text at the given position. You must use
|
Draws text at the given position. You must use
|
||||||
:py:meth:`~PIL.PSDraw.PSDraw.setfont` before calling this method.
|
:py:meth:`~PIL.PSDraw.PSDraw.setfont` before calling this method.
|
||||||
"""
|
"""
|
||||||
text = bytes(text, "UTF-8")
|
text_bytes = bytes(text, "UTF-8")
|
||||||
text = b"\\(".join(text.split(b"("))
|
text_bytes = b"\\(".join(text_bytes.split(b"("))
|
||||||
text = b"\\)".join(text.split(b")"))
|
text_bytes = b"\\)".join(text_bytes.split(b")"))
|
||||||
xy += (text,)
|
self.fp.write(b"%d %d M (%s) S\n" % (xy + (text_bytes,)))
|
||||||
self.fp.write(b"%d %d M (%s) S\n" % xy)
|
|
||||||
|
|
||||||
def image(self, box, im, dpi=None):
|
if TYPE_CHECKING:
|
||||||
|
from . import Image
|
||||||
|
|
||||||
|
def image(
|
||||||
|
self, box: tuple[int, int, int, int], im: Image.Image, dpi: int | None = None
|
||||||
|
) -> None:
|
||||||
"""Draw a PIL image, centered in the given box."""
|
"""Draw a PIL image, centered in the given box."""
|
||||||
# default resolution depends on mode
|
# default resolution depends on mode
|
||||||
if not dpi:
|
if not dpi:
|
||||||
|
|
|
@ -13,7 +13,7 @@ from typing import TYPE_CHECKING, Any, List, NamedTuple, Union
|
||||||
|
|
||||||
# see 7.9.2.2 Text String Type on page 86 and D.3 PDFDocEncoding Character Set
|
# see 7.9.2.2 Text String Type on page 86 and D.3 PDFDocEncoding Character Set
|
||||||
# on page 656
|
# on page 656
|
||||||
def encode_text(s):
|
def encode_text(s: str) -> bytes:
|
||||||
return codecs.BOM_UTF16_BE + s.encode("utf_16_be")
|
return codecs.BOM_UTF16_BE + s.encode("utf_16_be")
|
||||||
|
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ class IndirectReference(IndirectReferenceTuple):
|
||||||
def __ne__(self, other):
|
def __ne__(self, other):
|
||||||
return not (self == other)
|
return not (self == other)
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self) -> int:
|
||||||
return hash((self.object_id, self.generation))
|
return hash((self.object_id, self.generation))
|
||||||
|
|
||||||
|
|
||||||
|
@ -219,7 +219,7 @@ class PdfName:
|
||||||
isinstance(other, PdfName) and other.name == self.name
|
isinstance(other, PdfName) and other.name == self.name
|
||||||
) or other == self.name
|
) or other == self.name
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self) -> int:
|
||||||
return hash(self.name)
|
return hash(self.name)
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
|
@ -402,7 +402,7 @@ class PdfParser:
|
||||||
if f:
|
if f:
|
||||||
self.seek_end()
|
self.seek_end()
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self) -> PdfParser:
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __exit__(self, exc_type, exc_value, traceback):
|
def __exit__(self, exc_type, exc_value, traceback):
|
||||||
|
@ -436,7 +436,7 @@ class PdfParser:
|
||||||
def write_comment(self, s):
|
def write_comment(self, s):
|
||||||
self.f.write(f"% {s}\n".encode())
|
self.f.write(f"% {s}\n".encode())
|
||||||
|
|
||||||
def write_catalog(self):
|
def write_catalog(self) -> IndirectReference:
|
||||||
self.del_root()
|
self.del_root()
|
||||||
self.root_ref = self.next_object_id(self.f.tell())
|
self.root_ref = self.next_object_id(self.f.tell())
|
||||||
self.pages_ref = self.next_object_id(0)
|
self.pages_ref = self.next_object_id(0)
|
||||||
|
|
|
@ -39,7 +39,7 @@ import struct
|
||||||
import warnings
|
import warnings
|
||||||
import zlib
|
import zlib
|
||||||
from enum import IntEnum
|
from enum import IntEnum
|
||||||
from typing import IO
|
from typing import IO, Any
|
||||||
|
|
||||||
from . import Image, ImageChops, ImageFile, ImagePalette, ImageSequence
|
from . import Image, ImageChops, ImageFile, ImagePalette, ImageSequence
|
||||||
from ._binary import i16be as i16
|
from ._binary import i16be as i16
|
||||||
|
@ -1019,7 +1019,7 @@ class PngImageFile(ImageFile.ImageFile):
|
||||||
if self.pyaccess:
|
if self.pyaccess:
|
||||||
self.pyaccess = None
|
self.pyaccess = None
|
||||||
|
|
||||||
def _getexif(self):
|
def _getexif(self) -> dict[str, Any] | None:
|
||||||
if "exif" not in self.info:
|
if "exif" not in self.info:
|
||||||
self.load()
|
self.load()
|
||||||
if "exif" not in self.info and "Raw profile type exif" not in self.info:
|
if "exif" not in self.info and "Raw profile type exif" not in self.info:
|
||||||
|
@ -1032,7 +1032,7 @@ class PngImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
return super().getexif()
|
return super().getexif()
|
||||||
|
|
||||||
def getxmp(self):
|
def getxmp(self) -> dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Returns a dictionary containing the XMP tags.
|
Returns a dictionary containing the XMP tags.
|
||||||
Requires defusedxml to be installed.
|
Requires defusedxml to be installed.
|
||||||
|
@ -1234,7 +1234,7 @@ def _write_multiple_frames(im, fp, chunk, rawmode, default_image, append_images)
|
||||||
seq_num = fdat_chunks.seq_num
|
seq_num = fdat_chunks.seq_num
|
||||||
|
|
||||||
|
|
||||||
def _save_all(im, fp, filename):
|
def _save_all(im: Image.Image, fp: IO[bytes], filename: str) -> None:
|
||||||
_save(im, fp, filename, save_all=True)
|
_save(im, fp, filename, save_all=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1202,7 +1202,7 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
"""Return the current frame number"""
|
"""Return the current frame number"""
|
||||||
return self.__frame
|
return self.__frame
|
||||||
|
|
||||||
def getxmp(self):
|
def getxmp(self) -> dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Returns a dictionary containing the XMP tags.
|
Returns a dictionary containing the XMP tags.
|
||||||
Requires defusedxml to be installed.
|
Requires defusedxml to be installed.
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from . import Image, ImageFile
|
from . import Image, ImageFile
|
||||||
|
|
||||||
|
@ -95,12 +96,12 @@ class WebPImageFile(ImageFile.ImageFile):
|
||||||
# Initialize seek state
|
# Initialize seek state
|
||||||
self._reset(reset=False)
|
self._reset(reset=False)
|
||||||
|
|
||||||
def _getexif(self):
|
def _getexif(self) -> dict[str, Any] | None:
|
||||||
if "exif" not in self.info:
|
if "exif" not in self.info:
|
||||||
return None
|
return None
|
||||||
return self.getexif()._get_merged_dict()
|
return self.getexif()._get_merged_dict()
|
||||||
|
|
||||||
def getxmp(self):
|
def getxmp(self) -> dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Returns a dictionary containing the XMP tags.
|
Returns a dictionary containing the XMP tags.
|
||||||
Requires defusedxml to be installed.
|
Requires defusedxml to be installed.
|
||||||
|
|
|
@ -28,7 +28,7 @@ from ._binary import si32le as _long
|
||||||
_handler = None
|
_handler = None
|
||||||
|
|
||||||
|
|
||||||
def register_handler(handler):
|
def register_handler(handler: ImageFile.StubHandler) -> None:
|
||||||
"""
|
"""
|
||||||
Install application-specific WMF image handler.
|
Install application-specific WMF image handler.
|
||||||
|
|
||||||
|
@ -41,12 +41,12 @@ def register_handler(handler):
|
||||||
if hasattr(Image.core, "drawwmf"):
|
if hasattr(Image.core, "drawwmf"):
|
||||||
# install default handler (windows only)
|
# install default handler (windows only)
|
||||||
|
|
||||||
class WmfHandler:
|
class WmfHandler(ImageFile.StubHandler):
|
||||||
def open(self, im):
|
def open(self, im: ImageFile.StubImageFile) -> None:
|
||||||
im._mode = "RGB"
|
im._mode = "RGB"
|
||||||
self.bbox = im.info["wmf_bbox"]
|
self.bbox = im.info["wmf_bbox"]
|
||||||
|
|
||||||
def load(self, im):
|
def load(self, im: ImageFile.StubImageFile) -> Image.Image:
|
||||||
im.fp.seek(0) # rewind
|
im.fp.seek(0) # rewind
|
||||||
return Image.frombytes(
|
return Image.frombytes(
|
||||||
"RGB",
|
"RGB",
|
||||||
|
@ -147,7 +147,7 @@ class WmfStubImageFile(ImageFile.StubImageFile):
|
||||||
if loader:
|
if loader:
|
||||||
loader.open(self)
|
loader.open(self)
|
||||||
|
|
||||||
def _load(self):
|
def _load(self) -> ImageFile.StubHandler | None:
|
||||||
return _handler
|
return _handler
|
||||||
|
|
||||||
def load(self, dpi=None):
|
def load(self, dpi=None):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user