Merge pull request #8265 from radarhere/imagedraw2

This commit is contained in:
Hugo van Kemenade 2024-08-01 14:50:43 +03:00 committed by GitHub
commit 126af363af
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 94 additions and 18 deletions

View File

@ -65,6 +65,36 @@ def test_mode() -> None:
ImageDraw2.Draw("L") ImageDraw2.Draw("L")
@pytest.mark.parametrize("bbox", BBOX)
@pytest.mark.parametrize("start, end", ((0, 180), (0.5, 180.4)))
def test_arc(bbox: Coords, start: float, end: float) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
pen = ImageDraw2.Pen("white", width=1)
# Act
draw.arc(bbox, pen, start, end)
# Assert
assert_image_similar_tofile(im, "Tests/images/imagedraw_arc.png", 1)
@pytest.mark.parametrize("bbox", BBOX)
def test_chord(bbox: Coords) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
pen = ImageDraw2.Pen("yellow")
brush = ImageDraw2.Brush("red")
# Act
draw.chord(bbox, pen, 0, 180, brush)
# Assert
assert_image_similar_tofile(im, "Tests/images/imagedraw_chord_RGB.png", 1)
@pytest.mark.parametrize("bbox", BBOX) @pytest.mark.parametrize("bbox", BBOX)
def test_ellipse(bbox: Coords) -> None: def test_ellipse(bbox: Coords) -> None:
# Arrange # Arrange
@ -123,6 +153,22 @@ def test_line_pen_as_brush(points: Coords) -> None:
assert_image_equal_tofile(im, "Tests/images/imagedraw_line.png") assert_image_equal_tofile(im, "Tests/images/imagedraw_line.png")
@pytest.mark.parametrize("bbox", BBOX)
@pytest.mark.parametrize("start, end", ((-92, 46), (-92.2, 46.2)))
def test_pieslice(bbox: Coords, start: float, end: float) -> None:
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
pen = ImageDraw2.Pen("blue")
brush = ImageDraw2.Brush("white")
# Act
draw.pieslice(bbox, pen, start, end, brush)
# Assert
assert_image_similar_tofile(im, "Tests/images/imagedraw_pieslice.png", 1)
@pytest.mark.parametrize("points", POINTS) @pytest.mark.parametrize("points", POINTS)
def test_polygon(points: Coords) -> None: def test_polygon(points: Coords) -> None:
# Arrange # Arrange

View File

@ -80,7 +80,12 @@ class Draw:
return self.image return self.image
def render( def render(
self, op: str, xy: Coords, pen: Pen | Brush, brush: Brush | Pen | None = None self,
op: str,
xy: Coords,
pen: Pen | Brush | None,
brush: Brush | Pen | None = None,
**kwargs: Any,
) -> None: ) -> None:
# handle color arguments # handle color arguments
outline = fill = None outline = fill = None
@ -101,60 +106,85 @@ class Draw:
path.transform(self.transform) path.transform(self.transform)
xy = path xy = path
# render the item # render the item
if op == "line": if op in ("arc", "line"):
self.draw.line(xy, fill=outline, width=width) kwargs.setdefault("fill", outline)
else: else:
getattr(self.draw, op)(xy, fill=fill, outline=outline) kwargs.setdefault("fill", fill)
kwargs.setdefault("outline", outline)
if op == "line":
kwargs.setdefault("width", width)
getattr(self.draw, op)(xy, **kwargs)
def settransform(self, offset: tuple[float, float]) -> None: def settransform(self, offset: tuple[float, float]) -> None:
"""Sets a transformation offset.""" """Sets a transformation offset."""
(xoffset, yoffset) = offset (xoffset, yoffset) = offset
self.transform = (1, 0, xoffset, 0, 1, yoffset) self.transform = (1, 0, xoffset, 0, 1, yoffset)
def arc(self, xy: Coords, start, end, *options: Any) -> None: def arc(
self,
xy: Coords,
pen: Pen | Brush | None,
start: float,
end: float,
*options: Any,
) -> None:
""" """
Draws an arc (a portion of a circle outline) between the start and end Draws an arc (a portion of a circle outline) between the start and end
angles, inside the given bounding box. angles, inside the given bounding box.
.. seealso:: :py:meth:`PIL.ImageDraw.ImageDraw.arc` .. seealso:: :py:meth:`PIL.ImageDraw.ImageDraw.arc`
""" """
self.render("arc", xy, start, end, *options) self.render("arc", xy, pen, *options, start=start, end=end)
def chord(self, xy: Coords, start, end, *options: Any) -> None: def chord(
self,
xy: Coords,
pen: Pen | Brush | None,
start: float,
end: float,
*options: Any,
) -> None:
""" """
Same as :py:meth:`~PIL.ImageDraw2.Draw.arc`, but connects the end points Same as :py:meth:`~PIL.ImageDraw2.Draw.arc`, but connects the end points
with a straight line. with a straight line.
.. seealso:: :py:meth:`PIL.ImageDraw.ImageDraw.chord` .. seealso:: :py:meth:`PIL.ImageDraw.ImageDraw.chord`
""" """
self.render("chord", xy, start, end, *options) self.render("chord", xy, pen, *options, start=start, end=end)
def ellipse(self, xy: Coords, *options: Any) -> None: def ellipse(self, xy: Coords, pen: Pen | Brush | None, *options: Any) -> None:
""" """
Draws an ellipse inside the given bounding box. Draws an ellipse inside the given bounding box.
.. seealso:: :py:meth:`PIL.ImageDraw.ImageDraw.ellipse` .. seealso:: :py:meth:`PIL.ImageDraw.ImageDraw.ellipse`
""" """
self.render("ellipse", xy, *options) self.render("ellipse", xy, pen, *options)
def line(self, xy: Coords, *options: Any) -> None: def line(self, xy: Coords, pen: Pen | Brush | None, *options: Any) -> None:
""" """
Draws a line between the coordinates in the ``xy`` list. Draws a line between the coordinates in the ``xy`` list.
.. seealso:: :py:meth:`PIL.ImageDraw.ImageDraw.line` .. seealso:: :py:meth:`PIL.ImageDraw.ImageDraw.line`
""" """
self.render("line", xy, *options) self.render("line", xy, pen, *options)
def pieslice(self, xy: Coords, start, end, *options: Any) -> None: def pieslice(
self,
xy: Coords,
pen: Pen | Brush | None,
start: float,
end: float,
*options: Any,
) -> None:
""" """
Same as arc, but also draws straight lines between the end points and the Same as arc, but also draws straight lines between the end points and the
center of the bounding box. center of the bounding box.
.. seealso:: :py:meth:`PIL.ImageDraw.ImageDraw.pieslice` .. seealso:: :py:meth:`PIL.ImageDraw.ImageDraw.pieslice`
""" """
self.render("pieslice", xy, start, end, *options) self.render("pieslice", xy, pen, *options, start=start, end=end)
def polygon(self, xy: Coords, *options: Any) -> None: def polygon(self, xy: Coords, pen: Pen | Brush | None, *options: Any) -> None:
""" """
Draws a polygon. Draws a polygon.
@ -165,15 +195,15 @@ class Draw:
.. seealso:: :py:meth:`PIL.ImageDraw.ImageDraw.polygon` .. seealso:: :py:meth:`PIL.ImageDraw.ImageDraw.polygon`
""" """
self.render("polygon", xy, *options) self.render("polygon", xy, pen, *options)
def rectangle(self, xy: Coords, *options: Any) -> None: def rectangle(self, xy: Coords, pen: Pen | Brush | None, *options: Any) -> None:
""" """
Draws a rectangle. Draws a rectangle.
.. seealso:: :py:meth:`PIL.ImageDraw.ImageDraw.rectangle` .. seealso:: :py:meth:`PIL.ImageDraw.ImageDraw.rectangle`
""" """
self.render("rectangle", xy, *options) self.render("rectangle", xy, pen, *options)
def text(self, xy: tuple[float, float], text: AnyStr, font: Font) -> None: def text(self, xy: tuple[float, float], text: AnyStr, font: Font) -> None:
""" """