File Coverage

regmach.c
Criterion Covered Total %
statement 167 214 78.0
branch 43 86 50.0
condition n/a
subroutine n/a
pod n/a
total 210 300 70.0


line stmt bran cond sub pod time code
1             #include "regmach.h"
2             #include
3             #include "imageri.h"
4              
5             /*#define DEBUG*/
6             #ifdef DEBUG
7             #define DBG(x) printf x
8             #else
9             #define DBG(x)
10             #endif
11              
12             static float MAX_EXP_ARG; /* = log(DBL_MAX); */
13              
14              
15             /* these functions currently assume RGB images - there seems to be some
16             support for other color spaces, but I can't tell how you find what
17             space an image is using.
18              
19             HSV conversions from pages 401-403 "Procedural Elements for Computer
20             Graphics", 1985, ISBN 0-07-053534-5. The algorithm presents to produce
21             an HSV color calculates all components at once - I don't, so I've
22             simiplified the algorithm to avoid unnecessary calculation (any errors
23             (of which I had a few ;) are mine).
24             */
25              
26             /* returns the value (brightness) of color from 0 to 1 */
27 1           static double hsv_value(i_color color) {
28 1           return i_max(i_max(color.rgb.r, color.rgb.g), color.rgb.b) / 255.0;
29             }
30              
31             /* returns the hue (color) of color from 0 to 360 */
32 1           static double hsv_hue(i_color color) {
33             int val;
34             int temp;
35 1           temp = i_min(i_min(color.rgb.r, color.rgb.g), color.rgb.b);
36 1           val = i_max(color.rgb.r, i_max(color.rgb.g, color.rgb.b));
37 1 50         if (val == 0 || val==temp) {
    50          
38 0           return 0;
39             }
40             else {
41 1           double cr = (val - color.rgb.r) / (double)(val - temp);
42 1           double cg = (val - color.rgb.g) / (double)(val - temp);
43 1           double cb = (val - color.rgb.b) / (double)(val - temp);
44             double hue;
45 1 50         if (color.rgb.r == val) {
46 1           hue = cb-cg;
47             }
48 0 0         else if (color.rgb.g == val) {
49 0           hue = 2.0 + cr-cb;
50             }
51             else { /* if (blue == val) */
52 0           hue = 4.0 + cg - cr;
53             }
54 1           hue *= 60.0; /* to degrees */
55 1 50         if (hue < 0)
56 0           hue += 360;
57              
58 1           return hue;
59             }
60             }
61              
62             /* return the saturation of color from 0 to 1 */
63 2           static double hsv_sat(i_color color) {
64 2           int value = i_max(i_max(color.rgb.r, color.rgb.g), color.rgb.b);
65 2 50         if (value == 0) {
66 0           return 0;
67             }
68             else {
69 2           int temp = i_min(i_min(color.rgb.r, color.rgb.g), color.rgb.b);
70 2           return (value - temp) / (double)value;
71             }
72             }
73              
74 90004           static i_color make_hsv(double hue, double sat, double val, int alpha) {
75             int i;
76             i_color c;
77 450020 100         for( i=0; i< MAXCHANNELS; i++) c.channel[i]=0;
78             DBG(("hsv=%f %f %f\n", hue, sat, val));
79 90004 100         if (sat <= 0) { /* handle -ve in case someone supplies a bad value */
80             /* should this be * 256? */
81 1           c.rgb.r = c.rgb.g = c.rgb.b = 255 * val;
82             }
83             else {
84             int i, m, n, k, v;
85             double f;
86            
87 90003 50         if (val < 0) val = 0;
88 90003 50         if (val > 1) val = 1;
89 90003 50         if (sat > 1) sat = 1;
90              
91             /* I want to handle -360 <= hue < 720 so that the caller can
92             fiddle with colour
93             */
94 90003 50         if (hue >= 360)
95 0           hue -= 360;
96 90003 100         else if (hue < 0)
97 501           hue += 360;
98 90003           hue /= 60;
99 90003           i = hue; /* floor */
100 90003           f = hue - i;
101 90003           val *= 255;
102 90003           m = val * (1.0 - sat);
103 90003           n = val * (1.0 - sat * f);
104 90003           k = val * (1.0 - sat * (1 - f));
105 90003           v = val;
106 90003           switch (i) {
107             case 0:
108 18075           c.rgb.r = v; c.rgb.g = k; c.rgb.b = m;
109 18075           break;
110             case 1:
111 18045           c.rgb.r = n; c.rgb.g = v; c.rgb.b = m;
112 18045           break;
113             case 2:
114 17912           c.rgb.r = m; c.rgb.g = v; c.rgb.b = k;
115 17912           break;
116             case 3:
117 17830           c.rgb.r = m; c.rgb.g = n; c.rgb.b = v;
118 17830           break;
119             case 4:
120 17743           c.rgb.r = k; c.rgb.g = m; c.rgb.b = v;
121 17743           break;
122             case 5:
123 398           c.rgb.r = v; c.rgb.g = m; c.rgb.b = n;
124 398           break;
125             }
126             }
127 90004           c.rgba.a = alpha;
128              
129 90004           return c;
130             }
131              
132 91080           static i_color make_rgb(int r, int g, int b, int a) {
133             i_color c;
134 91080 50         if (r < 0)
135 0           r = 0;
136 91080 50         if (r > 255)
137 0           r = 255;
138 91080           c.rgb.r = r;
139 91080 50         if (g < 0)
140 0           g = 0;
141 91080 50         if (g > 255)
142 0           g = 255;
143 91080           c.rgb.g = g;
144 91080 50         if (b < 0)
145 0           b = 0;
146 91080 50         if (b > 255)
147 0           b = 255;
148 91080           c.rgb.b = b;
149              
150 91080           c.rgba.a = a;
151              
152 91080           return c;
153             }
154              
155             /* greatly simplifies the code */
156             #define nout n_regs[codes->rout]
157             #define na n_regs[codes->ra]
158             #define nb n_regs[codes->rb]
159             #define nc n_regs[codes->rc]
160             #define nd n_regs[codes->rd]
161             #define cout c_regs[codes->rout]
162             #define ca c_regs[codes->ra]
163             #define cb c_regs[codes->rb]
164             #define cc c_regs[codes->rc]
165             #define cd c_regs[codes->rd]
166              
167             /* this is a pretty poor epsilon used for loosening up equality comparisons
168             It isn't currently used for inequalities
169             */
170              
171             #define n_epsilon(x, y) (fabs(x)+fabs(y))*0.001
172             static i_color bcol = {{ 0 }};
173              
174 181082           i_color i_rm_run(struct rm_op codes[], size_t code_count,
175             double n_regs[], size_t n_regs_count,
176             i_color c_regs[], size_t c_regs_count,
177             i_img *images[], size_t image_count) {
178             double dx, dy;
179 181082           struct rm_op *codes_base = codes;
180 181082           size_t count_base = code_count;
181              
182             DBG(("rm_run(%p, %d)\n", codes, code_count));
183 2076111 50         while (code_count) {
184             DBG((" rm_code %d\n", codes->code));
185 2076111           switch (codes->code) {
186             case rbc_add:
187 273566           nout = na + nb;
188 273566           break;
189            
190             case rbc_subtract:
191 212021           nout = na - nb;
192 212021           break;
193            
194             case rbc_mult:
195 600114           nout = na * nb;
196 600114           break;
197            
198             case rbc_div:
199 2500 50         if (fabs(nb) < 1e-10)
200 0           nout = 1e10;
201             else
202 2500           nout = na / nb;
203 2500           break;
204            
205             case rbc_mod:
206 149041 50         if (fabs(nb) > 1e-10) {
207 149041           nout = fmod(na, nb);
208             }
209             else {
210 0           nout = 0; /* close enough ;) */
211             }
212 149041           break;
213              
214             case rbc_pow:
215 2           nout = pow(na, nb);
216 2           break;
217              
218             case rbc_uminus:
219 1           nout = -na;
220 1           break;
221              
222             case rbc_multp:
223 59041           cout = make_rgb(ca.rgb.r * nb, ca.rgb.g * nb, ca.rgb.b * nb, 255);
224 59041           break;
225              
226             case rbc_addp:
227 29521           cout = make_rgb(ca.rgb.r + cb.rgb.r, ca.rgb.g + cb.rgb.g,
228 59042           ca.rgb.b + cb.rgb.b, 255);
229 29521           break;
230              
231             case rbc_subtractp:
232 1           cout = make_rgb(ca.rgb.r - cb.rgb.r, ca.rgb.g - cb.rgb.g,
233 2           ca.rgb.b - cb.rgb.b, 255);
234 1           break;
235              
236             case rbc_sin:
237 119521           nout = sin(na);
238 119521           break;
239              
240             case rbc_cos:
241 1           nout = cos(na);
242 1           break;
243              
244             case rbc_atan2:
245 90001           nout = atan2(na, nb);
246 90001           break;
247              
248             case rbc_sqrt:
249 1           nout = sqrt(na);
250 1           break;
251              
252             case rbc_distance:
253 90001           dx = na-nc;
254 90001           dy = nb-nd;
255 90001           nout = sqrt(dx*dx+dy*dy);
256 90001           break;
257              
258             case rbc_getp1:
259 88574           i_gpix(images[0], na, nb, c_regs+codes->rout);
260 88574 50         if (images[0]->channels < 4) cout.rgba.a = 255;
261 88574           break;
262              
263             case rbc_getp2:
264 29520           i_gpix(images[1], na, nb, c_regs+codes->rout);
265 29520 50         if (images[1]->channels < 4) cout.rgba.a = 255;
266 29520           break;
267              
268             case rbc_getp3:
269 0           i_gpix(images[2], na, nb, c_regs+codes->rout);
270 0 0         if (images[2]->channels < 4) cout.rgba.a = 255;
271 0           break;
272              
273             case rbc_value:
274 1           nout = hsv_value(ca);
275 1           break;
276              
277             case rbc_hue:
278 1           nout = hsv_hue(ca);
279 1           break;
280              
281             case rbc_sat:
282 2           nout = hsv_sat(ca);
283 2           break;
284            
285             case rbc_hsv:
286 90004           cout = make_hsv(na, nb, nc, 255);
287 90004           break;
288              
289             case rbc_hsva:
290 0           cout = make_hsv(na, nb, nc, nd);
291 0           break;
292              
293             case rbc_red:
294 6           nout = ca.rgb.r;
295 6           break;
296              
297             case rbc_green:
298 6           nout = ca.rgb.g;
299 6           break;
300              
301             case rbc_blue:
302 4           nout = ca.rgb.b;
303 4           break;
304              
305             case rbc_alpha:
306 0           nout = ca.rgba.a;
307 0           break;
308              
309             case rbc_rgb:
310 17           cout = make_rgb(na, nb, nc, 255);
311 17           break;
312              
313             case rbc_rgba:
314 2500           cout = make_rgb(na, nb, nc, nd);
315 2500           break;
316              
317             case rbc_int:
318 1           nout = (int)(na);
319 1           break;
320              
321             case rbc_if:
322 2 100         nout = na ? nb : nc;
323 2           break;
324              
325             case rbc_ifp:
326 1 50         cout = na ? cb : cc;
327 1           break;
328              
329             case rbc_le:
330 1 50         nout = na <= nb + n_epsilon(na,nb);
331 1           break;
332              
333             case rbc_lt:
334 1 50         nout = na < nb;
335 1           break;
336              
337             case rbc_ge:
338 1 50         nout = na >= nb - n_epsilon(na,nb);
339 1           break;
340              
341             case rbc_gt:
342 1 50         nout = na > nb;
343 1           break;
344              
345             case rbc_eq:
346 1 50         nout = fabs(na-nb) <= n_epsilon(na,nb);
347 1           break;
348              
349             case rbc_ne:
350 1 50         nout = fabs(na-nb) > n_epsilon(na,nb);
351 1           break;
352              
353             case rbc_and:
354 1 50         nout = na && nb;
    50          
355 1           break;
356            
357             case rbc_or:
358 1 50         nout = na || nb;
    0          
359 1           break;
360              
361             case rbc_not:
362 1 50         nout = !na;
363 1           break;
364              
365             case rbc_abs:
366 3           nout = fabs(na);
367 3           break;
368              
369             case rbc_ret:
370 181082           return ca;
371             break;
372              
373             case rbc_jump:
374             /* yes, order is important here */
375 0           code_count = count_base - codes->ra;
376 0           codes = codes_base + codes->ra;
377 0           continue;
378            
379             case rbc_jumpz:
380 0 0         if (!na) {
381             /* yes, order is important here */
382 0           code_count = count_base - codes->rb;
383 0           codes = codes_base + codes->rb;
384 0           continue;
385             }
386 0           break;
387              
388             case rbc_jumpnz:
389 0 0         if (na) {
390             /* yes, order is important here */
391 0           code_count = count_base - codes->rb;
392 0           codes = codes_base + codes->rb;
393 0           continue;
394             }
395 0           break;
396              
397             case rbc_set:
398 0           nout = na;
399 0           break;
400              
401             case rbc_setp:
402 0           cout = ca;
403 0           break;
404              
405             case rbc_log:
406 59041 50         if (na > 0) {
407 59041           nout = log(na);
408             }
409             else {
410 0           nout = DBL_MAX;
411             }
412 59041           break;
413              
414             case rbc_exp:
415 2 100         if (!MAX_EXP_ARG) MAX_EXP_ARG = log(DBL_MAX);
416 2 50         if (na <= MAX_EXP_ARG) {
417 2           nout = exp(na);
418             }
419             else {
420 0           nout = DBL_MAX;
421             }
422 2           break;
423              
424             case rbc_print:
425 0           nout = na;
426 0           printf("r%d is %g\n", codes->ra, na);
427 0           break;
428              
429             case rbc_det:
430 2           nout = na*nd-nb*nc;
431 2           break;
432              
433             default:
434             /*croak("bad opcode"); */
435 0           printf("bad op %d\n", codes->code);
436 0           return bcol;
437             }
438 1895029           --code_count;
439 1895029           ++codes;
440             }
441 0           return bcol;
442             /* croak("no return opcode"); */
443             }