aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeoff Levand <geoff@infradead.org>2011-11-25 17:16:30 -0800
committerGeoff Levand <geoff@infradead.org>2011-12-11 15:06:22 -0800
commitea951fb17d38c06d5db4920ef5f2d6e014667c2c (patch)
tree91a0492ca8a72c32c7d2b6eac1aa9ab9817f7695
parent33093a0dff8b8ffceb68f424bcd18cc7eae760a3 (diff)
downloadlibtwin-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.c36
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]);
}
}