Skip to content
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
16 changes: 2 additions & 14 deletions src/PIL/ImageDraw.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,22 +365,10 @@ def polygon(
# use the fill as a mask
mask = Image.new("1", self.im.size)
mask_ink = self._getink(1)[0]

fill_im = mask.copy()
draw = Draw(fill_im)
draw = Draw(mask)
draw.draw.draw_polygon(xy, mask_ink, 1)

ink_im = mask.copy()
draw = Draw(ink_im)
width = width * 2 - 1
draw.draw.draw_polygon(xy, mask_ink, 0, width)

mask.paste(ink_im, mask=fill_im)

im = Image.new(self.mode, self.im.size)
draw = Draw(im)
draw.draw.draw_polygon(xy, ink, 0, width)
self.im.paste(im.im, (0, 0) + im.size, mask.im)
self.draw.draw_polygon(xy, ink, 0, width * 2 - 1, mask.im)

def regular_polygon(
self,
Expand Down
20 changes: 16 additions & 4 deletions src/_imaging.c
Original file line number Diff line number Diff line change
Expand Up @@ -3220,7 +3220,8 @@
(int)p[3],
&ink,
width,
self->blend
self->blend,
NULL
) < 0) {
free(xy);
return NULL;
Expand Down Expand Up @@ -3358,7 +3359,10 @@
int ink;
int fill = 0;
int width = 0;
if (!PyArg_ParseTuple(args, "Oi|ii", &data, &ink, &fill, &width)) {
ImagingObject *maskp = NULL;

Check warning on line 3362 in src/_imaging.c

View check run for this annotation

Codecov / codecov/patch

src/_imaging.c#L3362

Added line #L3362 was not covered by tests
if (!PyArg_ParseTuple(
args, "Oi|iiO!", &data, &ink, &fill, &width, &Imaging_Type, &maskp
)) {
return NULL;
}

Expand Down Expand Up @@ -3388,8 +3392,16 @@

free(xy);

if (ImagingDrawPolygon(self->image->image, n, ixy, &ink, fill, width, self->blend) <
0) {
if (ImagingDrawPolygon(
self->image->image,

Check warning on line 3396 in src/_imaging.c

View check run for this annotation

Codecov / codecov/patch

src/_imaging.c#L3396

Added line #L3396 was not covered by tests
n,
ixy,
&ink,
fill,
width,
self->blend,
maskp ? maskp->image : NULL

Check warning on line 3403 in src/_imaging.c

View check run for this annotation

Codecov / codecov/patch

src/_imaging.c#L3403

Added line #L3403 was not covered by tests
) < 0) {
free(ixy);
return NULL;
}
Expand Down
113 changes: 81 additions & 32 deletions src/libImaging/Draw.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
} Edge;

/* Type used in "polygon*" functions */
typedef void (*hline_handler)(Imaging, int, int, int, int);
typedef void (*hline_handler)(Imaging, int, int, int, int, Imaging);

static inline void
point8(Imaging im, int x, int y, int ink) {
Expand Down Expand Up @@ -103,7 +103,7 @@
}

static inline void
hline8(Imaging im, int x0, int y0, int x1, int ink) {
hline8(Imaging im, int x0, int y0, int x1, int ink, Imaging mask) {

Check warning on line 106 in src/libImaging/Draw.c

View check run for this annotation

Codecov / codecov/patch

src/libImaging/Draw.c#L106

Added line #L106 was not covered by tests
int pixelwidth;

if (y0 >= 0 && y0 < im->ysize) {
Expand All @@ -119,15 +119,30 @@
}
if (x0 <= x1) {
pixelwidth = strncmp(im->mode, "I;16", 4) == 0 ? 2 : 1;
memset(
im->image8[y0] + x0 * pixelwidth, (UINT8)ink, (x1 - x0 + 1) * pixelwidth
);
if (mask == NULL) {
memset(
im->image8[y0] + x0 * pixelwidth,
(UINT8)ink,
(x1 - x0 + 1) * pixelwidth

Check warning on line 126 in src/libImaging/Draw.c

View check run for this annotation

Codecov / codecov/patch

src/libImaging/Draw.c#L123-L126

Added lines #L123 - L126 were not covered by tests
);
} else {
UINT8 *p = im->image8[y0];

Check warning on line 129 in src/libImaging/Draw.c

View check run for this annotation

Codecov / codecov/patch

src/libImaging/Draw.c#L129

Added line #L129 was not covered by tests
while (x0 <= x1) {
if (mask->image8[y0][x0]) {
p[x0 * pixelwidth] = ink;

Check warning on line 132 in src/libImaging/Draw.c

View check run for this annotation

Codecov / codecov/patch

src/libImaging/Draw.c#L132

Added line #L132 was not covered by tests
if (pixelwidth == 2) {
p[x0 * pixelwidth + 1] = ink;

Check warning on line 134 in src/libImaging/Draw.c

View check run for this annotation

Codecov / codecov/patch

src/libImaging/Draw.c#L134

Added line #L134 was not covered by tests
}
}
x0++;

Check warning on line 137 in src/libImaging/Draw.c

View check run for this annotation

Codecov / codecov/patch

src/libImaging/Draw.c#L137

Added line #L137 was not covered by tests
}
}
}
}
}

static inline void
hline32(Imaging im, int x0, int y0, int x1, int ink) {
hline32(Imaging im, int x0, int y0, int x1, int ink, Imaging mask) {
INT32 *p;

if (y0 >= 0 && y0 < im->ysize) {
Expand All @@ -143,13 +158,16 @@
}
p = im->image32[y0];
while (x0 <= x1) {
p[x0++] = ink;
if (mask == NULL || mask->image8[y0][x0]) {
p[x0] = ink;
}
x0++;
}
}
}

static inline void
hline32rgba(Imaging im, int x0, int y0, int x1, int ink) {
hline32rgba(Imaging im, int x0, int y0, int x1, int ink, Imaging mask) {

Check warning on line 170 in src/libImaging/Draw.c

View check run for this annotation

Codecov / codecov/patch

src/libImaging/Draw.c#L170

Added line #L170 was not covered by tests
unsigned int tmp;

if (y0 >= 0 && y0 < im->ysize) {
Expand All @@ -167,9 +185,11 @@
UINT8 *out = (UINT8 *)im->image[y0] + x0 * 4;
UINT8 *in = (UINT8 *)&ink;
while (x0 <= x1) {
out[0] = BLEND(in[3], out[0], in[0], tmp);
out[1] = BLEND(in[3], out[1], in[1], tmp);
out[2] = BLEND(in[3], out[2], in[2], tmp);
if (mask == NULL || mask->image8[y0][x0]) {
out[0] = BLEND(in[3], out[0], in[0], tmp);
out[1] = BLEND(in[3], out[1], in[1], tmp);
out[2] = BLEND(in[3], out[2], in[2], tmp);

Check warning on line 191 in src/libImaging/Draw.c

View check run for this annotation

Codecov / codecov/patch

src/libImaging/Draw.c#L189-L191

Added lines #L189 - L191 were not covered by tests
}
x0++;
out += 4;
}
Expand Down Expand Up @@ -407,7 +427,14 @@

static void
draw_horizontal_lines(
Imaging im, int n, Edge *e, int ink, int *x_pos, int y, hline_handler hline
Imaging im,
int n,
Edge *e,
int ink,
int *x_pos,
int y,
hline_handler hline,
Imaging mask
) {
int i;
for (i = 0; i < n; i++) {
Expand All @@ -429,7 +456,7 @@
}
}

(*hline)(im, xmin, e[i].ymin, xmax, ink);
(*hline)(im, xmin, e[i].ymin, xmax, ink, mask);

Check warning on line 459 in src/libImaging/Draw.c

View check run for this annotation

Codecov / codecov/patch

src/libImaging/Draw.c#L459

Added line #L459 was not covered by tests
*x_pos = xmax + 1;
}
}
Expand All @@ -439,7 +466,9 @@
* Filled polygon draw function using scan line algorithm.
*/
static inline int
polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill, hline_handler hline) {
polygon_generic(

Check warning on line 469 in src/libImaging/Draw.c

View check run for this annotation

Codecov / codecov/patch

src/libImaging/Draw.c#L469

Added line #L469 was not covered by tests
Imaging im, int n, Edge *e, int ink, int eofill, hline_handler hline, Imaging mask
) {
Edge **edge_table;
float *xx;
int edge_count = 0;
Expand Down Expand Up @@ -469,7 +498,7 @@
}
if (e[i].ymin == e[i].ymax) {
if (hasAlpha != 1) {
(*hline)(im, e[i].xmin, e[i].ymin, e[i].xmax, ink);
(*hline)(im, e[i].xmin, e[i].ymin, e[i].xmax, ink, mask);

Check warning on line 501 in src/libImaging/Draw.c

View check run for this annotation

Codecov / codecov/patch

src/libImaging/Draw.c#L501

Added line #L501 was not covered by tests
}
continue;
}
Expand Down Expand Up @@ -557,7 +586,7 @@
// Line would be before the current position
continue;
}
draw_horizontal_lines(im, n, e, ink, &x_pos, ymin, hline);
draw_horizontal_lines(im, n, e, ink, &x_pos, ymin, hline, mask);

Check warning on line 589 in src/libImaging/Draw.c

View check run for this annotation

Codecov / codecov/patch

src/libImaging/Draw.c#L589

Added line #L589 was not covered by tests
if (x_end < x_pos) {
// Line would be before the current position
continue;
Expand All @@ -573,13 +602,13 @@
continue;
}
}
(*hline)(im, x_start, ymin, x_end, ink);
(*hline)(im, x_start, ymin, x_end, ink, mask);

Check warning on line 605 in src/libImaging/Draw.c

View check run for this annotation

Codecov / codecov/patch

src/libImaging/Draw.c#L605

Added line #L605 was not covered by tests
x_pos = x_end + 1;
}
draw_horizontal_lines(im, n, e, ink, &x_pos, ymin, hline);
draw_horizontal_lines(im, n, e, ink, &x_pos, ymin, hline, mask);

Check warning on line 608 in src/libImaging/Draw.c

View check run for this annotation

Codecov / codecov/patch

src/libImaging/Draw.c#L608

Added line #L608 was not covered by tests
} else {
for (i = 1; i < j; i += 2) {
(*hline)(im, ROUND_UP(xx[i - 1]), ymin, ROUND_DOWN(xx[i]), ink);
(*hline)(im, ROUND_UP(xx[i - 1]), ymin, ROUND_DOWN(xx[i]), ink, mask);

Check warning on line 611 in src/libImaging/Draw.c

View check run for this annotation

Codecov / codecov/patch

src/libImaging/Draw.c#L611

Added line #L611 was not covered by tests
}
}
}
Expand Down Expand Up @@ -623,7 +652,7 @@

typedef struct {
void (*point)(Imaging im, int x, int y, int ink);
void (*hline)(Imaging im, int x0, int y0, int x1, int ink);
void (*hline)(Imaging im, int x0, int y0, int x1, int ink, Imaging mask);
void (*line)(Imaging im, int x0, int y0, int x1, int y1, int ink);
} DRAW;

Expand Down Expand Up @@ -674,7 +703,15 @@

int
ImagingDrawWideLine(
Imaging im, int x0, int y0, int x1, int y1, const void *ink_, int width, int op
Imaging im,
int x0,
int y0,
int x1,
int y1,
const void *ink_,
int width,
int op,
Imaging mask
) {
DRAW *draw;
INT32 ink;
Expand Down Expand Up @@ -714,7 +751,7 @@
add_edge(e + 2, vertices[2][0], vertices[2][1], vertices[3][0], vertices[3][1]);
add_edge(e + 3, vertices[3][0], vertices[3][1], vertices[0][0], vertices[0][1]);

polygon_generic(im, 4, e, ink, 0, draw->hline);
polygon_generic(im, 4, e, ink, 0, draw->hline, mask);

Check warning on line 754 in src/libImaging/Draw.c

View check run for this annotation

Codecov / codecov/patch

src/libImaging/Draw.c#L754

Added line #L754 was not covered by tests
}
return 0;
}
Expand Down Expand Up @@ -757,7 +794,7 @@
}

for (y = y0; y <= y1; y++) {
draw->hline(im, x0, y, x1, ink);
draw->hline(im, x0, y, x1, ink, NULL);
}

} else {
Expand All @@ -766,8 +803,8 @@
width = 1;
}
for (i = 0; i < width; i++) {
draw->hline(im, x0, y0 + i, x1, ink);
draw->hline(im, x0, y1 - i, x1, ink);
draw->hline(im, x0, y0 + i, x1, ink, NULL);
draw->hline(im, x0, y1 - i, x1, ink, NULL);

Check warning on line 807 in src/libImaging/Draw.c

View check run for this annotation

Codecov / codecov/patch

src/libImaging/Draw.c#L806-L807

Added lines #L806 - L807 were not covered by tests
draw->line(im, x1 - i, y0 + width, x1 - i, y1 - width + 1, ink);
draw->line(im, x0 + i, y0 + width, x0 + i, y1 - width + 1, ink);
}
Expand All @@ -778,7 +815,14 @@

int
ImagingDrawPolygon(
Imaging im, int count, int *xy, const void *ink_, int fill, int width, int op
Imaging im,
int count,
int *xy,
const void *ink_,
int fill,
int width,
int op,
Imaging mask
) {
int i, n, x0, y0, x1, y1;
DRAW *draw;
Expand Down Expand Up @@ -822,7 +866,7 @@
if (xy[i * 2] != xy[0] || xy[i * 2 + 1] != xy[1]) {
add_edge(&e[n++], xy[i * 2], xy[i * 2 + 1], xy[0], xy[1]);
}
polygon_generic(im, n, e, ink, 0, draw->hline);
polygon_generic(im, n, e, ink, 0, draw->hline, mask);

Check warning on line 869 in src/libImaging/Draw.c

View check run for this annotation

Codecov / codecov/patch

src/libImaging/Draw.c#L869

Added line #L869 was not covered by tests
free(e);

} else {
Expand All @@ -844,11 +888,12 @@
xy[i * 2 + 3],
ink_,
width,
op
op,
mask
);
}
ImagingDrawWideLine(
im, xy[i * 2], xy[i * 2 + 1], xy[0], xy[1], ink_, width, op
im, xy[i * 2], xy[i * 2 + 1], xy[0], xy[1], ink_, width, op, mask

Check warning on line 896 in src/libImaging/Draw.c

View check run for this annotation

Codecov / codecov/patch

src/libImaging/Draw.c#L896

Added line #L896 was not covered by tests
);
}
}
Expand Down Expand Up @@ -1519,7 +1564,9 @@
ellipse_init(&st, a, b, width);
int32_t X0, Y, X1;
while (ellipse_next(&st, &X0, &Y, &X1) != -1) {
draw->hline(im, x0 + (X0 + a) / 2, y0 + (Y + b) / 2, x0 + (X1 + a) / 2, ink);
draw->hline(
im, x0 + (X0 + a) / 2, y0 + (Y + b) / 2, x0 + (X1 + a) / 2, ink, NULL

Check warning on line 1568 in src/libImaging/Draw.c

View check run for this annotation

Codecov / codecov/patch

src/libImaging/Draw.c#L1567-L1568

Added lines #L1567 - L1568 were not covered by tests
);
}
return 0;
}
Expand Down Expand Up @@ -1554,7 +1601,9 @@
int32_t X0, Y, X1;
int next_code;
while ((next_code = clip_ellipse_next(&st, &X0, &Y, &X1)) >= 0) {
draw->hline(im, x0 + (X0 + a) / 2, y0 + (Y + b) / 2, x0 + (X1 + a) / 2, ink);
draw->hline(
im, x0 + (X0 + a) / 2, y0 + (Y + b) / 2, x0 + (X1 + a) / 2, ink, NULL

Check warning on line 1605 in src/libImaging/Draw.c

View check run for this annotation

Codecov / codecov/patch

src/libImaging/Draw.c#L1604-L1605

Added lines #L1604 - L1605 were not covered by tests
);
}
clip_ellipse_free(&st);
return next_code == -1 ? 0 : -1;
Expand Down Expand Up @@ -1972,7 +2021,7 @@

DRAWINIT();

polygon_generic(im, outline->count, outline->edges, ink, 0, draw->hline);
polygon_generic(im, outline->count, outline->edges, ink, 0, draw->hline, NULL);

Check warning on line 2024 in src/libImaging/Draw.c

View check run for this annotation

Codecov / codecov/patch

src/libImaging/Draw.c#L2024

Added line #L2024 was not covered by tests

return 0;
}
19 changes: 17 additions & 2 deletions src/libImaging/Imaging.h
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,15 @@ extern int
ImagingDrawLine(Imaging im, int x0, int y0, int x1, int y1, const void *ink, int op);
extern int
ImagingDrawWideLine(
Imaging im, int x0, int y0, int x1, int y1, const void *ink, int width, int op
Imaging im,
int x0,
int y0,
int x1,
int y1,
const void *ink,
int width,
int op,
Imaging mask
);
extern int
ImagingDrawPieslice(
Expand All @@ -530,7 +538,14 @@ extern int
ImagingDrawPoint(Imaging im, int x, int y, const void *ink, int op);
extern int
ImagingDrawPolygon(
Imaging im, int points, int *xy, const void *ink, int fill, int width, int op
Imaging im,
int points,
int *xy,
const void *ink,
int fill,
int width,
int op,
Imaging mask
);
extern int
ImagingDrawRectangle(
Expand Down
Loading