From 9227cb284dc3f1689852094765e088ef99cce609 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 26 Dec 2023 10:56:29 +1100 Subject: [PATCH] Added ImageType as type alias for Image.Image --- src/PIL/Image.py | 2 ++ src/PIL/ImageChops.py | 60 ++++++++++++++++++++++++---------------- src/PIL/ImageSequence.py | 12 ++++---- 3 files changed, 44 insertions(+), 30 deletions(-) diff --git a/src/PIL/Image.py b/src/PIL/Image.py index d04801cba75..bf966d45922 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -2846,6 +2846,8 @@ def toqpixmap(self): raise ImportError(msg) return ImageQt.toqpixmap(self) +ImageType = Image + # -------------------------------------------------------------------- # Abstract handlers. diff --git a/src/PIL/ImageChops.py b/src/PIL/ImageChops.py index 29a5c995fd8..416c7244e3a 100644 --- a/src/PIL/ImageChops.py +++ b/src/PIL/ImageChops.py @@ -20,7 +20,7 @@ from . import Image -def constant(image: Image.Image, value: int) -> Image.Image: +def constant(image: Image.ImageType, value: int) -> Image.ImageType: """Fill a channel with a given gray level. :rtype: :py:class:`~PIL.Image.Image` @@ -29,7 +29,7 @@ def constant(image: Image.Image, value: int) -> Image.Image: return Image.new("L", image.size, value) -def duplicate(image: Image.Image) -> Image.Image: +def duplicate(image: Image.ImageType) -> Image.ImageType: """Copy a channel. Alias for :py:meth:`PIL.Image.Image.copy`. :rtype: :py:class:`~PIL.Image.Image` @@ -38,7 +38,7 @@ def duplicate(image: Image.Image) -> Image.Image: return image.copy() -def invert(image: Image.Image) -> Image.Image: +def invert(image: Image.ImageType) -> Image.ImageType: """ Invert an image (channel). :: @@ -51,7 +51,7 @@ def invert(image: Image.Image) -> Image.Image: return image._new(image.im.chop_invert()) -def lighter(image1: Image.Image, image2: Image.Image) -> Image.Image: +def lighter(image1: Image.ImageType, image2: Image.ImageType) -> Image.ImageType: """ Compares the two images, pixel by pixel, and returns a new image containing the lighter values. :: @@ -66,7 +66,7 @@ def lighter(image1: Image.Image, image2: Image.Image) -> Image.Image: return image1._new(image1.im.chop_lighter(image2.im)) -def darker(image1: Image.Image, image2: Image.Image) -> Image.Image: +def darker(image1: Image.ImageType, image2: Image.ImageType) -> Image.ImageType: """ Compares the two images, pixel by pixel, and returns a new image containing the darker values. :: @@ -81,7 +81,7 @@ def darker(image1: Image.Image, image2: Image.Image) -> Image.Image: return image1._new(image1.im.chop_darker(image2.im)) -def difference(image1: Image.Image, image2: Image.Image) -> Image.Image: +def difference(image1: Image.ImageType, image2: Image.ImageType) -> Image.ImageType: """ Returns the absolute value of the pixel-by-pixel difference between the two images. :: @@ -96,7 +96,7 @@ def difference(image1: Image.Image, image2: Image.Image) -> Image.Image: return image1._new(image1.im.chop_difference(image2.im)) -def multiply(image1: Image.Image, image2: Image.Image) -> Image.Image: +def multiply(image1: Image.ImageType, image2: Image.ImageType) -> Image.ImageType: """ Superimposes two images on top of each other. @@ -113,7 +113,7 @@ def multiply(image1: Image.Image, image2: Image.Image) -> Image.Image: return image1._new(image1.im.chop_multiply(image2.im)) -def screen(image1: Image.Image, image2: Image.Image) -> Image.Image: +def screen(image1: Image.ImageType, image2: Image.ImageType) -> Image.ImageType: """ Superimposes two inverted images on top of each other. :: @@ -127,7 +127,7 @@ def screen(image1: Image.Image, image2: Image.Image) -> Image.Image: return image1._new(image1.im.chop_screen(image2.im)) -def soft_light(image1: Image.Image, image2: Image.Image) -> Image.Image: +def soft_light(image1: Image.ImageType, image2: Image.ImageType) -> Image.ImageType: """ Superimposes two images on top of each other using the Soft Light algorithm @@ -139,7 +139,7 @@ def soft_light(image1: Image.Image, image2: Image.Image) -> Image.Image: return image1._new(image1.im.chop_soft_light(image2.im)) -def hard_light(image1: Image.Image, image2: Image.Image) -> Image.Image: +def hard_light(image1: Image.ImageType, image2: Image.ImageType) -> Image.ImageType: """ Superimposes two images on top of each other using the Hard Light algorithm @@ -151,7 +151,7 @@ def hard_light(image1: Image.Image, image2: Image.Image) -> Image.Image: return image1._new(image1.im.chop_hard_light(image2.im)) -def overlay(image1: Image.Image, image2: Image.Image) -> Image.Image: +def overlay(image1: Image.ImageType, image2: Image.ImageType) -> Image.ImageType: """ Superimposes two images on top of each other using the Overlay algorithm @@ -164,8 +164,11 @@ def overlay(image1: Image.Image, image2: Image.Image) -> Image.Image: def add( - image1: Image.Image, image2: Image.Image, scale: float = 1.0, offset: float = 0 -) -> Image.Image: + image1: Image.ImageType, + image2: Image.ImageType, + scale: float = 1.0, + offset: float = 0, +) -> Image.ImageType: """ Adds two images, dividing the result by scale and adding the offset. If omitted, scale defaults to 1.0, and offset to 0.0. :: @@ -181,8 +184,11 @@ def add( def subtract( - image1: Image.Image, image2: Image.Image, scale: float = 1.0, offset: float = 0 -) -> Image.Image: + image1: Image.ImageType, + image2: Image.ImageType, + scale: float = 1.0, + offset: float = 0, +) -> Image.ImageType: """ Subtracts two images, dividing the result by scale and adding the offset. If omitted, scale defaults to 1.0, and offset to 0.0. :: @@ -197,7 +203,7 @@ def subtract( return image1._new(image1.im.chop_subtract(image2.im, scale, offset)) -def add_modulo(image1: Image.Image, image2: Image.Image) -> Image.Image: +def add_modulo(image1: Image.ImageType, image2: Image.ImageType) -> Image.ImageType: """Add two images, without clipping the result. :: out = ((image1 + image2) % MAX) @@ -210,7 +216,9 @@ def add_modulo(image1: Image.Image, image2: Image.Image) -> Image.Image: return image1._new(image1.im.chop_add_modulo(image2.im)) -def subtract_modulo(image1: Image.Image, image2: Image.Image) -> Image.Image: +def subtract_modulo( + image1: Image.ImageType, image2: Image.ImageType +) -> Image.ImageType: """Subtract two images, without clipping the result. :: out = ((image1 - image2) % MAX) @@ -223,7 +231,7 @@ def subtract_modulo(image1: Image.Image, image2: Image.Image) -> Image.Image: return image1._new(image1.im.chop_subtract_modulo(image2.im)) -def logical_and(image1: Image.Image, image2: Image.Image) -> Image.Image: +def logical_and(image1: Image.ImageType, image2: Image.ImageType) -> Image.ImageType: """Logical AND between two images. Both of the images must have mode "1". If you would like to perform a @@ -241,7 +249,7 @@ def logical_and(image1: Image.Image, image2: Image.Image) -> Image.Image: return image1._new(image1.im.chop_and(image2.im)) -def logical_or(image1: Image.Image, image2: Image.Image) -> Image.Image: +def logical_or(image1: Image.ImageType, image2: Image.ImageType) -> Image.ImageType: """Logical OR between two images. Both of the images must have mode "1". :: @@ -256,7 +264,7 @@ def logical_or(image1: Image.Image, image2: Image.Image) -> Image.Image: return image1._new(image1.im.chop_or(image2.im)) -def logical_xor(image1: Image.Image, image2: Image.Image) -> Image.Image: +def logical_xor(image1: Image.ImageType, image2: Image.ImageType) -> Image.ImageType: """Logical XOR between two images. Both of the images must have mode "1". :: @@ -271,7 +279,9 @@ def logical_xor(image1: Image.Image, image2: Image.Image) -> Image.Image: return image1._new(image1.im.chop_xor(image2.im)) -def blend(image1: Image.Image, image2: Image.Image, alpha: float) -> Image.Image: +def blend( + image1: Image.ImageType, image2: Image.ImageType, alpha: float +) -> Image.ImageType: """Blend images using constant transparency weight. Alias for :py:func:`PIL.Image.blend`. @@ -282,8 +292,8 @@ def blend(image1: Image.Image, image2: Image.Image, alpha: float) -> Image.Image def composite( - image1: Image.Image, image2: Image.Image, mask: Image.Image -) -> Image.Image: + image1: Image.ImageType, image2: Image.ImageType, mask: Image.ImageType +) -> Image.ImageType: """Create composite using transparency mask. Alias for :py:func:`PIL.Image.composite`. @@ -293,7 +303,9 @@ def composite( return Image.composite(image1, image2, mask) -def offset(image: Image.Image, xoffset: int, yoffset: int | None = None) -> Image.Image: +def offset( + image: Image.ImageType, xoffset: int, yoffset: int | None = None +) -> Image.ImageType: """Returns a copy of the image where data has been offset by the given distances. Data wraps around the edges. If ``yoffset`` is omitted, it is assumed to be equal to ``xoffset``. diff --git a/src/PIL/ImageSequence.py b/src/PIL/ImageSequence.py index 2c185027630..db921e8d9d8 100644 --- a/src/PIL/ImageSequence.py +++ b/src/PIL/ImageSequence.py @@ -33,14 +33,14 @@ class Iterator: :param im: An image object. """ - def __init__(self, im: Image.Image): + def __init__(self, im: Image.ImageType): if not hasattr(im, "seek"): msg = "im must have seek method" raise AttributeError(msg) self.im = im self.position = getattr(self.im, "_min_frame", 0) - def __getitem__(self, ix: int) -> Image.Image: + def __getitem__(self, ix: int) -> Image.ImageType: try: self.im.seek(ix) return self.im @@ -51,7 +51,7 @@ def __getitem__(self, ix: int) -> Image.Image: def __iter__(self) -> Iterator: return self - def __next__(self) -> Image.Image: + def __next__(self) -> Image.ImageType: try: self.im.seek(self.position) self.position += 1 @@ -62,9 +62,9 @@ def __next__(self) -> Image.Image: def all_frames( - im: Image.Image | list[Image.Image], - func: Callable[[Image.Image], Image.Image] | None = None, -) -> list[Image.Image]: + im: Image.ImageType | list[Image.ImageType], + func: Callable[[Image.ImageType], Image.ImageType] | None = None, +) -> list[Image.ImageType]: """ Applies a given function to all frames in an image or a list of images. The frames are returned as a list of separate images.