Merge pull request #661 from hugovk/test_imagedraw
Add more ImageDraw tests
BIN
Tests/images/imagedraw_arc.png
Normal file
After Width: | Height: | Size: 284 B |
BIN
Tests/images/imagedraw_bitmap.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
Tests/images/imagedraw_chord.png
Normal file
After Width: | Height: | Size: 326 B |
BIN
Tests/images/imagedraw_ellipse.png
Normal file
After Width: | Height: | Size: 491 B |
BIN
Tests/images/imagedraw_floodfill.png
Normal file
After Width: | Height: | Size: 232 B |
BIN
Tests/images/imagedraw_floodfill2.png
Normal file
After Width: | Height: | Size: 212 B |
BIN
Tests/images/imagedraw_line.png
Normal file
After Width: | Height: | Size: 286 B |
BIN
Tests/images/imagedraw_pieslice.png
Normal file
After Width: | Height: | Size: 405 B |
BIN
Tests/images/imagedraw_point.png
Normal file
After Width: | Height: | Size: 124 B |
BIN
Tests/images/imagedraw_polygon.png
Normal file
After Width: | Height: | Size: 292 B |
BIN
Tests/images/imagedraw_rectangle.png
Normal file
After Width: | Height: | Size: 228 B |
|
@ -1,8 +1,27 @@
|
||||||
from tester import *
|
from tester import *
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
from PIL import ImageColor
|
||||||
from PIL import ImageDraw
|
from PIL import ImageDraw
|
||||||
|
|
||||||
|
# Image size
|
||||||
|
w, h = 100, 100
|
||||||
|
|
||||||
|
# Bounding box points
|
||||||
|
x0 = int(w / 4)
|
||||||
|
x1 = int(x0 * 3)
|
||||||
|
y0 = int(h / 4)
|
||||||
|
y1 = int(x0 * 3)
|
||||||
|
|
||||||
|
# Two kinds of bounding box
|
||||||
|
bbox1 = [(x0, y0), (x1, y1)]
|
||||||
|
bbox2 = [x0, y0, x1, y1]
|
||||||
|
|
||||||
|
# Two kinds of coordinate sequences
|
||||||
|
points1 = [(10, 10), (20, 40), (30, 30)]
|
||||||
|
points2 = [10, 10, 20, 40, 30, 30]
|
||||||
|
|
||||||
|
|
||||||
def test_sanity():
|
def test_sanity():
|
||||||
|
|
||||||
im = lena("RGB").copy()
|
im = lena("RGB").copy()
|
||||||
|
@ -17,6 +36,7 @@ def test_sanity():
|
||||||
|
|
||||||
success()
|
success()
|
||||||
|
|
||||||
|
|
||||||
def test_deprecated():
|
def test_deprecated():
|
||||||
|
|
||||||
im = lena().copy()
|
im = lena().copy()
|
||||||
|
@ -26,3 +46,220 @@ def test_deprecated():
|
||||||
assert_warning(DeprecationWarning, lambda: draw.setink(0))
|
assert_warning(DeprecationWarning, lambda: draw.setink(0))
|
||||||
assert_warning(DeprecationWarning, lambda: draw.setfill(0))
|
assert_warning(DeprecationWarning, lambda: draw.setfill(0))
|
||||||
|
|
||||||
|
|
||||||
|
def helper_arc(bbox):
|
||||||
|
# Arrange
|
||||||
|
im = Image.new("RGB", (w, h))
|
||||||
|
draw = ImageDraw.Draw(im)
|
||||||
|
|
||||||
|
# Act
|
||||||
|
# FIXME Fill param should be named outline.
|
||||||
|
draw.arc(bbox, 0, 180)
|
||||||
|
del draw
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
assert_image_equal(im, Image.open("Tests/images/imagedraw_arc.png"))
|
||||||
|
|
||||||
|
|
||||||
|
def test_arc1():
|
||||||
|
helper_arc(bbox1)
|
||||||
|
|
||||||
|
|
||||||
|
def test_arc2():
|
||||||
|
helper_arc(bbox2)
|
||||||
|
|
||||||
|
|
||||||
|
def test_bitmap():
|
||||||
|
# Arrange
|
||||||
|
small = Image.open("Tests/images/pil123rgba.png").resize((50, 50))
|
||||||
|
im = Image.new("RGB", (w, h))
|
||||||
|
draw = ImageDraw.Draw(im)
|
||||||
|
|
||||||
|
# Act
|
||||||
|
draw.bitmap((10, 10), small)
|
||||||
|
del draw
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
assert_image_equal(im, Image.open("Tests/images/imagedraw_bitmap.png"))
|
||||||
|
|
||||||
|
|
||||||
|
def helper_chord(bbox):
|
||||||
|
# Arrange
|
||||||
|
im = Image.new("RGB", (w, h))
|
||||||
|
draw = ImageDraw.Draw(im)
|
||||||
|
|
||||||
|
# Act
|
||||||
|
draw.chord(bbox, 0, 180, fill="red", outline="yellow")
|
||||||
|
del draw
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
assert_image_equal(im, Image.open("Tests/images/imagedraw_chord.png"))
|
||||||
|
|
||||||
|
|
||||||
|
def test_chord1():
|
||||||
|
helper_chord(bbox1)
|
||||||
|
|
||||||
|
|
||||||
|
def test_chord2():
|
||||||
|
helper_chord(bbox2)
|
||||||
|
|
||||||
|
|
||||||
|
def helper_ellipse(bbox):
|
||||||
|
# Arrange
|
||||||
|
im = Image.new("RGB", (w, h))
|
||||||
|
draw = ImageDraw.Draw(im)
|
||||||
|
|
||||||
|
# Act
|
||||||
|
draw.ellipse(bbox, fill="green", outline="blue")
|
||||||
|
del draw
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
assert_image_equal(im, Image.open("Tests/images/imagedraw_ellipse.png"))
|
||||||
|
|
||||||
|
|
||||||
|
def test_ellipse1():
|
||||||
|
helper_ellipse(bbox1)
|
||||||
|
|
||||||
|
|
||||||
|
def test_ellipse2():
|
||||||
|
helper_ellipse(bbox2)
|
||||||
|
|
||||||
|
|
||||||
|
def helper_line(points):
|
||||||
|
# Arrange
|
||||||
|
im = Image.new("RGB", (w, h))
|
||||||
|
draw = ImageDraw.Draw(im)
|
||||||
|
|
||||||
|
# Act
|
||||||
|
draw.line(points1, fill="yellow", width=2)
|
||||||
|
del draw
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
assert_image_equal(im, Image.open("Tests/images/imagedraw_line.png"))
|
||||||
|
|
||||||
|
|
||||||
|
def test_line1():
|
||||||
|
helper_line(points1)
|
||||||
|
|
||||||
|
|
||||||
|
def test_line2():
|
||||||
|
helper_line(points2)
|
||||||
|
|
||||||
|
|
||||||
|
def helper_pieslice(bbox):
|
||||||
|
# Arrange
|
||||||
|
im = Image.new("RGB", (w, h))
|
||||||
|
draw = ImageDraw.Draw(im)
|
||||||
|
|
||||||
|
# Act
|
||||||
|
draw.pieslice(bbox, -90, 45, fill="white", outline="blue")
|
||||||
|
del draw
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
assert_image_equal(im, Image.open("Tests/images/imagedraw_pieslice.png"))
|
||||||
|
|
||||||
|
|
||||||
|
def test_pieslice1():
|
||||||
|
helper_pieslice(bbox1)
|
||||||
|
|
||||||
|
|
||||||
|
def test_pieslice2():
|
||||||
|
helper_pieslice(bbox2)
|
||||||
|
|
||||||
|
|
||||||
|
def helper_point(points):
|
||||||
|
# Arrange
|
||||||
|
im = Image.new("RGB", (w, h))
|
||||||
|
draw = ImageDraw.Draw(im)
|
||||||
|
|
||||||
|
# Act
|
||||||
|
draw.point(points1, fill="yellow")
|
||||||
|
del draw
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
assert_image_equal(im, Image.open("Tests/images/imagedraw_point.png"))
|
||||||
|
|
||||||
|
|
||||||
|
def test_point1():
|
||||||
|
helper_point(points1)
|
||||||
|
|
||||||
|
|
||||||
|
def test_point2():
|
||||||
|
helper_point(points2)
|
||||||
|
|
||||||
|
|
||||||
|
def helper_polygon(points):
|
||||||
|
# Arrange
|
||||||
|
im = Image.new("RGB", (w, h))
|
||||||
|
draw = ImageDraw.Draw(im)
|
||||||
|
|
||||||
|
# Act
|
||||||
|
draw.polygon(points1, fill="red", outline="blue")
|
||||||
|
del draw
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
assert_image_equal(im, Image.open("Tests/images/imagedraw_polygon.png"))
|
||||||
|
|
||||||
|
|
||||||
|
def test_polygon1():
|
||||||
|
helper_polygon(points1)
|
||||||
|
|
||||||
|
|
||||||
|
def test_polygon2():
|
||||||
|
helper_polygon(points2)
|
||||||
|
|
||||||
|
|
||||||
|
def helper_rectangle(bbox):
|
||||||
|
# Arrange
|
||||||
|
im = Image.new("RGB", (w, h))
|
||||||
|
draw = ImageDraw.Draw(im)
|
||||||
|
|
||||||
|
# Act
|
||||||
|
draw.rectangle(bbox, fill="black", outline="green")
|
||||||
|
del draw
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
assert_image_equal(im, Image.open("Tests/images/imagedraw_rectangle.png"))
|
||||||
|
|
||||||
|
|
||||||
|
def test_rectangle1():
|
||||||
|
helper_rectangle(bbox1)
|
||||||
|
|
||||||
|
|
||||||
|
def test_rectangle2():
|
||||||
|
helper_rectangle(bbox2)
|
||||||
|
|
||||||
|
|
||||||
|
def test_floodfill():
|
||||||
|
# Arrange
|
||||||
|
im = Image.new("RGB", (w, h))
|
||||||
|
draw = ImageDraw.Draw(im)
|
||||||
|
draw.rectangle(bbox2, outline="yellow", fill="green")
|
||||||
|
centre_point = (int(w/2), int(h/2))
|
||||||
|
|
||||||
|
# Act
|
||||||
|
ImageDraw.floodfill(im, centre_point, ImageColor.getrgb("red"))
|
||||||
|
del draw
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
assert_image_equal(im, Image.open("Tests/images/imagedraw_floodfill.png"))
|
||||||
|
|
||||||
|
|
||||||
|
def test_floodfill_border():
|
||||||
|
# Arrange
|
||||||
|
im = Image.new("RGB", (w, h))
|
||||||
|
draw = ImageDraw.Draw(im)
|
||||||
|
draw.rectangle(bbox2, outline="yellow", fill="green")
|
||||||
|
centre_point = (int(w/2), int(h/2))
|
||||||
|
|
||||||
|
# Act
|
||||||
|
ImageDraw.floodfill(
|
||||||
|
im, centre_point, ImageColor.getrgb("red"),
|
||||||
|
border=ImageColor.getrgb("black"))
|
||||||
|
del draw
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
assert_image_equal(im, Image.open("Tests/images/imagedraw_floodfill2.png"))
|
||||||
|
|
||||||
|
|
||||||
|
# End of file
|
||||||
|
|
89
_imaging.c
|
@ -2399,17 +2399,35 @@ _draw_ink(ImagingDrawObject* self, PyObject* args)
|
||||||
static PyObject*
|
static PyObject*
|
||||||
_draw_arc(ImagingDrawObject* self, PyObject* args)
|
_draw_arc(ImagingDrawObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
int x0, y0, x1, y1;
|
double* xy;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
PyObject* data;
|
||||||
int ink;
|
int ink;
|
||||||
int start, end;
|
int start, end;
|
||||||
int op = 0;
|
int op = 0;
|
||||||
if (!PyArg_ParseTuple(args, "(iiii)iii|i",
|
if (!PyArg_ParseTuple(args, "Oiii|i", &data, &start, &end, &ink))
|
||||||
&x0, &y0, &x1, &y1,
|
|
||||||
&start, &end, &ink))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (ImagingDrawArc(self->image->image, x0, y0, x1, y1, start, end,
|
n = PyPath_Flatten(data, &xy);
|
||||||
&ink, op) < 0)
|
if (n < 0)
|
||||||
|
return NULL;
|
||||||
|
if (n != 2) {
|
||||||
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
"coordinate list must contain exactly 2 coordinates"
|
||||||
|
);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = ImagingDrawArc(self->image->image,
|
||||||
|
(int) xy[0], (int) xy[1],
|
||||||
|
(int) xy[2], (int) xy[3],
|
||||||
|
start, end, &ink, op
|
||||||
|
);
|
||||||
|
|
||||||
|
free(xy);
|
||||||
|
|
||||||
|
if (n < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
|
@ -2455,15 +2473,35 @@ _draw_bitmap(ImagingDrawObject* self, PyObject* args)
|
||||||
static PyObject*
|
static PyObject*
|
||||||
_draw_chord(ImagingDrawObject* self, PyObject* args)
|
_draw_chord(ImagingDrawObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
int x0, y0, x1, y1;
|
double* xy;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
PyObject* data;
|
||||||
int ink, fill;
|
int ink, fill;
|
||||||
int start, end;
|
int start, end;
|
||||||
if (!PyArg_ParseTuple(args, "(iiii)iiii",
|
if (!PyArg_ParseTuple(args, "Oiiii",
|
||||||
&x0, &y0, &x1, &y1, &start, &end, &ink, &fill))
|
&data, &start, &end, &ink, &fill))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (ImagingDrawChord(self->image->image, x0, y0, x1, y1,
|
n = PyPath_Flatten(data, &xy);
|
||||||
start, end, &ink, fill, self->blend) < 0)
|
if (n < 0)
|
||||||
|
return NULL;
|
||||||
|
if (n != 2) {
|
||||||
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
"coordinate list must contain exactly 2 coordinates"
|
||||||
|
);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = ImagingDrawChord(self->image->image,
|
||||||
|
(int) xy[0], (int) xy[1],
|
||||||
|
(int) xy[2], (int) xy[3],
|
||||||
|
start, end, &ink, fill, self->blend
|
||||||
|
);
|
||||||
|
|
||||||
|
free(xy);
|
||||||
|
|
||||||
|
if (n < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
|
@ -2656,15 +2694,34 @@ _draw_outline(ImagingDrawObject* self, PyObject* args)
|
||||||
static PyObject*
|
static PyObject*
|
||||||
_draw_pieslice(ImagingDrawObject* self, PyObject* args)
|
_draw_pieslice(ImagingDrawObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
int x0, y0, x1, y1;
|
double* xy;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
PyObject* data;
|
||||||
int ink, fill;
|
int ink, fill;
|
||||||
int start, end;
|
int start, end;
|
||||||
if (!PyArg_ParseTuple(args, "(iiii)iiii",
|
if (!PyArg_ParseTuple(args, "Oiiii", &data, &start, &end, &ink, &fill))
|
||||||
&x0, &y0, &x1, &y1, &start, &end, &ink, &fill))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (ImagingDrawPieslice(self->image->image, x0, y0, x1, y1,
|
n = PyPath_Flatten(data, &xy);
|
||||||
start, end, &ink, fill, self->blend) < 0)
|
if (n < 0)
|
||||||
|
return NULL;
|
||||||
|
if (n != 2) {
|
||||||
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
"coordinate list must contain exactly 2 coordinates"
|
||||||
|
);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = ImagingDrawPieslice(self->image->image,
|
||||||
|
(int) xy[0], (int) xy[1],
|
||||||
|
(int) xy[2], (int) xy[3],
|
||||||
|
start, end, &ink, fill, self->blend
|
||||||
|
);
|
||||||
|
|
||||||
|
free(xy);
|
||||||
|
|
||||||
|
if (n < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
|
|
|
@ -91,9 +91,12 @@ Methods
|
||||||
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.
|
||||||
|
|
||||||
:param xy: Four points to define the bounding box. Sequence of either
|
:param xy: Four points to define the bounding box. Sequence of
|
||||||
``[(x0, y0), (x1, y1)]`` or ``[x0, y0, x1, y1]``.
|
``[(x0, y0), (x1, y1)]`` or ``[x0, y0, x1, y1]``.
|
||||||
:param outline: Color to use for the outline.
|
:param start: Starting angle, in degrees. Angles are measured from
|
||||||
|
3 o'clock, increasing clockwise.
|
||||||
|
:param end: Ending angle, in degrees.
|
||||||
|
:param fill: Color to use for the arc.
|
||||||
|
|
||||||
.. py:method:: PIL.ImageDraw.Draw.bitmap(xy, bitmap, fill=None)
|
.. py:method:: PIL.ImageDraw.Draw.bitmap(xy, bitmap, fill=None)
|
||||||
|
|
||||||
|
@ -111,7 +114,7 @@ Methods
|
||||||
Same as :py:meth:`~PIL.ImageDraw.Draw.arc`, but connects the end points
|
Same as :py:meth:`~PIL.ImageDraw.Draw.arc`, but connects the end points
|
||||||
with a straight line.
|
with a straight line.
|
||||||
|
|
||||||
:param xy: Four points to define the bounding box. Sequence of either
|
:param xy: Four points to define the bounding box. Sequence of
|
||||||
``[(x0, y0), (x1, y1)]`` or ``[x0, y0, x1, y1]``.
|
``[(x0, y0), (x1, y1)]`` or ``[x0, y0, x1, y1]``.
|
||||||
:param outline: Color to use for the outline.
|
:param outline: Color to use for the outline.
|
||||||
:param fill: Color to use for the fill.
|
:param fill: Color to use for the fill.
|
||||||
|
@ -144,7 +147,7 @@ Methods
|
||||||
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.
|
||||||
|
|
||||||
:param xy: Four points to define the bounding box. Sequence of either
|
:param xy: Four points to define the bounding box. Sequence of
|
||||||
``[(x0, y0), (x1, y1)]`` or ``[x0, y0, x1, y1]``.
|
``[(x0, y0), (x1, y1)]`` or ``[x0, y0, x1, y1]``.
|
||||||
:param outline: Color to use for the outline.
|
:param outline: Color to use for the outline.
|
||||||
:param fill: Color to use for the fill.
|
:param fill: Color to use for the fill.
|
||||||
|
|