Skip to content

Commit ea1e317

Browse files
committed
Avoid blend work in point32rgba/hline32rgba/line32rgba when possible
1 parent f600687 commit ea1e317

1 file changed

Lines changed: 56 additions & 21 deletions

File tree

src/libImaging/Draw.c

Lines changed: 56 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,23 @@ point32(Imaging im, int x, int y, int ink) {
9292
static inline void
9393
point32rgba(Imaging im, int x, int y, int ink) {
9494
unsigned int tmp;
95+
UINT8 *in = (UINT8 *)&ink;
96+
int a = in[3];
97+
if (a == 0) { // Transparent ink. Nothing to paint.
98+
return;
99+
}
95100

96101
if (x >= 0 && x < im->xsize && y >= 0 && y < im->ysize) {
97102
UINT8 *out = (UINT8 *)im->image[y] + x * 4;
98-
UINT8 *in = (UINT8 *)&ink;
99-
out[0] = BLEND(in[3], out[0], in[0], tmp);
100-
out[1] = BLEND(in[3], out[1], in[1], tmp);
101-
out[2] = BLEND(in[3], out[2], in[2], tmp);
103+
if (a == 255) { // Solid ink, no need to blend.
104+
out[0] = in[0];
105+
out[1] = in[1];
106+
out[2] = in[2];
107+
} else {
108+
out[0] = BLEND(in[3], out[0], in[0], tmp);
109+
out[1] = BLEND(in[3], out[1], in[1], tmp);
110+
out[2] = BLEND(in[3], out[2], in[2], tmp);
111+
}
102112
}
103113
}
104114

@@ -188,32 +198,52 @@ hline32rgba(Imaging im, int x0, int y0, int x1, int ink, Imaging mask) {
188198
UINT8 b = ((UINT8 *)&ink)[2];
189199
UINT8 a = ((UINT8 *)&ink)[3];
190200

191-
if (y0 >= 0 && y0 < im->ysize) {
192-
if (x0 < 0) {
193-
x0 = 0;
194-
} else if (x0 >= im->xsize) {
195-
return;
196-
}
197-
if (x1 < 0) {
198-
return;
199-
} else if (x1 >= im->xsize) {
200-
x1 = im->xsize - 1;
201-
}
202-
if (x0 > x1) {
203-
return;
204-
}
201+
if (a == 0) { // Transparent ink. Nothing to paint.
202+
return;
203+
}
205204

206-
UINT8 *restrict out = (UINT8 *)im->image[y0] + x0 * 4;
207-
if (mask == NULL) {
205+
int xsize = im->xsize, ysize = im->ysize;
206+
if (y0 < 0 || y0 >= ysize || x0 >= xsize || x1 < 0) {
207+
// Painting outside the canvas.
208+
return;
209+
}
210+
211+
x0 = x0 < 0 ? 0 : x0;
212+
x1 = x1 >= xsize ? xsize - 1 : x1;
213+
214+
UINT8 *restrict out = (UINT8 *)im->image[y0] + x0 * 4;
215+
216+
if (mask == NULL) {
217+
if (a == 255) { // Solid ink, no need to blend.
218+
for (; x0 <= x1; x0++, out += 4) {
219+
out[0] = r;
220+
out[1] = g;
221+
out[2] = b;
222+
// No-op, but allows the compiler to vectorize the loop:
223+
out[3] = BLEND(255, out[3], out[3], tmp);
224+
}
225+
} else {
208226
for (; x0 <= x1; x0++, out += 4) {
209227
out[0] = BLEND(a, out[0], r, tmp);
210228
out[1] = BLEND(a, out[1], g, tmp);
211229
out[2] = BLEND(a, out[2], b, tmp);
212230
// No-op, but allows the compiler to vectorize the loop:
213231
out[3] = BLEND(a, out[3], out[3], tmp);
214232
}
233+
}
234+
} else {
235+
UINT8 *mask_row = mask->image8[y0];
236+
if (a == 255) { // Solid paint, no need to blend.
237+
for (; x0 <= x1; x0++, out += 4) {
238+
if (mask_row[x0]) {
239+
out[0] = r;
240+
out[1] = g;
241+
out[2] = b;
242+
// Not touching out[3] here, since the mask check prevents
243+
// vectorization anyway.
244+
}
245+
}
215246
} else {
216-
UINT8 *mask_row = mask->image8[y0];
217247
for (; x0 <= x1; x0++, out += 4) {
218248
if (mask_row[x0]) {
219249
out[0] = BLEND(a, out[0], r, tmp);
@@ -377,6 +407,11 @@ line32rgba(Imaging im, int x0, int y0, int x1, int y1, int ink) {
377407
int dx, dy;
378408
int xs, ys;
379409

410+
UINT8 a = ((UINT8 *)&ink)[3];
411+
if (a == 0) { // Transparent ink. Nothing to paint.
412+
return;
413+
}
414+
380415
/* normalize coordinates */
381416
dx = x1 - x0;
382417
if (dx < 0) {

0 commit comments

Comments
 (0)