1 /* Utility functions for the filters. */
2
3 #include "evas_filter_private.h"
4
5 Evas_Filter_Buffer *
evas_filter_buffer_scaled_get(Evas_Filter_Context * ctx,Evas_Filter_Buffer * src,unsigned w,unsigned h)6 evas_filter_buffer_scaled_get(Evas_Filter_Context *ctx,
7 Evas_Filter_Buffer *src,
8 unsigned w, unsigned h)
9 {
10 unsigned int src_len = 0, src_stride, dst_len = 0, dst_stride;
11 uint8_t *src_map = NULL, *dst_map = NULL;
12 Evas_Filter_Buffer *dst;
13 RGBA_Image dstim, srcim;
14 RGBA_Draw_Context dc;
15 Eina_Bool ok;
16
17 DBG("Scaling buffer from %dx%d to %dx%d, this is a slow operation!",
18 src->w, src->h, w, h);
19 DEBUG_TIME_BEGIN();
20
21 // Get destination buffer
22 dst = evas_filter_temporary_buffer_get(ctx, w, h, src->alpha_only, 0);
23 EINA_SAFETY_ON_NULL_RETURN_VAL(dst, NULL);
24
25 // Map input and output
26 src_map = _buffer_map_all(src->buffer, &src_len, E_READ, E_ARGB, &src_stride);
27 dst_map = _buffer_map_all(dst->buffer, &dst_len, E_WRITE, E_ARGB, &dst_stride);
28 EINA_SAFETY_ON_FALSE_GOTO(src_map && dst_map, end);
29 EINA_SAFETY_ON_FALSE_GOTO((src_stride == ((unsigned) src->w * 4)) &&
30 (dst_stride == (w * 4)), end);
31
32 // Wrap as basic RGBA_Images
33 memset(&dstim, 0, sizeof(dstim));
34 dstim.cache_entry.w = w;
35 dstim.cache_entry.h = h;
36 dstim.cache_entry.flags.alpha = 1;
37 dstim.cache_entry.flags.alpha_sparse = 0;
38 dstim.cache_entry.space = EVAS_COLORSPACE_ARGB8888;
39 dstim.image.data8 = dst_map;
40
41 memset(&srcim, 0, sizeof(srcim));
42 srcim.cache_entry.w = src->w;
43 srcim.cache_entry.h = src->h;
44 srcim.cache_entry.flags.alpha = 1;
45 srcim.cache_entry.flags.alpha_sparse = 0;
46 srcim.cache_entry.space = EVAS_COLORSPACE_ARGB8888;
47 srcim.image.data8 = src_map;
48
49 // Basic draw context
50 memset(&dc, 0, sizeof(dc));
51 dc.render_op = EVAS_RENDER_COPY;
52
53 // Do the scale
54 ok = evas_common_scale_rgba_in_to_out_clip_smooth
55 (&srcim, &dstim, &dc, 0, 0, src->w, src->h, 0, 0, w, h);
56
57 if (!ok)
58 {
59 ERR("RGBA Image scaling failed.");
60 dst = NULL;
61 }
62
63 end:
64 if (src_map) ector_buffer_unmap(src->buffer, src_map, src_len);
65 if ((dst) && (dst_map))
66 ector_buffer_unmap(dst->buffer, dst_map, dst_len);
67 DEBUG_TIME_END();
68 return dst;
69 }
70
71 static Eina_Bool
_interpolate_none(DATA8 * output,int * points)72 _interpolate_none(DATA8 *output, int *points)
73 {
74 DATA8 val = 0;
75 int j;
76 for (j = 0; j < 256; j++)
77 {
78 if (points[j] == -1)
79 output[j] = val;
80 else
81 val = output[j] = (DATA8) points[j];
82 }
83 return EINA_TRUE;
84 }
85
86 static Eina_Bool
_interpolate_linear(DATA8 * output,int * points)87 _interpolate_linear(DATA8 *output, int *points)
88 {
89 DATA8 val = 0;
90 int j, k, last_idx = 0;
91 for (j = 0; j < 256; j++)
92 {
93 if (points[j] != -1)
94 {
95 output[j] = (DATA8) points[j];
96 for (k = last_idx + 1; k < j; k++)
97 output[k] = (DATA8) (points[j] + ((k - last_idx) * (points[j] - points[last_idx]) / (j - last_idx)));
98 last_idx = j;
99 }
100 }
101 val = (DATA8) points[last_idx];
102 for (j = last_idx + 1; j < 256; j++)
103 output[j] = val;
104 return EINA_TRUE;
105 }
106
107 Eina_Bool
evas_filter_interpolate(DATA8 * output,int * points,Evas_Filter_Interpolation_Mode mode)108 evas_filter_interpolate(DATA8 *output, int *points,
109 Evas_Filter_Interpolation_Mode mode)
110 {
111 switch (mode)
112 {
113 case EVAS_FILTER_INTERPOLATION_MODE_NONE:
114 return _interpolate_none(output, points);
115 case EVAS_FILTER_INTERPOLATION_MODE_LINEAR:
116 default:
117 return _interpolate_linear(output, points);
118 }
119 }
120
121 int
evas_filter_smallest_pow2_larger_than(int val)122 evas_filter_smallest_pow2_larger_than(int val)
123 {
124 int n;
125
126 for (n = 0; n < 32; n++)
127 if (val <= (1 << n)) return n;
128
129 ERR("Value %d is too damn high!", val);
130 return 32;
131 }
132