2014-02-12 00:52:01 -08:00
|
|
|
/* Utility functions for the filters. */
|
2014-01-01 19:43:44 -08:00
|
|
|
|
|
|
|
#include "evas_filter_private.h"
|
|
|
|
|
|
|
|
Evas_Filter_Buffer *
|
|
|
|
evas_filter_buffer_scaled_get(Evas_Filter_Context *ctx,
|
|
|
|
Evas_Filter_Buffer *src,
|
2014-01-22 23:54:50 -08:00
|
|
|
unsigned w, unsigned h)
|
2014-01-01 19:43:44 -08:00
|
|
|
{
|
2016-01-04 04:46:56 -08:00
|
|
|
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;
|
2015-12-08 17:45:53 -08:00
|
|
|
RGBA_Draw_Context dc;
|
|
|
|
Eina_Bool ok;
|
2014-01-01 19:43:44 -08:00
|
|
|
|
2016-01-04 04:46:56 -08:00
|
|
|
DBG("Scaling buffer from %dx%d to %dx%d, this is a slow operation!",
|
|
|
|
src->w, src->h, w, h);
|
|
|
|
DEBUG_TIME_BEGIN();
|
2014-01-01 19:43:44 -08:00
|
|
|
|
2016-01-04 04:46:56 -08:00
|
|
|
// Get destination buffer
|
2017-01-23 00:55:17 -08:00
|
|
|
dst = evas_filter_temporary_buffer_get(ctx, w, h, src->alpha_only, 0);
|
2016-01-04 04:46:56 -08:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(dst, NULL);
|
2014-03-06 01:28:46 -08:00
|
|
|
|
2016-01-04 04:46:56 -08:00
|
|
|
// 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);
|
2014-01-01 19:43:44 -08:00
|
|
|
|
2016-01-04 04:46:56 -08:00
|
|
|
// 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;
|
2014-01-22 21:58:05 -08:00
|
|
|
|
2016-01-04 04:46:56 -08:00
|
|
|
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
|
2015-12-08 17:45:53 -08:00
|
|
|
memset(&dc, 0, sizeof(dc));
|
|
|
|
dc.render_op = EVAS_RENDER_COPY;
|
2014-01-01 19:43:44 -08:00
|
|
|
|
2016-01-04 04:46:56 -08:00
|
|
|
// Do the scale
|
2015-12-08 17:45:53 -08:00
|
|
|
ok = evas_common_scale_rgba_in_to_out_clip_smooth
|
2016-01-04 04:46:56 -08:00
|
|
|
(&srcim, &dstim, &dc, 0, 0, src->w, src->h, 0, 0, w, h);
|
2014-03-06 01:28:46 -08:00
|
|
|
|
2015-12-08 17:45:53 -08:00
|
|
|
if (!ok)
|
2014-01-01 19:43:44 -08:00
|
|
|
{
|
2015-12-08 17:45:53 -08:00
|
|
|
ERR("RGBA Image scaling failed.");
|
2016-01-04 04:46:56 -08:00
|
|
|
dst = NULL;
|
2014-01-01 19:43:44 -08:00
|
|
|
}
|
|
|
|
|
2016-01-04 04:46:56 -08:00
|
|
|
end:
|
2016-03-01 10:06:28 -08:00
|
|
|
if (src_map) ector_buffer_unmap(src->buffer, src_map, src_len);
|
2016-01-27 09:05:59 -08:00
|
|
|
if ((dst) && (dst_map))
|
2016-03-01 10:06:28 -08:00
|
|
|
ector_buffer_unmap(dst->buffer, dst_map, dst_len);
|
2016-01-04 04:46:56 -08:00
|
|
|
DEBUG_TIME_END();
|
|
|
|
return dst;
|
2014-01-01 19:43:44 -08:00
|
|
|
}
|
2014-01-01 22:57:44 -08:00
|
|
|
|
|
|
|
static Eina_Bool
|
2015-05-27 22:37:10 -07:00
|
|
|
_interpolate_none(DATA8 *output, int *points)
|
2014-01-01 22:57:44 -08:00
|
|
|
{
|
2015-05-27 22:37:10 -07:00
|
|
|
DATA8 val = 0;
|
|
|
|
int j;
|
|
|
|
for (j = 0; j < 256; j++)
|
2014-01-01 22:57:44 -08:00
|
|
|
{
|
2015-05-27 22:37:10 -07:00
|
|
|
if (points[j] == -1)
|
|
|
|
output[j] = val;
|
2014-01-01 22:57:44 -08:00
|
|
|
else
|
2015-05-27 22:37:10 -07:00
|
|
|
val = output[j] = (DATA8) points[j];
|
2014-01-01 22:57:44 -08:00
|
|
|
}
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
2015-05-27 22:37:10 -07:00
|
|
|
_interpolate_linear(DATA8 *output, int *points)
|
2014-01-01 22:57:44 -08:00
|
|
|
{
|
2015-05-27 22:37:10 -07:00
|
|
|
DATA8 val = 0;
|
|
|
|
int j, k, last_idx = 0;
|
|
|
|
for (j = 0; j < 256; j++)
|
2014-01-01 22:57:44 -08:00
|
|
|
{
|
2015-05-27 22:37:10 -07:00
|
|
|
if (points[j] != -1)
|
2014-01-01 22:57:44 -08:00
|
|
|
{
|
2024-01-09 04:18:44 -08:00
|
|
|
int val1, val2, vald, pos, len;
|
|
|
|
|
2015-05-27 22:37:10 -07:00
|
|
|
output[j] = (DATA8) points[j];
|
2024-01-09 04:18:44 -08:00
|
|
|
val1 = points[last_idx];
|
|
|
|
val2 = points[j];
|
|
|
|
vald = val2 - val1;
|
|
|
|
len = j - last_idx;
|
2015-05-27 22:37:10 -07:00
|
|
|
for (k = last_idx + 1; k < j; k++)
|
2024-01-09 04:18:44 -08:00
|
|
|
{
|
|
|
|
pos = k - last_idx;
|
|
|
|
output[k] = (DATA8) (val1 + ((pos * vald) / len));
|
|
|
|
}
|
2015-05-27 22:37:10 -07:00
|
|
|
last_idx = j;
|
2014-01-01 22:57:44 -08:00
|
|
|
}
|
|
|
|
}
|
2015-05-27 22:37:10 -07:00
|
|
|
val = (DATA8) points[last_idx];
|
|
|
|
for (j = last_idx + 1; j < 256; j++)
|
|
|
|
output[j] = val;
|
2014-01-01 22:57:44 -08:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Eina_Bool
|
2015-05-27 22:37:10 -07:00
|
|
|
evas_filter_interpolate(DATA8 *output, int *points,
|
2014-01-01 22:57:44 -08:00
|
|
|
Evas_Filter_Interpolation_Mode mode)
|
|
|
|
{
|
|
|
|
switch (mode)
|
|
|
|
{
|
|
|
|
case EVAS_FILTER_INTERPOLATION_MODE_NONE:
|
2015-05-27 22:37:10 -07:00
|
|
|
return _interpolate_none(output, points);
|
2014-01-01 22:57:44 -08:00
|
|
|
case EVAS_FILTER_INTERPOLATION_MODE_LINEAR:
|
|
|
|
default:
|
2015-05-27 22:37:10 -07:00
|
|
|
return _interpolate_linear(output, points);
|
2014-01-01 22:57:44 -08:00
|
|
|
}
|
|
|
|
}
|
2014-03-11 00:18:41 -07:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|