diff options
| -rw-r--r-- | src/gdisp/gdisp.c | 61 | 
1 files changed, 42 insertions, 19 deletions
| diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index 3af31ac2..81d0dd0f 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -3654,26 +3654,49 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co  	// Note: this will still work with real RGB888  	color_t gdispBlendColor(color_t fg, color_t bg, uint8_t alpha)  	{ -		uint16_t fg_ratio = alpha + 1; -		uint16_t bg_ratio = 256 - alpha; -		uint16_t a, r, g, b; - -		a = ALPHA_OF(fg) * fg_ratio; -		r = RED_OF(fg) * fg_ratio; -		g = GREEN_OF(fg) * fg_ratio; -		b = BLUE_OF(fg) * fg_ratio; - -		a += ALPHA_OF(bg) * bg_ratio; -		r += RED_OF(bg) * bg_ratio; -		g += GREEN_OF(bg) * bg_ratio; -		b += BLUE_OF(bg) * bg_ratio; - -		a >>= 8; -		r >>= 8; -		g >>= 8; -		b >>= 8; +		uint32_t ratio; +		uint32_t a1, r1, g1, b1; +		uint32_t a2, r2, g2, b2; + +		// Ratio - add one to get 1 to 256 +		ratio = (uint32_t)alpha + 1;		// 0 to 1 in 0.8 fixed point + +		// Calculate the pre-multiplied values of r, g, b for the fg color +		a1 = ALPHA_OF(fg);					// 0 to 1 in 0.8 fixed point +		r1 = RED_OF(fg) * a1;				// 0 to 1 in 0.16 fixed point +		g1 = GREEN_OF(fg) * a1;				// 0 to 1 in 0.16 fixed point +		b1 = BLUE_OF(fg) * a1;				// 0 to 1 in 0.16 fixed point + +		// Calculate the pre-multiplied values of r, g, b for the bg color +		a2 = ALPHA_OF(bg);					// 0 to 1 in 0.8 fixed point +		r2 = RED_OF(bg) * a2;				// 0 to 1 in 0.16 fixed point +		g2 = GREEN_OF(bg) * a2;				// 0 to 1 in 0.16 fixed point +		b2 = BLUE_OF(bg) * a2;				// 0 to 1 in 0.16 fixed point + +		// Calculate the mixed color values +		a1 = ratio * (a1 - a2) + (a2<<8);	// 0 to 1 in 0.16 fixed point +		if (!a1) return GFXTRANSPARENT; +		r1 = ((ratio * (r1 - r2))>>8) + r2;	// 0 to 1 in 0.16 fixed point +		g1 = ((ratio * (g1 - g2))>>8) + g2;	// 0 to 1 in 0.16 fixed point +		b1 = ((ratio * (b1 - b2))>>8) + b2;	// 0 to 1 in 0.16 fixed point + +		// Fix precision +		#if 1 +			// Convert back to un-multiplied values +			ratio = 0x80000000 / a1;		// Divide 1 (0.31 fixed point) by a1 (0.16 fixed point) to get the a1 reciprocal in 0.15 fixed point +			a1 >>= 8;						// Shift to get back to 0.8 fixed point +			r1 = (r1 * ratio) >> 23;		// Multiply by ratio to get 0.31 and then shift to get back to 0.8 fixed point +			g1 = (g1 * ratio) >> 23;		// Multiply by ratio to get 0.31 and then shift to get back to 0.8 fixed point +			b1 = (b1 * ratio) >> 23;		// Multiply by ratio to get 0.31 and then shift to get back to 0.8 fixed point +		#else +			// Leave as pre-multiplied values +			a1 >>= 8;						// Shift to get back to 0.8 fixed point +			r1 >>= 8;						// Shift to get back to 0.8 fixed point +			g1 >>= 8;						// Shift to get back to 0.8 fixed point +			b1 >>= 8;						// Shift to get back to 0.8 fixed point +		#endif -		return ARGB2COLOR(a, r, g, b); +		return ARGB2COLOR(a1, r1, g1, b1);  	}  #else  	color_t gdispBlendColor(color_t fg, color_t bg, uint8_t alpha) | 
