forked from enlightenment/efl
Evas filters: Implement color curves filter
Color curves are a very simple tool to alter the colors of an image, on a per-pixel basis. This implementation will simply map each pixel to a 256 bytes buffer, provided by the application. NOTE: There are no convenience functions yet for easy curve generation, but this is the plan (give point A, B, B and interpolate between them to generate the 256 values array).
This commit is contained in:
parent
84caa5902e
commit
6458df7a65
|
@ -0,0 +1,125 @@
|
|||
#include "evas_filter.h"
|
||||
#include "evas_filter_private.h"
|
||||
|
||||
|
||||
static Eina_Bool
|
||||
_filter_curve_cpu_rgba(Evas_Filter_Command *cmd)
|
||||
{
|
||||
RGBA_Image *in, *out;
|
||||
DATA32 *src, *dst, *d, *s;
|
||||
DATA8 *curve;
|
||||
int k, offset = -1, len;
|
||||
|
||||
#define C_VAL(p) (((DATA8 *)(p))[offset])
|
||||
|
||||
in = cmd->input->backing;
|
||||
out = cmd->output->backing;
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(in, EINA_FALSE);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(out, EINA_FALSE);
|
||||
src = in->image.data;
|
||||
dst = out->image.data;
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(dst, EINA_FALSE);
|
||||
curve = cmd->curve.data;
|
||||
len = in->cache_entry.w * in->cache_entry.h;
|
||||
|
||||
switch (cmd->curve.channel)
|
||||
{
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
case EVAS_FILTER_CHANNEL_RED: offset = 2; break;
|
||||
case EVAS_FILTER_CHANNEL_GREEN: offset = 1; break;
|
||||
case EVAS_FILTER_CHANNEL_BLUE: offset = 0; break;
|
||||
#else
|
||||
case EVAS_FILTER_CHANNEL_RED: offset = 1; break;
|
||||
case EVAS_FILTER_CHANNEL_GREEN: offset = 2; break;
|
||||
case EVAS_FILTER_CHANNEL_BLUE: offset = 3; break;
|
||||
#endif
|
||||
case EVAS_FILTER_CHANNEL_ALPHA: break;
|
||||
case EVAS_FILTER_CHANNEL_RGB: break;
|
||||
default:
|
||||
ERR("Invalid color channel %d", (int) cmd->curve.channel);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
// One channel
|
||||
if (offset >= 0)
|
||||
{
|
||||
for (k = len; k; k--, dst++, src++)
|
||||
C_VAL(dst) = curve[C_VAL(src)];
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
// RGB
|
||||
if (cmd->curve.channel == EVAS_FILTER_CHANNEL_RGB)
|
||||
{
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
for (offset = 0; offset <= 2; offset++)
|
||||
#else
|
||||
for (offset = 1; offset <= 3; offset++)
|
||||
#endif
|
||||
{
|
||||
for (k = len, s = src, d = dst; k; k--, d++, s++)
|
||||
C_VAL(d) = curve[C_VAL(s)];
|
||||
}
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
// Alpha
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
offset = 3;
|
||||
#else
|
||||
offset = 0;
|
||||
#endif
|
||||
|
||||
if (src != dst)
|
||||
memcpy(dst, src, len * sizeof(DATA32));
|
||||
evas_data_argb_unpremul(dst, len);
|
||||
for (k = len, d = dst; k; k--, d++, src++)
|
||||
C_VAL(d) = curve[C_VAL(src)];
|
||||
evas_data_argb_premul(dst, len);
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_filter_curve_cpu_alpha(Evas_Filter_Command *cmd)
|
||||
{
|
||||
RGBA_Image *in, *out;
|
||||
DATA8 *src, *dst;
|
||||
DATA8 *curve;
|
||||
int k;
|
||||
|
||||
in = cmd->input->backing;
|
||||
out = cmd->output->backing;
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(in, EINA_FALSE);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(out, EINA_FALSE);
|
||||
src = in->mask.data;
|
||||
dst = out->mask.data;
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(src, EINA_FALSE);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(dst, EINA_FALSE);
|
||||
curve = cmd->curve.data;
|
||||
|
||||
for (k = in->cache_entry.w * in->cache_entry.h; k; k--)
|
||||
*dst++ = curve[*src++];
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
Evas_Filter_Apply_Func
|
||||
evas_filter_curve_cpu_func_get(Evas_Filter_Command *cmd)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, NULL);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output, NULL);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input, NULL);
|
||||
EINA_SAFETY_ON_FALSE_RETURN_VAL((cmd->input->w == cmd->output->w)
|
||||
&& (cmd->input->h == cmd->output->h), 0);
|
||||
|
||||
if (!cmd->input->alpha_only && !cmd->output->alpha_only)
|
||||
return _filter_curve_cpu_rgba;
|
||||
|
||||
if (cmd->input->alpha_only && cmd->output->alpha_only)
|
||||
return _filter_curve_cpu_alpha;
|
||||
|
||||
CRIT("Incompatible image formats");
|
||||
return NULL;
|
||||
}
|
Loading…
Reference in New Issue