From 2c4a6e1179a7e2460d3dae9f4558173c547996a7 Mon Sep 17 00:00:00 2001 From: void4 Date: Mon, 27 May 2024 00:23:16 +0200 Subject: [PATCH 01/11] Add function and documentation to draw circle --- docs/reference/ImageDraw.rst | 13 +++++++++++++ src/PIL/ImageDraw.py | 9 +++++++++ 2 files changed, 22 insertions(+) diff --git a/docs/reference/ImageDraw.rst b/docs/reference/ImageDraw.rst index 4ccfacae7..6987adc88 100644 --- a/docs/reference/ImageDraw.rst +++ b/docs/reference/ImageDraw.rst @@ -240,6 +240,19 @@ Methods .. versionadded:: 5.3.0 +.. py:method:: ImageDraw.circle(xy, radius, fill=None, outline=None, width=1) + + Draws a circle given the center coordinates and a radius. + + :param xy: One point to define the circle center. Sequence: + ``[x, y]`` + :param radius: Radius of the circle + :param outline: Color to use for the outline. + :param fill: Color to use for the fill. + :param width: The line width, in pixels. + + .. versionadded:: ?.?.? + .. py:method:: ImageDraw.line(xy, fill=None, width=0, joint=None) Draws a line between the coordinates in the ``xy`` list. diff --git a/src/PIL/ImageDraw.py b/src/PIL/ImageDraw.py index 42f2ee8c7..4b42b32d0 100644 --- a/src/PIL/ImageDraw.py +++ b/src/PIL/ImageDraw.py @@ -181,6 +181,15 @@ class ImageDraw: if ink is not None and ink != fill and width != 0: self.draw.draw_ellipse(xy, ink, 0, width) + def circle(self, xy: Coords, radius, fill=None, outline=None, width=1) -> None: + """Draw a circle given center coordinates and a radius.""" + ink, fill = self._getink(outline, fill) + ellipse_xy = (xy[0]-radius, xy[1]-radius, xy[0]+radius, xy[1]+radius) + if fill is not None: + self.draw.draw_ellipse(ellipse_xy, fill, 1) + if ink is not None and ink != fill and width != 0: + self.draw.draw_ellipse(ellipse_xy, ink, 0, width) + def line(self, xy: Coords, fill=None, width=0, joint=None) -> None: """Draw a line, or a connected sequence of line segments.""" ink = self._getink(fill)[0] From 2ee3cef50ef6b1917ea3c03ad06849a2a599ee8a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 26 May 2024 22:25:13 +0000 Subject: [PATCH 02/11] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/PIL/ImageDraw.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PIL/ImageDraw.py b/src/PIL/ImageDraw.py index 4b42b32d0..03f2637ae 100644 --- a/src/PIL/ImageDraw.py +++ b/src/PIL/ImageDraw.py @@ -184,7 +184,7 @@ class ImageDraw: def circle(self, xy: Coords, radius, fill=None, outline=None, width=1) -> None: """Draw a circle given center coordinates and a radius.""" ink, fill = self._getink(outline, fill) - ellipse_xy = (xy[0]-radius, xy[1]-radius, xy[0]+radius, xy[1]+radius) + ellipse_xy = (xy[0] - radius, xy[1] - radius, xy[0] + radius, xy[1] + radius) if fill is not None: self.draw.draw_ellipse(ellipse_xy, fill, 1) if ink is not None and ink != fill and width != 0: From 8d9a4dda980f02ff93fa2301d906ef32602c5e07 Mon Sep 17 00:00:00 2001 From: void4 Date: Mon, 27 May 2024 12:57:50 +0200 Subject: [PATCH 03/11] Update docs/reference/ImageDraw.rst - Set versionadded Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> --- docs/reference/ImageDraw.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/ImageDraw.rst b/docs/reference/ImageDraw.rst index 6987adc88..51d5965db 100644 --- a/docs/reference/ImageDraw.rst +++ b/docs/reference/ImageDraw.rst @@ -251,7 +251,7 @@ Methods :param fill: Color to use for the fill. :param width: The line width, in pixels. - .. versionadded:: ?.?.? + .. versionadded:: 10.4.0 .. py:method:: ImageDraw.line(xy, fill=None, width=0, joint=None) From 38e6913579c3c7c04bb40384cd7eb797130c5dd8 Mon Sep 17 00:00:00 2001 From: void4 Date: Mon, 27 May 2024 13:01:10 +0200 Subject: [PATCH 04/11] Simplify circle() by reusing ellipse() --- src/PIL/ImageDraw.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/PIL/ImageDraw.py b/src/PIL/ImageDraw.py index 03f2637ae..b270cc6ba 100644 --- a/src/PIL/ImageDraw.py +++ b/src/PIL/ImageDraw.py @@ -183,12 +183,8 @@ class ImageDraw: def circle(self, xy: Coords, radius, fill=None, outline=None, width=1) -> None: """Draw a circle given center coordinates and a radius.""" - ink, fill = self._getink(outline, fill) ellipse_xy = (xy[0] - radius, xy[1] - radius, xy[0] + radius, xy[1] + radius) - if fill is not None: - self.draw.draw_ellipse(ellipse_xy, fill, 1) - if ink is not None and ink != fill and width != 0: - self.draw.draw_ellipse(ellipse_xy, ink, 0, width) + self.ellipse(ellipse_xy, fill, outline, width) def line(self, xy: Coords, fill=None, width=0, joint=None) -> None: """Draw a line, or a connected sequence of line segments.""" From 35a700a1d4b2de51c8e13d4b60736f765b8b816b Mon Sep 17 00:00:00 2001 From: void4 Date: Mon, 27 May 2024 13:14:04 +0200 Subject: [PATCH 05/11] Update 10.4.0.rst - Add PIL.ImageDraw.circle() API addition --- docs/releasenotes/10.4.0.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/releasenotes/10.4.0.rst b/docs/releasenotes/10.4.0.rst index 41f33102f..3c4258801 100644 --- a/docs/releasenotes/10.4.0.rst +++ b/docs/releasenotes/10.4.0.rst @@ -45,6 +45,10 @@ TODO API Additions ============= +Added PIL.ImageDraw.circle() +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Given the circle center coordinate pair and a radius, plots a circle using PIL.ImageDraw.ellipse() + TODO ^^^^ From 773ff20b762247a9fa717683f5e89349830def7e Mon Sep 17 00:00:00 2001 From: void4 Date: Mon, 27 May 2024 13:18:47 +0200 Subject: [PATCH 06/11] Update docs/reference/ImageDraw.rst - move circle method up to indicate it is new Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> --- docs/reference/ImageDraw.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/reference/ImageDraw.rst b/docs/reference/ImageDraw.rst index 51d5965db..ed762c8d6 100644 --- a/docs/reference/ImageDraw.rst +++ b/docs/reference/ImageDraw.rst @@ -243,6 +243,8 @@ Methods .. py:method:: ImageDraw.circle(xy, radius, fill=None, outline=None, width=1) Draws a circle given the center coordinates and a radius. + + .. versionadded:: 10.4.0 :param xy: One point to define the circle center. Sequence: ``[x, y]`` From 034f3cbed522b862b07bf938bbce0a599018bc57 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 11:19:09 +0000 Subject: [PATCH 07/11] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- docs/reference/ImageDraw.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/ImageDraw.rst b/docs/reference/ImageDraw.rst index ed762c8d6..4996acf71 100644 --- a/docs/reference/ImageDraw.rst +++ b/docs/reference/ImageDraw.rst @@ -243,7 +243,7 @@ Methods .. py:method:: ImageDraw.circle(xy, radius, fill=None, outline=None, width=1) Draws a circle given the center coordinates and a radius. - + .. versionadded:: 10.4.0 :param xy: One point to define the circle center. Sequence: From 9b7556228e0f045495f6b3dd2fd22e84b65ab0eb Mon Sep 17 00:00:00 2001 From: void4 Date: Mon, 27 May 2024 13:21:41 +0200 Subject: [PATCH 08/11] Update docs/reference/ImageDraw.rst - move versionadded Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> --- docs/reference/ImageDraw.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/reference/ImageDraw.rst b/docs/reference/ImageDraw.rst index 4996acf71..c4ce76cc0 100644 --- a/docs/reference/ImageDraw.rst +++ b/docs/reference/ImageDraw.rst @@ -253,8 +253,6 @@ Methods :param fill: Color to use for the fill. :param width: The line width, in pixels. - .. versionadded:: 10.4.0 - .. py:method:: ImageDraw.line(xy, fill=None, width=0, joint=None) Draws a line between the coordinates in the ``xy`` list. From 8db5fbead1955ed6f1f4810e3b36c46483dcc62e Mon Sep 17 00:00:00 2001 From: void4 Date: Mon, 27 May 2024 13:27:56 +0200 Subject: [PATCH 09/11] Update src/PIL/ImageDraw.py - set circle argument xy to type Sequence[float] instead of Coords, radius to float Co-authored-by: Andrew Murray <3112309+radarhere@users.noreply.github.com> --- src/PIL/ImageDraw.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/PIL/ImageDraw.py b/src/PIL/ImageDraw.py index b270cc6ba..17c176430 100644 --- a/src/PIL/ImageDraw.py +++ b/src/PIL/ImageDraw.py @@ -181,7 +181,9 @@ class ImageDraw: if ink is not None and ink != fill and width != 0: self.draw.draw_ellipse(xy, ink, 0, width) - def circle(self, xy: Coords, radius, fill=None, outline=None, width=1) -> None: + def circle( + self, xy: Sequence[float], radius: float, fill=None, outline=None, width=1 + ) -> None: """Draw a circle given center coordinates and a radius.""" ellipse_xy = (xy[0] - radius, xy[1] - radius, xy[0] + radius, xy[1] + radius) self.ellipse(ellipse_xy, fill, outline, width) From 12cefd798e7b28d05af4a39abd601bc862081881 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 27 May 2024 21:48:38 +1000 Subject: [PATCH 10/11] Added method links to release notes --- docs/reference/ImageDraw.rst | 25 ++++++++++++------------- docs/releasenotes/10.4.0.rst | 9 ++++++--- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/docs/reference/ImageDraw.rst b/docs/reference/ImageDraw.rst index c4ce76cc0..1404869ca 100644 --- a/docs/reference/ImageDraw.rst +++ b/docs/reference/ImageDraw.rst @@ -227,6 +227,18 @@ Methods .. versionadded:: 5.3.0 +.. py:method:: ImageDraw.circle(xy, radius, fill=None, outline=None, width=1) + + Draws a circle with a given radius centering on a point. + + .. versionadded:: 10.4.0 + + :param xy: The point for the center of the circle, e.g. ``(x, y)``. + :param radius: Radius of the circle. + :param outline: Color to use for the outline. + :param fill: Color to use for the fill. + :param width: The line width, in pixels. + .. py:method:: ImageDraw.ellipse(xy, fill=None, outline=None, width=1) Draws an ellipse inside the given bounding box. @@ -240,19 +252,6 @@ Methods .. versionadded:: 5.3.0 -.. py:method:: ImageDraw.circle(xy, radius, fill=None, outline=None, width=1) - - Draws a circle given the center coordinates and a radius. - - .. versionadded:: 10.4.0 - - :param xy: One point to define the circle center. Sequence: - ``[x, y]`` - :param radius: Radius of the circle - :param outline: Color to use for the outline. - :param fill: Color to use for the fill. - :param width: The line width, in pixels. - .. py:method:: ImageDraw.line(xy, fill=None, width=0, joint=None) Draws a line between the coordinates in the ``xy`` list. diff --git a/docs/releasenotes/10.4.0.rst b/docs/releasenotes/10.4.0.rst index 3c4258801..e0d695a8b 100644 --- a/docs/releasenotes/10.4.0.rst +++ b/docs/releasenotes/10.4.0.rst @@ -45,9 +45,12 @@ TODO API Additions ============= -Added PIL.ImageDraw.circle() -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Given the circle center coordinate pair and a radius, plots a circle using PIL.ImageDraw.ellipse() +ImageDraw.circle +^^^^^^^^^^^^^^^^ + +Added :py:meth:`~PIL.ImageDraw.ImageDraw.circle`. It provides the same functionality as +:py:meth:`~PIL.ImageDraw.ImageDraw.ellipse`, but instead of taking a bounding box, it +takes a center point and radius. TODO ^^^^ From cac1a04329a2bb0864075f0aca4ff6e2c48a45cf Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 27 May 2024 21:59:32 +1000 Subject: [PATCH 11/11] Added test --- Tests/test_imagedraw.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Tests/test_imagedraw.py b/Tests/test_imagedraw.py index 0a699e2ab..69d09e03d 100644 --- a/Tests/test_imagedraw.py +++ b/Tests/test_imagedraw.py @@ -2,6 +2,7 @@ from __future__ import annotations import contextlib import os.path +from typing import Sequence import pytest @@ -265,6 +266,21 @@ def test_chord_too_fat() -> None: assert_image_equal_tofile(im, "Tests/images/imagedraw_chord_too_fat.png") +@pytest.mark.parametrize("mode", ("RGB", "L")) +@pytest.mark.parametrize("xy", ((W / 2, H / 2), [W / 2, H / 2])) +def test_circle(mode: str, xy: Sequence[float]) -> None: + # Arrange + im = Image.new(mode, (W, H)) + draw = ImageDraw.Draw(im) + expected = f"Tests/images/imagedraw_ellipse_{mode}.png" + + # Act + draw.circle(xy, 25, fill="green", outline="blue") + + # Assert + assert_image_similar_tofile(im, expected, 1) + + @pytest.mark.parametrize("mode", ("RGB", "L")) @pytest.mark.parametrize("bbox", BBOX) def test_ellipse(mode: str, bbox: Coords) -> None: