efl/src/lib/evas/filters/evas_filter_utils.c

141 lines
3.7 KiB
C

/* Utility functions for the filters. */
#include "evas_filter_private.h"
Evas_Filter_Buffer *
evas_filter_buffer_scaled_get(Evas_Filter_Context *ctx,
Evas_Filter_Buffer *src,
unsigned w, unsigned h)
{
unsigned int src_len = 0, src_stride, dst_len = 0, dst_stride;
uint8_t *src_map = NULL, *dst_map = NULL;
Evas_Filter_Buffer *dst;
RGBA_Image dstim, srcim;
RGBA_Draw_Context dc;
Eina_Bool ok;
DBG("Scaling buffer from %dx%d to %dx%d, this is a slow operation!",
src->w, src->h, w, h);
DEBUG_TIME_BEGIN();
// Get destination buffer
dst = evas_filter_temporary_buffer_get(ctx, w, h, src->alpha_only, 0);
EINA_SAFETY_ON_NULL_RETURN_VAL(dst, NULL);
// Map input and output
src_map = _buffer_map_all(src->buffer, &src_len, E_READ, E_ARGB, &src_stride);
dst_map = _buffer_map_all(dst->buffer, &dst_len, E_WRITE, E_ARGB, &dst_stride);
EINA_SAFETY_ON_FALSE_GOTO(src_map && dst_map, end);
EINA_SAFETY_ON_FALSE_GOTO((src_stride == ((unsigned) src->w * 4)) &&
(dst_stride == (w * 4)), end);
// Wrap as basic RGBA_Images
memset(&dstim, 0, sizeof(dstim));
dstim.cache_entry.w = w;
dstim.cache_entry.h = h;
dstim.cache_entry.flags.alpha = 1;
dstim.cache_entry.flags.alpha_sparse = 0;
dstim.cache_entry.space = EVAS_COLORSPACE_ARGB8888;
dstim.image.data8 = dst_map;
memset(&srcim, 0, sizeof(srcim));
srcim.cache_entry.w = src->w;
srcim.cache_entry.h = src->h;
srcim.cache_entry.flags.alpha = 1;
srcim.cache_entry.flags.alpha_sparse = 0;
srcim.cache_entry.space = EVAS_COLORSPACE_ARGB8888;
srcim.image.data8 = src_map;
// Basic draw context
memset(&dc, 0, sizeof(dc));
dc.render_op = EVAS_RENDER_COPY;
// Do the scale
ok = evas_common_scale_rgba_in_to_out_clip_smooth
(&srcim, &dstim, &dc, 0, 0, src->w, src->h, 0, 0, w, h);
if (!ok)
{
ERR("RGBA Image scaling failed.");
dst = NULL;
}
end:
if (src_map) ector_buffer_unmap(src->buffer, src_map, src_len);
if ((dst) && (dst_map))
ector_buffer_unmap(dst->buffer, dst_map, dst_len);
DEBUG_TIME_END();
return dst;
}
static Eina_Bool
_interpolate_none(DATA8 *output, int *points)
{
DATA8 val = 0;
int j;
for (j = 0; j < 256; j++)
{
if (points[j] == -1)
output[j] = val;
else
val = output[j] = (DATA8) points[j];
}
return EINA_TRUE;
}
static Eina_Bool
_interpolate_linear(DATA8 *output, int *points)
{
DATA8 val = 0;
int j, k, last_idx = 0;
for (j = 0; j < 256; j++)
{
if (points[j] != -1)
{
int val1, val2, vald, pos, len;
output[j] = (DATA8) points[j];
val1 = points[last_idx];
val2 = points[j];
vald = val2 - val1;
len = j - last_idx;
for (k = last_idx + 1; k < j; k++)
{
pos = k - last_idx;
output[k] = (DATA8) (val1 + ((pos * vald) / len));
}
last_idx = j;
}
}
val = (DATA8) points[last_idx];
for (j = last_idx + 1; j < 256; j++)
output[j] = val;
return EINA_TRUE;
}
Eina_Bool
evas_filter_interpolate(DATA8 *output, int *points,
Evas_Filter_Interpolation_Mode mode)
{
switch (mode)
{
case EVAS_FILTER_INTERPOLATION_MODE_NONE:
return _interpolate_none(output, points);
case EVAS_FILTER_INTERPOLATION_MODE_LINEAR:
default:
return _interpolate_linear(output, points);
}
}
int
evas_filter_smallest_pow2_larger_than(int val)
{
int n;
for (n = 0; n < 32; n++)
if (val <= (1 << n)) return n;
ERR("Value %d is too damn high!", val);
return 32;
}