Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented another ellipse drawing algorithm #4523

Merged
merged 19 commits into from
Oct 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified Tests/images/imagedraw_arc.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Tests/images/imagedraw_arc_end_le_start.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Tests/images/imagedraw_arc_high.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Tests/images/imagedraw_arc_no_loops.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Tests/images/imagedraw_arc_width.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Tests/images/imagedraw_arc_width_fill.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Tests/images/imagedraw_arc_width_non_whole_angle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Tests/images/imagedraw_arc_width_pieslice.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Tests/images/imagedraw_chord_L.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Tests/images/imagedraw_chord_RGB.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Tests/images/imagedraw_chord_too_fat.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Tests/images/imagedraw_chord_width.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Tests/images/imagedraw_chord_width_fill.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Tests/images/imagedraw_chord_zero_width.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Tests/images/imagedraw_ellipse_L.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Tests/images/imagedraw_ellipse_RGB.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Tests/images/imagedraw_ellipse_edge.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Tests/images/imagedraw_ellipse_various_sizes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Tests/images/imagedraw_ellipse_width.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Tests/images/imagedraw_ellipse_width_fill.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Tests/images/imagedraw_ellipse_width_large.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Tests/images/imagedraw_ellipse_zero_width.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Tests/images/imagedraw_outline_chord_RGB.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Tests/images/imagedraw_pieslice.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Tests/images/imagedraw_pieslice_wide.png
Binary file modified Tests/images/imagedraw_pieslice_width.png
Binary file modified Tests/images/imagedraw_pieslice_width_fill.png
Binary file modified Tests/images/imagedraw_pieslice_zero_width.png
8 changes: 4 additions & 4 deletions Tests/test_imagechops.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,8 +311,8 @@ def test_subtract():

# Assert
assert new.getbbox() == (25, 50, 76, 76)
assert new.getpixel((50, 50)) == GREEN
assert new.getpixel((50, 51)) == BLACK
assert new.getpixel((50, 51)) == GREEN
assert new.getpixel((50, 52)) == BLACK


def test_subtract_scale_offset():
Expand Down Expand Up @@ -350,8 +350,8 @@ def test_subtract_modulo():

# Assert
assert new.getbbox() == (25, 50, 76, 76)
assert new.getpixel((50, 50)) == GREEN
assert new.getpixel((50, 51)) == BLACK
assert new.getpixel((50, 51)) == GREEN
assert new.getpixel((50, 52)) == BLACK


def test_subtract_modulo_no_clip():
Expand Down
93 changes: 84 additions & 9 deletions Tests/test_imagedraw.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,19 @@ def test_arc_width_non_whole_angle():
assert_image_similar_tofile(im, expected, 1)


def test_arc_high():
# Arrange
im = Image.new("RGB", (200, 200))
draw = ImageDraw.Draw(im)

# Act
draw.arc([10, 10, 89, 189], 20, 330, width=20, fill="white")
draw.arc([110, 10, 189, 189], 20, 150, width=20, fill="white")

# Assert
assert_image_equal(im, Image.open("Tests/images/imagedraw_arc_high.png"))


def test_bitmap():
# Arrange
im = Image.new("RGB", (W, H))
Expand Down Expand Up @@ -193,13 +206,11 @@ def helper_chord(mode, bbox, start, end):
def test_chord1():
for mode in ["RGB", "L"]:
helper_chord(mode, BBOX1, 0, 180)
helper_chord(mode, BBOX1, 0.5, 180.4)


def test_chord2():
for mode in ["RGB", "L"]:
helper_chord(mode, BBOX2, 0, 180)
helper_chord(mode, BBOX2, 0.5, 180.4)


def test_chord_width():
Expand Down Expand Up @@ -239,6 +250,18 @@ def test_chord_zero_width():
assert_image_equal(im, expected)


def test_chord_too_fat():
# Arrange
im = Image.new("RGB", (100, 100))
draw = ImageDraw.Draw(im)

# Act
draw.chord([-150, -150, 99, 99], 15, 60, width=10, fill="white", outline="red")

# Assert
assert_image_equal(im, Image.open("Tests/images/imagedraw_chord_too_fat.png"))


def helper_ellipse(mode, bbox):
# Arrange
im = Image.new(mode, (W, H))
Expand Down Expand Up @@ -281,15 +304,18 @@ def test_ellipse_edge():
draw = ImageDraw.Draw(im)

# Act
draw.ellipse(((0, 0), (W - 1, H)), fill="white")
draw.ellipse(((0, 0), (W - 1, H - 1)), fill="white")

# Assert
assert_image_similar_tofile(im, "Tests/images/imagedraw_ellipse_edge.png", 1)


def test_ellipse_symmetric():
for bbox in [(25, 25, 76, 76), (25, 25, 75, 75)]:
im = Image.new("RGB", (101, 101))
for width, bbox in (
(100, (24, 24, 75, 75)),
(101, (25, 25, 75, 75)),
):
im = Image.new("RGB", (width, 100))
draw = ImageDraw.Draw(im)
draw.ellipse(bbox, fill="green", outline="blue")
assert_image_equal(im, im.transpose(Image.FLIP_LEFT_RIGHT))
Expand Down Expand Up @@ -344,6 +370,43 @@ def test_ellipse_zero_width():
assert_image_equal(im, expected)


def ellipse_various_sizes_helper(filled):
ellipse_sizes = range(32)
image_size = sum(ellipse_sizes) + len(ellipse_sizes) + 1
im = Image.new("RGB", (image_size, image_size))
draw = ImageDraw.Draw(im)

x = 1
for w in ellipse_sizes:
y = 1
for h in ellipse_sizes:
border = [x, y, x + w - 1, y + h - 1]
if filled:
draw.ellipse(border, fill="white")
else:
draw.ellipse(border, outline="white")
y += h + 1
x += w + 1

return im


def test_ellipse_various_sizes():
im = ellipse_various_sizes_helper(False)

with Image.open("Tests/images/imagedraw_ellipse_various_sizes.png") as expected:
assert_image_equal(im, expected)


def test_ellipse_various_sizes_filled():
im = ellipse_various_sizes_helper(True)

with Image.open(
"Tests/images/imagedraw_ellipse_various_sizes_filled.png"
) as expected:
assert_image_equal(im, expected)


def helper_line(points):
# Arrange
im = Image.new("RGB", (W, H))
Expand Down Expand Up @@ -419,13 +482,13 @@ def helper_pieslice(bbox, start, end):


def test_pieslice1():
helper_pieslice(BBOX1, -90, 45)
helper_pieslice(BBOX1, -90.5, 45.4)
helper_pieslice(BBOX1, -92, 46)
helper_pieslice(BBOX1, -92.2, 46.2)


def test_pieslice2():
helper_pieslice(BBOX2, -90, 45)
helper_pieslice(BBOX2, -90.5, 45.4)
helper_pieslice(BBOX2, -92, 46)
helper_pieslice(BBOX2, -92.2, 46.2)


def test_pieslice_width():
Expand Down Expand Up @@ -466,6 +529,18 @@ def test_pieslice_zero_width():
assert_image_equal(im, expected)


def test_pieslice_wide():
# Arrange
im = Image.new("RGB", (200, 100))
draw = ImageDraw.Draw(im)

# Act
draw.pieslice([0, 0, 199, 99], 190, 170, width=10, fill="white", outline="red")

# Assert
assert_image_equal(im, Image.open("Tests/images/imagedraw_pieslice_wide.png"))


def helper_point(points):
# Arrange
im = Image.new("RGB", (W, H))
Expand Down
2 changes: 1 addition & 1 deletion Tests/test_imagedraw2.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def test_ellipse_edge():
brush = ImageDraw2.Brush("white")

# Act
draw.ellipse(((0, 0), (W - 1, H)), brush)
draw.ellipse(((0, 0), (W - 1, H - 1)), brush)

# Assert
assert_image_similar(im, Image.open("Tests/images/imagedraw_ellipse_edge.png"), 1)
Expand Down
2 changes: 1 addition & 1 deletion src/PIL/ImageDraw.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def _getink(self, ink, fill=None):
fill = self.draw.draw_ink(fill)
return ink, fill

def arc(self, xy, start, end, fill=None, width=0):
def arc(self, xy, start, end, fill=None, width=1):
"""Draw an arc."""
ink, fill = self._getink(fill)
if ink is not None:
Expand Down
5 changes: 2 additions & 3 deletions src/_imaging.c
Original file line number Diff line number Diff line change
Expand Up @@ -2834,8 +2834,7 @@ _draw_arc(ImagingDrawObject* self, PyObject* args)
int ink;
int width = 0;
float start, end;
int op = 0;
if (!PyArg_ParseTuple(args, "Offi|ii", &data, &start, &end, &ink, &width)) {
if (!PyArg_ParseTuple(args, "Offi|i", &data, &start, &end, &ink, &width)) {
return NULL;
}

Expand All @@ -2852,7 +2851,7 @@ _draw_arc(ImagingDrawObject* self, PyObject* args)
n = ImagingDrawArc(self->image->image,
(int) xy[0], (int) xy[1],
(int) xy[2], (int) xy[3],
start, end, &ink, width, op
start, end, &ink, width, self->blend
);

free(xy);
Expand Down
Loading