Mercurial > MadButterfly
changeset 1106:b5145de15ace
Fix issue of alpha channel not working.
Cairo is referene design of our graphic engine. It always trade an
image as pre-multiplied, but imlib2 is not. It causes no opacity
effects for the images loaded with imlib2. It is fixed by
pre-multipling images loaded by imlib2.
author | Thinker K.F. Li <thinker@codemud.net> |
---|---|
date | Mon, 06 Dec 2010 01:05:32 +0800 |
parents | 1b3e295f3acb |
children | 1c64a9cec2f2 |
files | src/img_ldr_imlib2.c |
diffstat | 1 files changed, 43 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- a/src/img_ldr_imlib2.c Sun Dec 05 21:04:12 2010 +0800 +++ b/src/img_ldr_imlib2.c Mon Dec 06 01:05:32 2010 +0800 @@ -1,6 +1,7 @@ // -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- // vim: sw=4:ts=8:sts=4 #include <stdio.h> +#include <stdint.h> #include <string.h> #include <Imlib2.h> #include "mb_graph_engine.h" @@ -19,7 +20,6 @@ struct _simple_mb_img_data { mb_img_data_t img; - Imlib_Image img_hdl; }; typedef struct _simple_mb_img_data simple_mb_img_data_t; @@ -31,7 +31,11 @@ simple_mb_img_data_t *img; Imlib_Image img_hdl; int w, h; - void *data; + int i, j, pos; + uint32_t alpha; + uint32_t value; + uint32_t *data; + uint32_t *premultiple_data; char *fname; int sz; @@ -50,21 +54,54 @@ imlib_context_set_image(img_hdl); w = imlib_image_get_width(); h = imlib_image_get_height(); - data = imlib_image_get_data_for_reading_only(); + data = (uint32_t *)imlib_image_get_data_for_reading_only(); img = O_ALLOC(simple_mb_img_data_t); if(img == NULL) { imlib_free_image(); return NULL; } - img->img.content = data; + + premultiple_data = (uint32_t *)malloc(4 * w * h); + if(premultiple_data == NULL) { + free(img); + imlib_free_image(); + return NULL; + } + memcpy(premultiple_data, data, 4 * w * h); + + /* Pre-multiply + * + * Our reference model is Cairo. In Cairo model, image is + * pre-multiplied with alpha, but imlib2 is not. So, we do it + * here. + */ + pos = 0; + for(i = 0; i < h; i++) { + for(j = 0; j < w; j++) { + value = data[pos]; + alpha = value >> 24; + if(alpha == 0) + value = 0; + else if(alpha != 0xff) { + value = (value & 0xff000000) | + (((value & 0xff0000) * alpha / 0xff) & 0xff0000) | + (((value & 0xff00) * alpha / 0xff) & 0xff00) | + ((value & 0xff) * alpha / 0xff); + } + premultiple_data[pos++] = value; + } + } + + img->img.content = premultiple_data; img->img.w = w; img->img.h = h; img->img.stride = w * 4; img->img.fmt = MB_IFMT_ARGB32; img->img.free = simple_mb_img_ldr_img_free; - img->img_hdl = img_hdl; + imlib_free_image(); + return (mb_img_data_t *)img; } @@ -72,8 +109,7 @@ void simple_mb_img_ldr_img_free(mb_img_data_t *img) { simple_mb_img_data_t *simg = (simple_mb_img_data_t *)img; - imlib_context_set_image(simg->img_hdl); - imlib_free_image(); + free(simg->img.content); free(img); }