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.
This commit is contained in:
Jean-Philippe Andre 2014-02-14 16:50:31 +09:00
parent 9472e03546
commit 7cc7af14b8
1 changed files with 16 additions and 7 deletions

View File

@ -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);