Merge pull request #5835 from radarhere/alpha

This commit is contained in:
Hugo van Kemenade 2021-11-16 09:07:18 +02:00 committed by GitHub
commit 2849347694
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 48 additions and 26 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 B

View File

@ -638,6 +638,19 @@ def test_polygon_1px_high():
assert_image_equal_tofile(im, expected) assert_image_equal_tofile(im, expected)
def test_polygon_translucent():
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im, "RGBA")
# Act
draw.polygon([(20, 80), (80, 80), (80, 20)], fill=(0, 255, 0, 127))
# Assert
expected = "Tests/images/imagedraw_polygon_translucent.png"
assert_image_equal_tofile(im, expected)
def helper_rectangle(bbox): def helper_rectangle(bbox):
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))

View File

@ -444,7 +444,7 @@ draw_horizontal_lines(
* Filled polygon draw function using scan line algorithm. * Filled polygon draw function using scan line algorithm.
*/ */
static inline int static inline int
polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill, hline_handler hline) { polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill, hline_handler hline, int hasAlpha) {
Edge **edge_table; Edge **edge_table;
float *xx; float *xx;
int edge_count = 0; int edge_count = 0;
@ -471,6 +471,9 @@ polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill, hline_handler h
ymax = e[i].ymax; ymax = e[i].ymax;
} }
if (e[i].ymin == e[i].ymax) { if (e[i].ymin == e[i].ymax) {
if (hasAlpha != 1) {
(*hline)(im, e[i].xmin, e[i].ymin, e[i].xmax, ink);
}
continue; continue;
} }
edge_table[edge_count++] = (e + i); edge_table[edge_count++] = (e + i);
@ -491,7 +494,6 @@ polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill, hline_handler h
} }
for (; ymin <= ymax; ymin++) { for (; ymin <= ymax; ymin++) {
int j = 0; int j = 0;
int x_pos = 0;
for (i = 0; i < edge_count; i++) { for (i = 0; i < edge_count; i++) {
Edge *current = edge_table[i]; Edge *current = edge_table[i];
if (ymin >= current->ymin && ymin <= current->ymax) { if (ymin >= current->ymin && ymin <= current->ymax) {
@ -504,31 +506,38 @@ polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill, hline_handler h
} }
} }
qsort(xx, j, sizeof(float), x_cmp); qsort(xx, j, sizeof(float), x_cmp);
for (i = 1; i < j; i += 2) { if (hasAlpha == 1) {
int x_end = ROUND_DOWN(xx[i]); int x_pos = 0;
if (x_end < x_pos) { for (i = 1; i < j; i += 2) {
// Line would be before the current position int x_end = ROUND_DOWN(xx[i]);
continue; if (x_end < x_pos) {
} // Line would be before the current position
draw_horizontal_lines(im, n, e, ink, &x_pos, ymin, hline);
if (x_end < x_pos) {
// Line would be before the current position
continue;
}
int x_start = ROUND_UP(xx[i - 1]);
if (x_pos > x_start) {
// Line would be partway through x_pos, so increase the starting point
x_start = x_pos;
if (x_end < x_start) {
// Line would now end before it started
continue; continue;
} }
draw_horizontal_lines(im, n, e, ink, &x_pos, ymin, hline);
if (x_end < x_pos) {
// Line would be before the current position
continue;
}
int x_start = ROUND_UP(xx[i - 1]);
if (x_pos > x_start) {
// Line would be partway through x_pos, so increase the starting point
x_start = x_pos;
if (x_end < x_start) {
// Line would now end before it started
continue;
}
}
(*hline)(im, x_start, ymin, x_end, ink);
x_pos = x_end + 1;
}
draw_horizontal_lines(im, n, e, ink, &x_pos, ymin, hline);
} else {
for (i = 1; i < j; i += 2) {
(*hline)(im, ROUND_UP(xx[i - 1]), ymin, ROUND_DOWN(xx[i]), ink);
} }
(*hline)(im, x_start, ymin, x_end, ink);
x_pos = x_end + 1;
} }
draw_horizontal_lines(im, n, e, ink, &x_pos, ymin, hline);
} }
free(xx); free(xx);
@ -538,17 +547,17 @@ polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill, hline_handler h
static inline int static inline int
polygon8(Imaging im, int n, Edge *e, int ink, int eofill) { polygon8(Imaging im, int n, Edge *e, int ink, int eofill) {
return polygon_generic(im, n, e, ink, eofill, hline8); return polygon_generic(im, n, e, ink, eofill, hline8, 0);
} }
static inline int static inline int
polygon32(Imaging im, int n, Edge *e, int ink, int eofill) { polygon32(Imaging im, int n, Edge *e, int ink, int eofill) {
return polygon_generic(im, n, e, ink, eofill, hline32); return polygon_generic(im, n, e, ink, eofill, hline32, 0);
} }
static inline int static inline int
polygon32rgba(Imaging im, int n, Edge *e, int ink, int eofill) { polygon32rgba(Imaging im, int n, Edge *e, int ink, int eofill) {
return polygon_generic(im, n, e, ink, eofill, hline32rgba); return polygon_generic(im, n, e, ink, eofill, hline32rgba, 1);
} }
static inline void static inline void