diff options
author | Geoff Levand <geoff@infradead.org> | 2011-11-25 17:16:30 -0800 |
---|---|---|
committer | Geoff Levand <geoff@infradead.org> | 2011-12-11 15:06:22 -0800 |
commit | ea951fb17d38c06d5db4920ef5f2d6e014667c2c (patch) | |
tree | 91a0492ca8a72c32c7d2b6eac1aa9ab9817f7695 | |
parent | 33093a0dff8b8ffceb68f424bcd18cc7eae760a3 (diff) | |
download | libtwin-ea951fb17d38c06d5db4920ef5f2d6e014667c2c.tar.gz |
Fix png little endian alpha
Add a new helper routine _twin_apply_alpha() that handles
big and little endian details of alpha multiplication
for png to ARGB32.
Signed-off-by: Geoff Levand <geoff@infradead.org>
-rw-r--r-- | libtwin/twin_draw.c | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/libtwin/twin_draw.c b/libtwin/twin_draw.c index 3b19984..39af904 100644 --- a/libtwin/twin_draw.c +++ b/libtwin/twin_draw.c @@ -641,11 +641,34 @@ void twin_composite (twin_pixmap_t *dst, operator, width, height); } +static twin_argb32_t _twin_apply_alpha(twin_argb32_t v) +{ + uint16_t t1, t2, t3; + twin_a8_t alpha = twin_get_8(v, (__BYTE_ORDER == __BIG_ENDIAN) ? 24 : 0); + + /* clear RGB data if alpha is zero */ + + if (!alpha) + return 0; + + /* twin needs ARGB format */ + + if (__BYTE_ORDER == __BIG_ENDIAN) + return alpha << 24 | + twin_int_mult(twin_get_8(v, 16), alpha, t1) << 16 | + twin_int_mult(twin_get_8(v, 8), alpha, t2) << 8 | + twin_int_mult(twin_get_8(v, 0), alpha, t3) << 0; + + return alpha << 24 | + twin_int_mult(twin_get_8(v, 8), alpha, t1) << 16 | + twin_int_mult(twin_get_8(v, 16), alpha, t2) << 8 | + twin_int_mult(twin_get_8(v, 24), alpha, t3) << 0; +} + void twin_premultiply_alpha(twin_pixmap_t *px) { int x, y; twin_pointer_t p; - uint16_t t1, t2, t3; if (px->format != TWIN_ARGB32) return; @@ -653,15 +676,8 @@ void twin_premultiply_alpha(twin_pixmap_t *px) for (y = 0; y < px->height; y++) { p.b = px->p.b + y * px->stride; - for (x = 0; x < px->width; x++) { - twin_argb32_t v = p.argb32[x]; - twin_a8_t a = twin_get_8(v, 24); - - p.argb32[x] = (v & 0xff000000) | - twin_int_mult(twin_get_8(v, 16), a, t1) << 16 | - twin_int_mult(twin_get_8(v, 8), a, t2) << 8 | - twin_int_mult(twin_get_8(v, 0), a, t3); - } + for (x = 0; x < px->width; x++) + p.argb32[x] = _twin_apply_alpha(p.argb32[x]); } } |