Update blending logic

- Unpremultiply properly
- No longer uses floats
This commit is contained in:
ZachNagengast 2023-11-03 15:05:31 -07:00
parent f97570f523
commit bb0eff44cd

View File

@ -1049,6 +1049,7 @@ font_render(FontObject *self, PyObject *args) {
int k; int k;
unsigned char v; unsigned char v;
unsigned char *target; unsigned char *target;
unsigned int tmp;
if (color) { if (color) {
/* target[RGB] returns the color, target[A] returns the mask */ /* target[RGB] returns the color, target[A] returns the mask */
/* target bands get split again in ImageDraw.text */ /* target bands get split again in ImageDraw.text */
@ -1059,25 +1060,33 @@ font_render(FontObject *self, PyObject *args) {
if (color && bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) { if (color && bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) {
/* paste color glyph */ /* paste color glyph */
for (k = x0; k < x1; k++) { for (k = x0; k < x1; k++) {
float src_alpha = (float) source[k * 4 + 3] / 255.0; int src_alpha = source[k * 4 + 3];
float dst_alpha = (float) target[k * 4 + 3] / 255.0;
float out_alpha = src_alpha + dst_alpha * (1.0 - src_alpha);
/* unpremultiply BGRa to RGBA */ /* paste only if source has data */
int src_red = source[k * 4 + 0]; if (src_alpha > 0) {
int src_grn = source[k * 4 + 1]; /* unpremultiply RGBA */
int src_blu = source[k * 4 + 2]; int src_red = CLIP8((255 * (int)source[k * 4 + 0]) / src_alpha);
int src_grn = CLIP8((255 * (int)source[k * 4 + 1]) / src_alpha);
int src_blu = CLIP8((255 * (int)source[k * 4 + 2]) / src_alpha);
int dst_blu = target[k * 4 + 0]; /* blend required if target has data */
int dst_grn = target[k * 4 + 1]; if (target[k * 4 + 3] > 0) {
int dst_red = target[k * 4 + 2]; /* blend colors to BGRa */
target[k * 4 + 0] = BLEND(src_alpha, target[k * 4 + 0], src_blu, tmp);
target[k * 4 + 1] = BLEND(src_alpha, target[k * 4 + 1], src_grn, tmp);
target[k * 4 + 2] = BLEND(src_alpha, target[k * 4 + 2], src_red, tmp);
/* blend color values */ /* blend alpha */
target[k * 4 + 0] = CLIP8((src_blu * src_alpha + dst_blu * dst_alpha * (1.0 - src_alpha)) / out_alpha); int out_alpha = CLIP8(src_alpha + MULDIV255(target[k * 4 + 3], (255 - src_alpha), tmp));
target[k * 4 + 1] = CLIP8((src_grn * src_alpha + dst_grn * dst_alpha * (1.0 - src_alpha)) / out_alpha); target[k * 4 + 3] = out_alpha;
target[k * 4 + 2] = CLIP8((src_red * src_alpha + dst_red * dst_alpha * (1.0 - src_alpha)) / out_alpha); } else {
/* paste source directly to BGRa */
target[k * 4 + 3] = CLIP8(out_alpha * 255.0); target[k * 4 + 0] = src_blu;
target[k * 4 + 1] = src_grn;
target[k * 4 + 2] = src_red;
target[k * 4 + 3] = src_alpha;
}
}
} }
} else if (bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) { } else if (bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) {
if (color) { if (color) {