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 PIL import Image
|
||||
from PIL import ImageColor
|
||||
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():
|
||||
|
||||
im = lena("RGB").copy()
|
||||
|
@ -17,6 +36,7 @@ def test_sanity():
|
|||
|
||||
success()
|
||||
|
||||
|
||||
def test_deprecated():
|
||||
|
||||
im = lena().copy()
|
||||
|
@ -26,3 +46,220 @@ def test_deprecated():
|
|||
assert_warning(DeprecationWarning, lambda: draw.setink(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
|
||||
|
|
109
_imaging.c
|
@ -2252,17 +2252,17 @@ void _font_text_asBytes(PyObject* encoded_string, unsigned char** text){
|
|||
if (bytes) {
|
||||
*text = (unsigned char*)PyBytes_AsString(bytes);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#if PY_VERSION_HEX < 0x03000000
|
||||
/* likely case here is py2.x with an ordinary string.
|
||||
but this isn't defined in Py3.x */
|
||||
if (PyString_Check(encoded_string)) {
|
||||
*text = (unsigned char *)PyString_AsString(encoded_string);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
static PyObject*
|
||||
_font_getmask(ImagingFontObject* self, PyObject* args)
|
||||
|
@ -2336,7 +2336,7 @@ _font_getsize(ImagingFontObject* self, PyObject* args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return Py_BuildValue("ii", textwidth(self, text), self->ysize);
|
||||
return Py_BuildValue("ii", textwidth(self, text), self->ysize);
|
||||
}
|
||||
|
||||
static struct PyMethodDef _font_methods[] = {
|
||||
|
@ -2399,17 +2399,35 @@ _draw_ink(ImagingDrawObject* self, PyObject* args)
|
|||
static PyObject*
|
||||
_draw_arc(ImagingDrawObject* self, PyObject* args)
|
||||
{
|
||||
int x0, y0, x1, y1;
|
||||
double* xy;
|
||||
int n;
|
||||
|
||||
PyObject* data;
|
||||
int ink;
|
||||
int start, end;
|
||||
int op = 0;
|
||||
if (!PyArg_ParseTuple(args, "(iiii)iii|i",
|
||||
&x0, &y0, &x1, &y1,
|
||||
&start, &end, &ink))
|
||||
if (!PyArg_ParseTuple(args, "Oiii|i", &data, &start, &end, &ink))
|
||||
return NULL;
|
||||
|
||||
if (ImagingDrawArc(self->image->image, x0, y0, x1, y1, start, end,
|
||||
&ink, op) < 0)
|
||||
n = PyPath_Flatten(data, &xy);
|
||||
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;
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
|
@ -2455,15 +2473,35 @@ _draw_bitmap(ImagingDrawObject* self, PyObject* args)
|
|||
static PyObject*
|
||||
_draw_chord(ImagingDrawObject* self, PyObject* args)
|
||||
{
|
||||
int x0, y0, x1, y1;
|
||||
double* xy;
|
||||
int n;
|
||||
|
||||
PyObject* data;
|
||||
int ink, fill;
|
||||
int start, end;
|
||||
if (!PyArg_ParseTuple(args, "(iiii)iiii",
|
||||
&x0, &y0, &x1, &y1, &start, &end, &ink, &fill))
|
||||
if (!PyArg_ParseTuple(args, "Oiiii",
|
||||
&data, &start, &end, &ink, &fill))
|
||||
return NULL;
|
||||
|
||||
if (ImagingDrawChord(self->image->image, x0, y0, x1, y1,
|
||||
start, end, &ink, fill, self->blend) < 0)
|
||||
n = PyPath_Flatten(data, &xy);
|
||||
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;
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
|
@ -2492,8 +2530,8 @@ _draw_ellipse(ImagingDrawObject* self, PyObject* args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
n = ImagingDrawEllipse(self->image->image,
|
||||
(int) xy[0], (int) xy[1],
|
||||
n = ImagingDrawEllipse(self->image->image,
|
||||
(int) xy[0], (int) xy[1],
|
||||
(int) xy[2], (int) xy[3],
|
||||
&ink, fill, self->blend
|
||||
);
|
||||
|
@ -2656,15 +2694,34 @@ _draw_outline(ImagingDrawObject* self, PyObject* args)
|
|||
static PyObject*
|
||||
_draw_pieslice(ImagingDrawObject* self, PyObject* args)
|
||||
{
|
||||
int x0, y0, x1, y1;
|
||||
double* xy;
|
||||
int n;
|
||||
|
||||
PyObject* data;
|
||||
int ink, fill;
|
||||
int start, end;
|
||||
if (!PyArg_ParseTuple(args, "(iiii)iiii",
|
||||
&x0, &y0, &x1, &y1, &start, &end, &ink, &fill))
|
||||
if (!PyArg_ParseTuple(args, "Oiiii", &data, &start, &end, &ink, &fill))
|
||||
return NULL;
|
||||
|
||||
if (ImagingDrawPieslice(self->image->image, x0, y0, x1, y1,
|
||||
start, end, &ink, fill, self->blend) < 0)
|
||||
n = PyPath_Flatten(data, &xy);
|
||||
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;
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
|
@ -2738,9 +2795,9 @@ _draw_rectangle(ImagingDrawObject* self, PyObject* args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
n = ImagingDrawRectangle(self->image->image,
|
||||
n = ImagingDrawRectangle(self->image->image,
|
||||
(int) xy[0], (int) xy[1],
|
||||
(int) xy[2], (int) xy[3],
|
||||
(int) xy[2], (int) xy[3],
|
||||
&ink, fill, self->blend
|
||||
);
|
||||
|
||||
|
@ -3117,8 +3174,8 @@ _getattr_ptr(ImagingObject* self, void* closure)
|
|||
static PyObject*
|
||||
_getattr_unsafe_ptrs(ImagingObject* self, void* closure)
|
||||
{
|
||||
return Py_BuildValue("(ss)(si)(si)(si)(si)(si)(sn)(sn)(sn)(sn)(sn)(si)(si)(sn)",
|
||||
"mode", self->image->mode,
|
||||
return Py_BuildValue("(ss)(si)(si)(si)(si)(si)(sn)(sn)(sn)(sn)(sn)(si)(si)(sn)",
|
||||
"mode", self->image->mode,
|
||||
"type", self->image->type,
|
||||
"depth", self->image->depth,
|
||||
"bands", self->image->bands,
|
||||
|
|
|
@ -91,9 +91,12 @@ Methods
|
|||
Draws an arc (a portion of a circle outline) between the start and end
|
||||
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]``.
|
||||
: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)
|
||||
|
||||
|
@ -111,7 +114,7 @@ Methods
|
|||
Same as :py:meth:`~PIL.ImageDraw.Draw.arc`, but connects the end points
|
||||
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]``.
|
||||
:param outline: Color to use for the outline.
|
||||
: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
|
||||
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]``.
|
||||
:param outline: Color to use for the outline.
|
||||
:param fill: Color to use for the fill.
|
||||
|
|