1 // haip.c
2 // weed plugin
3 // (c) G. Finch (salsaman) 2006 - 2012
4 //
5 // released under the GNU GPL 3 or later
6 // see file COPYING or www.gnu.org for details
7
8 ///////////////////////////////////////////////////////////////////
9
10 static int package_version = 1; // version of this package
11
12 //////////////////////////////////////////////////////////////////
13
14 #define NEED_PALETTE_CONVERSIONS
15 #define NEED_RANDOM
16
17 #ifndef NEED_LOCAL_WEED_PLUGIN
18 #include <weed/weed-plugin.h>
19 #include <weed/weed-utils.h> // optional
20 #include <weed/weed-plugin-utils.h> // optional
21 #else
22 #include "../../libweed/weed-plugin.h"
23 #include "../../libweed/weed-utils.h" // optional
24 #include "../../libweed/weed-plugin-utils.h" // optional
25 #endif
26
27 #include "weed-plugin-utils.c" // optional
28
29 /////////////////////////////////////////////////////////////
30
31 typedef struct {
32 int x;
33 int y;
34 int *px;
35 int *py;
36 int *wt;
37 uint64_t fastrand_val;
38 int old_width;
39 int old_height;
40 } _sdata;
41
42 static int ress[8];
43
haip_init(weed_plant_t * inst)44 static weed_error_t haip_init(weed_plant_t *inst) {
45 _sdata *sdata = weed_malloc(sizeof(_sdata));
46 if (sdata == NULL) return WEED_ERROR_MEMORY_ALLOCATION;
47 else {
48 weed_plant_t **in_params = weed_get_in_params(inst, NULL);
49 int num_wurms = weed_param_get_value_int(in_params[0]);
50 weed_free(in_params);
51
52 sdata->x = sdata->y = -1;
53
54 weed_set_voidptr_value(inst, "plugin_internal", sdata);
55
56 sdata->px = weed_malloc(num_wurms * sizeof(int));
57 sdata->py = weed_malloc(num_wurms * sizeof(int));
58 sdata->wt = weed_malloc(num_wurms * sizeof(int));
59
60 for (int i = 0; i < num_wurms; i++) {
61 sdata->px[i] = sdata->py[i] = -1;
62 }
63
64 sdata->old_width = sdata->old_height = -1;
65 sdata->fastrand_val = fastrand(0);
66 return WEED_SUCCESS;
67 }
68 }
69
70
haip_deinit(weed_plant_t * inst)71 static weed_error_t haip_deinit(weed_plant_t *inst) {
72 _sdata *sdata = weed_get_voidptr_value(inst, "plugin_internal", NULL);
73 if (sdata) {
74 if (sdata->wt) weed_free(sdata->wt);
75 if (sdata->px) weed_free(sdata->px);
76 if (sdata->py) weed_free(sdata->py);
77 weed_free(sdata);
78 weed_set_voidptr_value(inst, "plugin_internal", NULL);
79 }
80 return WEED_SUCCESS;
81 }
82
83
make_eight_table(unsigned char * pt,int row,int luma,int adj,int pal)84 static int make_eight_table(unsigned char *pt, int row, int luma, int adj, int pal) {
85 int n = 0;
86 for (n = 0; n < 8; n++) ress[n] = -1;
87 n = 0;
88 if (calc_luma(&pt[-row - 3], pal, 0) >= (luma - adj)) {
89 ress[n] = 0;
90 n++;
91 }
92 if (calc_luma(&pt[-row], pal, 0) >= (luma - adj)) {
93 ress[n] = 1;
94 n++;
95 }
96 if (calc_luma(&pt[-row + 3], pal, 0) >= (luma - adj)) {
97 ress[n] = 2;
98 n++;
99 }
100 if (calc_luma(&pt[-3], pal, 0) >= (luma - adj)) {
101 ress[n] = 3;
102 n++;
103 }
104 if (calc_luma(&pt[3], pal, 0) >= (luma - adj)) {
105 ress[n] = 4;
106 n++;
107 }
108 if (calc_luma(&pt[row - 3], pal, 0) >= (luma - adj)) {
109 ress[n] = 5;
110 n++;
111 }
112 if (calc_luma(&pt[row], pal, 0) >= (luma - adj)) {
113 ress[n] = 6;
114 n++;
115 }
116 if (calc_luma(&pt[row + 3], pal, 0) >= (luma - adj)) {
117 ress[n] = 7;
118 n++;
119 }
120 return n;
121 }
122
123
select_dir(_sdata * sdata)124 static int select_dir(_sdata *sdata) {
125 int num_choices = 1;
126 int i;
127 int mychoice;
128 float fval;
129
130 for (i = 0; i < 8; i++) {
131 if (ress[i] != -1) num_choices++;
132 }
133
134 if (num_choices == 0) return 1;
135 sdata->fastrand_val = fastrand(sdata->fastrand_val);
136 fval = (float)((sdata->fastrand_val >> 16) & 0XFFFF) / 65535.;
137 mychoice = (int)(fval * (float)(num_choices));
138
139 switch (ress[mychoice]) {
140 case 0:
141 sdata->x--;
142 sdata->y--;
143 break;
144 case 1:
145 sdata->y--;
146 break;
147 case 2:
148 sdata->x++;
149 sdata->y--;
150 break;
151 case 3:
152 sdata->x--;
153 break;
154 case 4:
155 sdata->x++;
156 break;
157 case 5:
158 sdata->x--;
159 sdata->y++;
160 break;
161 case 6:
162 sdata->y++;
163 break;
164 case 7:
165 sdata->x++;
166 sdata->y++;
167 break;
168 }
169 return 0;
170 }
171
172
nine_fill(unsigned char * new_data,int row,unsigned char o0,unsigned char o1,unsigned char o2)173 static inline void nine_fill(unsigned char *new_data, int row, unsigned char o0, unsigned char o1, unsigned char o2) {
174 // fill nine pixels with the centre colour
175 new_data[-row - 3] = new_data[-row] = new_data[-row + 3] = new_data[-3] = new_data[0] =
176 new_data[3] = new_data[row - 3] = new_data[row] = new_data[row + 3] = o0;
177 new_data[-row - 2] = new_data[-row + 1] = new_data[-row + 4] = new_data[-2] = new_data[1] =
178 new_data[4] = new_data[row - 2] = new_data[row + 1] = new_data[row + 4] = o1;
179 new_data[-row - 1] = new_data[-row + 2] = new_data[-row + 5] = new_data[-1] = new_data[2] =
180 new_data[5] = new_data[row - 1] = new_data[row + 2] = new_data[row + 5] = o2;
181 }
182
183
black_fill(unsigned char * new_data,int row)184 static inline void black_fill(unsigned char *new_data, int row) {
185 // fill nine pixels with black
186 nine_fill(new_data, row, 0, 0, 0);
187 }
188
189
white_fill(unsigned char * new_data,int row)190 static inline void white_fill(unsigned char *new_data, int row) {
191 // fill nine pixels with white
192 nine_fill(new_data, row, 255, 255, 255);
193 }
194
195
proc_pt(unsigned char * dest,unsigned char * src,int x,int y,int orows,int irows,int wt)196 static void proc_pt(unsigned char *dest, unsigned char *src, int x, int y, int orows,
197 int irows, int wt) {
198 size_t offs;
199 switch (wt) {
200 case 0:
201 black_fill(&dest[orows * y + x * 3], orows);
202 break;
203 case 1:
204 white_fill(&dest[orows * y + x * 3], orows);
205 break;
206 case 2:
207 offs = irows * y + x * 3;
208 nine_fill(&dest[orows * y + x * 3], orows, src[offs], src[offs + 1], src[offs + 2]);
209 break;
210 }
211 }
212
213
haip_process(weed_plant_t * inst,weed_timecode_t timestamp)214 static weed_error_t haip_process(weed_plant_t *inst, weed_timecode_t timestamp) {
215 _sdata *sdata;
216
217 weed_plant_t *in_channel = weed_get_in_channel(inst, 0),
218 *out_channel = weed_get_out_channel(inst, 0);
219
220 unsigned char *src = weed_channel_get_pixel_data(in_channel);
221 unsigned char *dst = weed_channel_get_pixel_data(out_channel);
222 weed_plant_t **in_params = weed_get_in_params(inst, NULL);
223 int num_wurms = weed_param_get_value_int(in_params[0]);
224 unsigned char *pt;
225
226 int width = weed_channel_get_width(in_channel), width3 = width * 3;
227 int height = weed_channel_get_height(in_channel);
228 int irowstride = weed_channel_get_stride(in_channel);
229 int orowstride = weed_channel_get_stride(out_channel);
230 int palette = weed_channel_get_palette(in_channel);
231
232 int count;
233 int luma, adj;
234
235 uint64_t fastrand_val;
236 float scalex, scaley;
237
238 register int i;
239
240 weed_free(in_params);
241
242 sdata = weed_get_voidptr_value(inst, "plugin_internal", NULL);
243 sdata->fastrand_val = fastrand_val = fastrand(0);
244
245 for (i = 0; i < height; i++) {
246 weed_memcpy(&dst[i * orowstride], &src[i * irowstride], width3);
247 }
248
249 if (sdata->old_width == -1) {
250 sdata->old_width = width;
251 sdata->old_height = height;
252 }
253
254 scalex = (float)width / (float)sdata->old_width;
255 scaley = (float)height / (float)sdata->old_height;
256
257 for (i = 0; i < num_wurms; i++) {
258 count = 1000;
259 if (sdata->px[i] == -1) {
260 sdata->fastrand_val = fastrand(sdata->fastrand_val);
261 sdata->px[i] = (int)(((sdata->fastrand_val & 0xFF) / 255.*(width - 2))) + 1;
262 sdata->fastrand_val = fastrand(sdata->fastrand_val);
263 sdata->py[i] = (int)(((sdata->fastrand_val & 0xFF) / 255.*(height - 2))) + 1;
264 sdata->fastrand_val = fastrand(sdata->fastrand_val);
265 sdata->wt[i] = (int)(((sdata->fastrand_val & 0xFF) / 255.*2));
266 }
267
268 sdata->x = (float)sdata->px[i] * scalex;
269 sdata->y = (float)sdata->py[i] * scaley;
270
271 while (count > 0) {
272 if (sdata->x < 1) sdata->x++;
273 if (sdata->x > width - 2) sdata->x = width - 2;
274 if (sdata->y < 1) sdata->y++;
275 if (sdata->y > height - 2) sdata->y = height - 2;
276
277 proc_pt(dst, src, sdata->x, sdata->y, orowstride, irowstride, sdata->wt[i]);
278
279 if (sdata->x < 1) sdata->x++;
280 if (sdata->x > width - 2) sdata->x = width - 2;
281 if (sdata->y < 1) sdata->y++;
282 if (sdata->y > height - 2) sdata->y = height - 2;
283 pt = &src[sdata->y * irowstride + sdata->x * 3];
284
285 luma = calc_luma(pt, palette, 0);
286 adj = 0;
287
288 make_eight_table(pt, irowstride, luma, adj, palette);
289 if (((count << 7) >> 7) == count) select_dir(sdata);
290 count--;
291 }
292 sdata->px[i] = sdata->x;
293 sdata->py[i] = sdata->y;
294 }
295
296 sdata->old_width = width;
297 sdata->old_height = height;
298
299 return WEED_SUCCESS;
300 }
301
302
303 WEED_SETUP_START(200, 200) {
304 int palette_list[] = {WEED_PALETTE_RGB24, WEED_PALETTE_BGR24, WEED_PALETTE_END};
305 weed_plant_t *in_params[] = {weed_integer_init("nwurms", "Number of Wurms", 200, 1, 4092), NULL};
306 weed_plant_t *in_chantmpls[] = {weed_channel_template_init("in channel 0", 0), NULL};
307 weed_plant_t *out_chantmpls[] = {weed_channel_template_init("out channel 0", 0), NULL};
308 weed_plant_t *filter_class = weed_filter_class_init("haip", "salsaman", 1, 0, palette_list,
309 haip_init, haip_process, haip_deinit,
310 in_chantmpls, out_chantmpls, in_params, NULL);
311 weed_paramtmpl_set_flags(in_params[0], WEED_PARAMETER_REINIT_ON_VALUE_CHANGE);
312 weed_plugin_info_add_filter_class(plugin_info, filter_class);
313 weed_set_int_value(plugin_info, WEED_LEAF_VERSION, package_version);
314 }
315 WEED_SETUP_END;
316