aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorinmarket <andrewh@inmarket.com.au>2017-10-10 09:21:06 +1000
committerinmarket <andrewh@inmarket.com.au>2017-10-10 09:21:06 +1000
commit2a249e6140307c1cfaa1ce6f7775caf3f7be4b79 (patch)
treee15686b150eb112809421d4a02c59edabdcb2c03
parentc3b484a865a98bff5a89115c56364fdb7a2d854d (diff)
downloaduGFX-2a249e6140307c1cfaa1ce6f7775caf3f7be4b79.tar.gz
uGFX-2a249e6140307c1cfaa1ce6f7775caf3f7be4b79.tar.bz2
uGFX-2a249e6140307c1cfaa1ce6f7775caf3f7be4b79.zip
Update to hacked alpha support - now uses pre-multiplied color blending algorithm
-rw-r--r--src/gdisp/gdisp.c61
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)