Skip to content

Commit 5bacce9

Browse files
authored
Merge pull request #8046 from srittau/type-annotations
Add various type annotations
2 parents c9ac893 + 45cdc53 commit 5bacce9

File tree

10 files changed

+249
-97
lines changed

10 files changed

+249
-97
lines changed

Tests/test_image_rotate.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ def test_fastpath_translate() -> None:
124124
def test_center() -> None:
125125
im = hopper()
126126
rotate(im, im.mode, 45, center=(0, 0))
127-
rotate(im, im.mode, 45, translate=(im.size[0] / 2, 0))
128-
rotate(im, im.mode, 45, center=(0, 0), translate=(im.size[0] / 2, 0))
127+
rotate(im, im.mode, 45, translate=(im.size[0] // 2, 0))
128+
rotate(im, im.mode, 45, center=(0, 0), translate=(im.size[0] // 2, 0))
129129

130130

131131
def test_rotate_no_fill() -> None:

docs/handbook/concepts.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,12 @@ pixel, the Python Imaging Library provides different resampling *filters*.
144144
.. py:currentmodule:: PIL.Image
145145
146146
.. data:: Resampling.NEAREST
147+
:noindex:
147148

148149
Pick one nearest pixel from the input image. Ignore all other input pixels.
149150

150151
.. data:: Resampling.BOX
152+
:noindex:
151153

152154
Each pixel of source image contributes to one pixel of the
153155
destination image with identical weights.
@@ -158,13 +160,15 @@ pixel, the Python Imaging Library provides different resampling *filters*.
158160
.. versionadded:: 3.4.0
159161

160162
.. data:: Resampling.BILINEAR
163+
:noindex:
161164

162165
For resize calculate the output pixel value using linear interpolation
163166
on all pixels that may contribute to the output value.
164167
For other transformations linear interpolation over a 2x2 environment
165168
in the input image is used.
166169

167170
.. data:: Resampling.HAMMING
171+
:noindex:
168172

169173
Produces a sharper image than :data:`Resampling.BILINEAR`, doesn't have
170174
dislocations on local level like with :data:`Resampling.BOX`.
@@ -174,13 +178,15 @@ pixel, the Python Imaging Library provides different resampling *filters*.
174178
.. versionadded:: 3.4.0
175179

176180
.. data:: Resampling.BICUBIC
181+
:noindex:
177182

178183
For resize calculate the output pixel value using cubic interpolation
179184
on all pixels that may contribute to the output value.
180185
For other transformations cubic interpolation over a 4x4 environment
181186
in the input image is used.
182187

183188
.. data:: Resampling.LANCZOS
189+
:noindex:
184190

185191
Calculate the output pixel value using a high-quality Lanczos filter (a
186192
truncated sinc) on all pixels that may contribute to the output value.

docs/reference/Image.rst

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,6 @@ Constructing images
7878
^^^^^^^^^^^^^^^^^^^
7979

8080
.. autofunction:: new
81-
.. autoclass:: SupportsArrayInterface
82-
:show-inheritance:
8381
.. autofunction:: fromarray
8482
.. autofunction:: frombytes
8583
.. autofunction:: frombuffer
@@ -365,6 +363,14 @@ Classes
365363
.. autoclass:: PIL.Image.ImagePointHandler
366364
.. autoclass:: PIL.Image.ImageTransformHandler
367365

366+
Protocols
367+
---------
368+
369+
.. autoclass:: SupportsArrayInterface
370+
:show-inheritance:
371+
.. autoclass:: SupportsGetData
372+
:show-inheritance:
373+
368374
Constants
369375
---------
370376

@@ -418,7 +424,6 @@ See :ref:`concept-filters` for details.
418424
.. autoclass:: Resampling
419425
:members:
420426
:undoc-members:
421-
:noindex:
422427

423428
Dither modes
424429
^^^^^^^^^^^^

src/PIL/Image.py

Lines changed: 55 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,12 @@ def _getscaleoffset(expr):
503503
# Implementation wrapper
504504

505505

506+
class SupportsGetData(Protocol):
507+
def getdata(
508+
self,
509+
) -> tuple[Transform, Sequence[int]]: ...
510+
511+
506512
class Image:
507513
"""
508514
This class represents an image object. To create
@@ -1289,7 +1295,7 @@ def _crop(self, im, box):
12891295
return im.crop((x0, y0, x1, y1))
12901296

12911297
def draft(
1292-
self, mode: str, size: tuple[int, int]
1298+
self, mode: str | None, size: tuple[int, int]
12931299
) -> tuple[str, tuple[int, int, float, float]] | None:
12941300
"""
12951301
Configures the image file loader so it returns a version of the
@@ -1709,7 +1715,12 @@ def entropy(self, mask=None, extrema=None):
17091715
return self.im.entropy(extrema)
17101716
return self.im.entropy()
17111717

1712-
def paste(self, im, box=None, mask=None) -> None:
1718+
def paste(
1719+
self,
1720+
im: Image | str | float | tuple[float, ...],
1721+
box: tuple[int, int, int, int] | tuple[int, int] | None = None,
1722+
mask: Image | None = None,
1723+
) -> None:
17131724
"""
17141725
Pastes another image into this image. The box argument is either
17151726
a 2-tuple giving the upper left corner, a 4-tuple defining the
@@ -1737,7 +1748,7 @@ def paste(self, im, box=None, mask=None) -> None:
17371748
See :py:meth:`~PIL.Image.Image.alpha_composite` if you want to
17381749
combine images with respect to their alpha channels.
17391750
1740-
:param im: Source image or pixel value (integer or tuple).
1751+
:param im: Source image or pixel value (integer, float or tuple).
17411752
:param box: An optional 4-tuple giving the region to paste into.
17421753
If a 2-tuple is used instead, it's treated as the upper left
17431754
corner. If omitted or None, the source is pasted into the
@@ -2146,7 +2157,13 @@ def _get_safe_box(self, size, resample, box):
21462157
min(self.size[1], math.ceil(box[3] + support_y)),
21472158
)
21482159

2149-
def resize(self, size, resample=None, box=None, reducing_gap=None) -> Image:
2160+
def resize(
2161+
self,
2162+
size: tuple[int, int],
2163+
resample: int | None = None,
2164+
box: tuple[float, float, float, float] | None = None,
2165+
reducing_gap: float | None = None,
2166+
) -> Image:
21502167
"""
21512168
Returns a resized copy of this image.
21522169
@@ -2211,13 +2228,9 @@ def resize(self, size, resample=None, box=None, reducing_gap=None) -> Image:
22112228
msg = "reducing_gap must be 1.0 or greater"
22122229
raise ValueError(msg)
22132230

2214-
size = tuple(size)
2215-
22162231
self.load()
22172232
if box is None:
22182233
box = (0, 0) + self.size
2219-
else:
2220-
box = tuple(box)
22212234

22222235
if self.size == size and box == (0, 0) + self.size:
22232236
return self.copy()
@@ -2252,7 +2265,11 @@ def resize(self, size, resample=None, box=None, reducing_gap=None) -> Image:
22522265

22532266
return self._new(self.im.resize(size, resample, box))
22542267

2255-
def reduce(self, factor, box=None):
2268+
def reduce(
2269+
self,
2270+
factor: int | tuple[int, int],
2271+
box: tuple[int, int, int, int] | None = None,
2272+
) -> Image:
22562273
"""
22572274
Returns a copy of the image reduced ``factor`` times.
22582275
If the size of the image is not dividable by ``factor``,
@@ -2270,8 +2287,6 @@ def reduce(self, factor, box=None):
22702287

22712288
if box is None:
22722289
box = (0, 0) + self.size
2273-
else:
2274-
box = tuple(box)
22752290

22762291
if factor == (1, 1) and box == (0, 0) + self.size:
22772292
return self.copy()
@@ -2287,13 +2302,13 @@ def reduce(self, factor, box=None):
22872302

22882303
def rotate(
22892304
self,
2290-
angle,
2291-
resample=Resampling.NEAREST,
2292-
expand=0,
2293-
center=None,
2294-
translate=None,
2295-
fillcolor=None,
2296-
):
2305+
angle: float,
2306+
resample: Resampling = Resampling.NEAREST,
2307+
expand: int | bool = False,
2308+
center: tuple[int, int] | None = None,
2309+
translate: tuple[int, int] | None = None,
2310+
fillcolor: float | tuple[float, ...] | str | None = None,
2311+
) -> Image:
22972312
"""
22982313
Returns a rotated copy of this image. This method returns a
22992314
copy of this image, rotated the given number of degrees counter
@@ -2600,7 +2615,12 @@ def tell(self) -> int:
26002615
"""
26012616
return 0
26022617

2603-
def thumbnail(self, size, resample=Resampling.BICUBIC, reducing_gap=2.0):
2618+
def thumbnail(
2619+
self,
2620+
size: tuple[float, float],
2621+
resample: Resampling = Resampling.BICUBIC,
2622+
reducing_gap: float = 2.0,
2623+
) -> None:
26042624
"""
26052625
Make this image into a thumbnail. This method modifies the
26062626
image to contain a thumbnail version of itself, no larger than
@@ -2661,20 +2681,24 @@ def round_aspect(number, key):
26612681

26622682
box = None
26632683
if reducing_gap is not None:
2664-
size = preserve_aspect_ratio()
2665-
if size is None:
2684+
preserved_size = preserve_aspect_ratio()
2685+
if preserved_size is None:
26662686
return
2687+
size = preserved_size
26672688

2668-
res = self.draft(None, (size[0] * reducing_gap, size[1] * reducing_gap))
2689+
res = self.draft(
2690+
None, (int(size[0] * reducing_gap), int(size[1] * reducing_gap))
2691+
)
26692692
if res is not None:
26702693
box = res[1]
26712694
if box is None:
26722695
self.load()
26732696

26742697
# load() may have changed the size of the image
2675-
size = preserve_aspect_ratio()
2676-
if size is None:
2698+
preserved_size = preserve_aspect_ratio()
2699+
if preserved_size is None:
26772700
return
2701+
size = preserved_size
26782702

26792703
if self.size != size:
26802704
im = self.resize(size, resample, box=box, reducing_gap=reducing_gap)
@@ -2690,12 +2714,12 @@ def round_aspect(number, key):
26902714
# instead of bloating the method docs, add a separate chapter.
26912715
def transform(
26922716
self,
2693-
size,
2694-
method,
2695-
data=None,
2696-
resample=Resampling.NEAREST,
2697-
fill=1,
2698-
fillcolor=None,
2717+
size: tuple[int, int],
2718+
method: Transform | ImageTransformHandler | SupportsGetData,
2719+
data: Sequence[Any] | None = None,
2720+
resample: int = Resampling.NEAREST,
2721+
fill: int = 1,
2722+
fillcolor: float | tuple[float, ...] | str | None = None,
26992723
) -> Image:
27002724
"""
27012725
Transforms this image. This method creates a new image with the
@@ -2929,7 +2953,7 @@ def transform(
29292953
self,
29302954
size: tuple[int, int],
29312955
image: Image,
2932-
**options: dict[str, str | int | tuple[int, ...] | list[int]],
2956+
**options: Any,
29332957
) -> Image:
29342958
pass
29352959

0 commit comments

Comments
 (0)