Skip to content

Commit

Permalink
Merge pull request python-pillow#8265 from radarhere/imagedraw2
Browse files Browse the repository at this point in the history
  • Loading branch information
hugovk authored Aug 1, 2024
2 parents 5517232 + 9558547 commit 126af36
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 18 deletions.
46 changes: 46 additions & 0 deletions Tests/test_imagedraw2.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,36 @@ def test_mode() -> None:
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)
def test_ellipse(bbox: Coords) -> None:
# Arrange
Expand Down Expand Up @@ -123,6 +153,22 @@ def test_line_pen_as_brush(points: Coords) -> None:
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)
def test_polygon(points: Coords) -> None:
# Arrange
Expand Down
66 changes: 48 additions & 18 deletions src/PIL/ImageDraw2.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,12 @@ def flush(self) -> Image.Image:
return self.image

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:
# handle color arguments
outline = fill = None
Expand All @@ -101,60 +106,85 @@ def render(
path.transform(self.transform)
xy = path
# render the item
if op == "line":
self.draw.line(xy, fill=outline, width=width)
if op in ("arc", "line"):
kwargs.setdefault("fill", outline)
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:
"""Sets a transformation offset."""
(xoffset, yoffset) = offset
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
angles, inside the given bounding box.
.. 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
with a straight line.
.. 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.
.. 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.
.. 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
center of the bounding box.
.. 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.
Expand All @@ -165,15 +195,15 @@ def polygon(self, xy: Coords, *options: Any) -> None:
.. 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.
.. 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:
"""
Expand Down

0 comments on commit 126af36

Please sign in to comment.