From 7cc7af14b8016c74f05759cbbd0e3bc8e37302a5 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Fri, 14 Feb 2014 16:50:31 +0900 Subject: [PATCH] Evas filters: Fix alpha in displacement filter If the displacement map has some alpha values (not 0xFF), then the blending should take this alpha into account. This part is fine. BUT, since Evas relies on premultiplied colors... we have a problem: R (dx) and G (dy) have already been scaled down. Actually we would need to load the map in non premultiplied RGBA, otherwise we'll lose precision on dx,dy as soon as A != 0xFF. Well... I guess this will be a limitation of this filter, for now at least. Most displacement maps shouldn't even have any alpha anyways. --- src/lib/evas/filters/evas_filter_displace.c | 23 ++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/lib/evas/filters/evas_filter_displace.c b/src/lib/evas/filters/evas_filter_displace.c index 994cbe990a..362da634e9 100644 --- a/src/lib/evas/filters/evas_filter_displace.c +++ b/src/lib/evas/filters/evas_filter_displace.c @@ -77,20 +77,20 @@ _filter_displace_cpu_alpha_do(int w, int h, int map_w, int map_h, int intensity, static void _filter_displace_cpu_rgba_do(int w, int h, int map_w, int map_h, int intensity, - DATA32 *src, DATA32 *dst, DATA8 *map_start, + DATA32 *src, DATA32 *dst, DATA32 *map_start, Eina_Bool stretch, Eina_Bool smooth, Eina_Bool blend) { int x, y, map_x, map_y; - const int map_stride = sizeof(DATA32) * map_w; const int dx = RED; const int dy = GREEN; + Eina_Bool unpremul = EINA_FALSE; DATA8 *map; for (y = 0, map_y = 0; y < h; y++, map_y++) { if (map_y >= map_h) map_y = 0; - map = map_start + (map_y * map_stride); + map = (DATA8 *) (map_start + map_y * map_w); for (x = 0, map_x = 0; x < w; x++, dst++, src++, map_x++) { @@ -102,10 +102,17 @@ _filter_displace_cpu_rgba_do(int w, int h, int map_w, int map_h, int intensity, if (map_x >= map_w) { map_x = 0; - map = map_start + (map_y * map_stride); + map = (DATA8 *) (map_start + map_y * map_w); } else map += sizeof(DATA32); + if (!map[ALPHA]) continue; + if (!unpremul && map[ALPHA] != 0xFF) + { + unpremul = EINA_TRUE; + evas_data_argb_unpremul(map_start, map_w * map_h); + } + // x val = ((int) map[dx] - 128) * intensity; offx = val >> 7; @@ -173,6 +180,9 @@ _filter_displace_cpu_rgba_do(int w, int h, int map_w, int map_h, int intensity, *dst = col; } } + + if (unpremul) + evas_data_argb_premul(map_start, map_w * map_h); } /** @@ -226,8 +236,7 @@ static Eina_Bool _filter_displace_cpu_rgba(Evas_Filter_Command *cmd) { int w, h, map_w, map_h, intensity; - DATA32 *dst, *src; - DATA8 *map_start; + DATA32 *dst, *src, *map_start; Eina_Bool stretch, smooth, blend; w = cmd->input->w; @@ -239,7 +248,7 @@ _filter_displace_cpu_rgba(Evas_Filter_Command *cmd) EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output->backing, EINA_FALSE); src = ((RGBA_Image *) cmd->input->backing)->image.data; - map_start = ((RGBA_Image *) cmd->mask->backing)->mask.data; + map_start = ((RGBA_Image *) cmd->mask->backing)->image.data; dst = ((RGBA_Image *) cmd->output->backing)->image.data; EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(map_start, EINA_FALSE);