Subversion Repositories filter_foundry

Rev

Rev 232 | Rev 268 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
259 daniel-mar 1
/*
2
    This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop
3
    Copyright (C) 2003-2009 Toby Thain, toby@telegraphics.com.au
4
    Copyright (C) 2018-2021 Daniel Marschall, ViaThinkSoft
5
 
6
    This program is free software; you can redistribute it and/or modify
7
    it under the terms of the GNU General Public License as published by
8
    the Free Software Foundation; either version 2 of the License, or
9
    (at your option) any later version.
10
 
11
    This program is distributed in the hope that it will be useful,
12
    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
    GNU General Public License for more details.
15
 
16
    You should have received a copy of the GNU General Public License
17
    along with this program; if not, write to the Free Software
18
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
*/
20
 
21
#ifdef MAC_ENV
22
        #include <fp.h>
23
#endif
24
 
25
#include <math.h>
26
#include <stdlib.h>
27
 
28
#ifndef PARSERTEST
29
#include "ff.h"
30
#endif
31
#include "funcs.h"
32
#include "y.tab.h"
33
 
34
#include "node.h" // for symbol "var[]"
35
 
36
#define RINT //no rounding for now
37
 
38
//#if TARGET_API_MAC_CARBON
39
// this is another incompatibility between Classic stdclib and OS X stdclib
40
// ***FIXME: need to access real OS X includes for Carbon build
41
//#undef RAND_MAX
42
//#define RAND_MAX    0x7fffffff
43
//#endif
44
 
45
extern value_type slider[],cell[],var[],map[][0x100];
46
extern unsigned char *image_ptr;
47
 
48
double costab[COSTABSIZE];
49
double tantab[TANTABSIZE];
50
void init_trigtab(){
51
        int i;
52
        for(i=0;i<COSTABSIZE;++i){
53
                costab[i] = cos(FFANGLE(i));
54
        }
55
        for(i=0;i<TANTABSIZE;++i){
56
                if (i>=TANTABSIZE/2) {
57
                        /* the last '-1' in the expression '512-i-1' is for FilterFactory compatibility, and to avoid the undefined pi/2 area */
58
                        tantab[i] = -tantab[TANTABSIZE-i-1];
59
                } else {
60
                        tantab[i] = tan(FFANGLE(i));
61
                }
62
        }
63
}
64
 
65
/* Channel z for the input pixel at coordinates x,y.
66
 * Coordinates are relative to the input image data (pb->inData) */
67
static value_type rawsrc(value_type x,value_type y,value_type z){
68
        if (HAS_BIG_DOC(gpb)) {
69
                if (x < BIGDOC_IN_RECT(gpb).left)
70
                        x = BIGDOC_IN_RECT(gpb).left;
71
                else if (x >= BIGDOC_IN_RECT(gpb).right)
72
                        x = BIGDOC_IN_RECT(gpb).right - 1;
73
                if (y < BIGDOC_IN_RECT(gpb).top)
74
                        y = BIGDOC_IN_RECT(gpb).top;
75
                else if (y >= BIGDOC_IN_RECT(gpb).bottom)
76
                        y = BIGDOC_IN_RECT(gpb).bottom - 1;
77
                return ((unsigned char*)gpb->inData)[(long)gpb->inRowBytes * (y - BIGDOC_IN_RECT(gpb).top)
78
                        + (long)nplanes * (x - BIGDOC_IN_RECT(gpb).left) + z];
79
        } else {
80
                if (x < IN_RECT(gpb).left)
81
                        x = IN_RECT(gpb).left;
82
                else if (x >= IN_RECT(gpb).right)
83
                        x = IN_RECT(gpb).right - 1;
84
                if (y < IN_RECT(gpb).top)
85
                        y = IN_RECT(gpb).top;
86
                else if (y >= IN_RECT(gpb).bottom)
87
                        y = IN_RECT(gpb).bottom - 1;
88
                return ((unsigned char*)gpb->inData)[(long)gpb->inRowBytes * (y - IN_RECT(gpb).top)
89
                        + (long)nplanes * (x - IN_RECT(gpb).left) + z];
90
        }
91
}
92
 
93
/* src(x,y,z) Channel z for the pixel at coordinates x,y.
94
 * Coordinates are relative to filtered area (selection). */
95
value_type ff_src(value_type x,value_type y,value_type z){
96
#ifdef PARSERTEST
97
        return 0;
98
#else
99
        if(x < 0)
100
                x = 0;
101
        else if(x >= var['X'])
102
                x = var['X']-1;
103
        if(y < 0)
104
                y = 0;
105
        else if(y >= var['Y'])
106
                y = var['Y']-1;
107
        return z >= 0 && z < var['Z'] ?
108
                image_ptr[(long)gpb->inRowBytes*y + (long)nplanes*x + z] : 0;
109
#endif
110
}
111
 
112
/* rad(d,m,z) Channel z in the source image, which is m units away,
113
        at an angle of d, from the center of the image */
114
value_type ff_rad(value_type d,value_type m,value_type z){
115
        return ff_src(ff_r2x(d,m) + var['X']/2, ff_r2y(d,m) + var['Y']/2, z);
116
}
117
 
118
/* ctl(i) Value of slider i, where i is an integer between 0 and 7, inclusive */
119
value_type ff_ctl(value_type i){
120
        return i>=0 && i<=7 ? slider[i] : 0;
121
}
122
 
123
/* val(i,a,b) Value of slider i, mapped onto the range a to b */
124
value_type ff_val(value_type i,value_type a,value_type b){
125
        return ((long)ff_ctl(i)*(b-a))/255 + a;
126
}
127
 
128
/* map(i,n) Item n from mapping table i, where i is an integer between
129
 
130
        inclusive */
131
value_type ff_map(value_type i,value_type n){
132
/*
133
        if( i>=0 && i<=3 && n>=0 && n<=255 ){
134
                int H = slider[i*2],L = slider[i*2+1];
135
                return n<=L || H==L ? 0 : ( n>=H ? 255 : ((n-L)*255L)/(H-L) );
136
        }else
137
                return 0;
138
*/
139
        // this code is from GIMP User Filter
140
        value_type x = ff_ctl(i*2),
141
                           y = ff_ctl(i*2+1);
142
        return abs(((long)n*(y-x) / 255)+x);
143
}
144
 
145
/* min(a,b) Lesser of a and b */
146
value_type ff_min(value_type a,value_type b){
147
        return a < b ? a : b;
148
}
149
 
150
/* max(a,b) Greater of a and b */
151
value_type ff_max(value_type a,value_type b){
152
        return a > b ? a : b;
153
}
154
 
155
/* abs(a) Absolute value of a */
156
value_type ff_abs(value_type a){
157
        return abs(a);
158
}
159
 
160
/* add(a,b,c) Sum of a and b, or c, whichever is lesser */
161
value_type ff_add(value_type a,value_type b,value_type c){
162
        return ff_min(a+b,c);
163
}
164
 
165
/* sub(a,b,c) Difference of a and b, or c, whichever is greater */
166
value_type ff_sub(value_type a,value_type b,value_type c){
167
        return ff_max(ff_dif(a,b),c);
168
}
169
 
170
/* dif(a,b) Absolute value of the difference of a and b */
171
value_type ff_dif(value_type a,value_type b){
172
        return abs(a-b);
173
}
174
 
175
/* rnd(a,b) Random number between a and b, inclusive */
176
value_type ff_rnd(value_type a,value_type b){
177
        return (int)((abs(a-b)+1)*(rand()/(RAND_MAX+1.))) + ff_min(a,b);
178
//      return ((unsigned)rand() % (ff_dif(a,b)+1)) + ff_min(a,b);
179
}
180
 
181
/* mix(a,b,n,d) Mixture of a and b by fraction n/d, a*n/d+b*(d-n)/d */
182
value_type ff_mix(value_type a,value_type b,value_type n,value_type d){
183
        return d ? ((long)a*n)/d + ((long)b*(d-n))/d : 0;
184
}
185
 
186
/* scl(a,il,ih,ol,oh) Scale a from input range (il to ih)
187
                      to output range (ol to oh) */
188
value_type ff_scl(value_type a,value_type il,value_type ih,
189
                  value_type ol,value_type oh){
190
        return ih==il ? 0 : ol + ((long)(oh-ol)*(a-il))/(ih-il);
191
}
192
 
193
static uint32_t isqrt(uint32_t x) {
194
        // based on https://gist.github.com/orlp/3481770
195
 
196
        static uint32_t lkpSquares[65535];
197
        static int lkpInitialized = 0;
198
        const uint32_t *p;
199
        int i;
200
 
201
        while (lkpInitialized == 1) { /* If other thread is currently creating the lookup table, then wait */ }
202
        if (!lkpInitialized) {
203
                lkpInitialized = 1;
204
                for (i = 0; i < 65535; ++i) {
205
                        lkpSquares[i] = i * i;
206
                }
207
                lkpInitialized = 2;
208
        }
209
 
210
        p = lkpSquares;
211
 
212
        if (p[32768] <= x) p += 32768;
213
        if (p[16384] <= x) p += 16384;
214
        if (p[8192] <= x) p += 8192;
215
        if (p[4096] <= x) p += 4096;
216
        if (p[2048] <= x) p += 2048;
217
        if (p[1024] <= x) p += 1024;
218
        if (p[512] <= x) p += 512;
219
        if (p[256] <= x) p += 256;
220
        if (p[128] <= x) p += 128;
221
        if (p[64] <= x) p += 64;
222
        if (p[32] <= x) p += 32;
223
        if (p[16] <= x) p += 16;
224
        if (p[8] <= x) p += 8;
225
        if (p[4] <= x) p += 4;
226
        if (p[2] <= x) p += 2;
227
        if (p[1] <= x) p += 1;
228
 
229
        return (uint32_t)(p - lkpSquares);
230
}
231
 
232
/* sqr(x) Square root of x */
233
value_type ff_sqr(value_type x){
234
        return x < 0 ? 0 : isqrt(x);
235
}
236
 
237
/* sin(x) Sine function of x, where x is an integer between 0 and
238
   1024, inclusive, and the value returned is an integer
239
   between -512 and 512, inclusive (Windows) or -1024 and
240
   1024, inclusive (Mac OS) */
241
value_type ff_sin(value_type x){
242
        //return RINT(TRIGAMP*sin(FFANGLE(x)));
243
        return ff_cos(x-256);
244
}
245
 
246
/* cos(x) Cosine function of x, where x is an integer between 0 and
247
   1024, inclusive, and the value returned is an integer
248
   between -512 and 512, inclusive (Windows) or -1024 and
249
   1024, inclusive (Mac OS) */
250
value_type ff_cos(value_type x){
251
        //return RINT(TRIGAMP*cos(FFANGLE(x)));
252
        return (value_type)RINT(TRIGAMP*costab[abs(x) % COSTABSIZE]);
253
}
254
 
255
/* tan(x) Tangent function of x, where x is an integer
256
   between -256 and 256, inclusive. Althought the Filter Factory manual
257
   stated that the return value is bounded to -512 and 512, inclusive (Windows) or
258
   -1024 and 1024, inclusive (Mac OS), the output is actually NOT bounded! */
259
value_type ff_tan(value_type x){
260
        // Following filter shows that the Filter Factory manual differs from the implementation.
261
        //         R = cos(x) > 1024 || cos(x) < -1024 || cos(-x) > 1024 || cos(-x) < -1024 ? 255 : 0
262
        //     G = tan(x) > 1024 || tan(x) < -1024 || tan(-x) > 1024 || tan(-x) < -1024 ? 255 : 0
263
        //     B = sin(x) > 1024 || sin(x) < -1024 || sin(-x) > 1024 || sin(-x) < -1024 ? 255 : 0
264
        // It outputs green stripes, showing that the output of tan() is not bounded.
265
        // So, we do it the same way to stay compatible.
266
        if (x < 0) x--; /* required for Filter Factory compatibility */
267
        while (x < 0) x += TANTABSIZE;
268
        return (value_type)RINT(2*TRIGAMP*tantab[x % TANTABSIZE]); // We need the x2 multiplicator for some reason
269
}
270
 
271
/* r2x(d,m) x displacement of the pixel m units away, at an angle of d,
272
   from an arbitrary center */
273
value_type ff_r2x(value_type d,value_type m){
274
        return (value_type)RINT(m*costab[abs(d) % COSTABSIZE]);
275
}
276
 
277
/* r2y(d,m) y displacement of the pixel m units away, at an angle of d,
278
   from an arbitrary center */
279
value_type ff_r2y(value_type d,value_type m){
280
        return (value_type)RINT(m*costab[abs(d-256) % COSTABSIZE]);
281
}
282
 
283
/* Attention! This is NOT a function. It is internally used to calculate the variable "d". */
284
value_type ff_c2d_negated(value_type x, value_type y) {
285
        // NOTE: FilterFactory uses c2d(x,y):=atan2(y,x), but d:=atan2(-y,-x)
286
        // Due to compatibility reasons, we implement it the same way!
287
        // Sign of y difference is negated, as we are dealing with top-down coordinates angle is "observed"
288
        return (value_type)RINT(TO_FFANGLE(atan2(-y,-x)));
289
}
290
 
291
/* c2d(x,y) Angle displacement of the pixel at coordinates x,y */
292
value_type ff_c2d(value_type x,value_type y){
293
        // Behavior of FilterFoundry <1.7:
294
        //return ff_c2d_negated(x,y);
295
 
296
        // Behavior in FilterFoundry 1.7+: Matches FilterFactory
297
        return (value_type)RINT(TO_FFANGLE(atan2(y,x)));
298
}
299
 
300
/* c2m(x,y) Magnitude displacement of the pixel at coordinates x,y */
301
value_type ff_c2m(value_type x,value_type y){
302
        return isqrt((long)x*x + (long)y*y);
303
}
304
 
305
/* get(i) Returns the current cell value at i */
306
value_type ff_get(value_type i){
307
        // Filter Factory:
308
        //return i>=0 && i<NUM_CELLS ? cell[i] : i;
309
 
310
        // Filter Foundry:
311
        return i>=0 && i<NUM_CELLS ? cell[i] : 0;
312
}
313
 
314
/* put(v,i) Puts the new value v into cell i */
315
value_type ff_put(value_type v,value_type i){
316
        if(i>=0 && i<NUM_CELLS)
317
                cell[i] = v;
318
        return v;
319
}
320
 
321
/* Convolve. Applies a convolution matrix and divides with d. */
322
value_type ff_cnv(value_type m11,value_type m12,value_type m13,
323
                                  value_type m21,value_type m22,value_type m23,
324
                                  value_type m31,value_type m32,value_type m33,
325
                                  value_type d)
326
{
327
#ifdef PARSERTEST
328
        return 0;
329
#else
330
        long total;
331
        int x, y, z;
332
        // shift x,y from selection-relative to image relative
333
        if (HAS_BIG_DOC(gpb)) {
334
                x = var['x'] + BIGDOC_FILTER_RECT(gpb).left;
335
                y = var['y'] + BIGDOC_FILTER_RECT(gpb).top;
336
        } else {
337
                x = var['x'] + FILTER_RECT(gpb).left;
338
                y = var['y'] + FILTER_RECT(gpb).top;
339
        }
340
        z = var['z'];
341
 
342
        if(z >= 0 && z < var['Z'])
343
                total = m11*rawsrc(x-1,y-1,z) + m12*rawsrc(x,y-1,z) + m13*rawsrc(x+1,y-1,z)
344
                          + m21*rawsrc(x-1,y,  z) + m22*rawsrc(x,y,  z) + m23*rawsrc(x+1,y,  z)
345
                          + m31*rawsrc(x-1,y+1,z) + m32*rawsrc(x,y+1,z) + m33*rawsrc(x+1,y+1,z);
346
        else
347
                total = 0;
348
 
349
        return d ? total/d : 0;
350
#endif
351
}
352
 
353
/* rst(i) sets a random seed and returns 0. (undocumented Filter Factory function).
354
   Added by DM, 18 Dec 2018 */
355
value_type ff_rst(value_type seed){
356
        srand(seed);
357
        return 0;
358
}
359
 
360
value_type zero_val = 0;
361
value_type one_val = 1;
362
value_type max_channel_val = 255;
363
 
364
/* predefined symbols */
365
struct sym_rec predefs[]={
366
        /* functions */
367
 
368
        {0,TOK_FN3,"src", (pfunc_type)ff_src, 0},
369
        {0,TOK_FN3,"rad", (pfunc_type)ff_rad, 0},
370
        {0,TOK_FN1,"ctl", (pfunc_type)ff_ctl, 0},
371
        {0,TOK_FN3,"val", (pfunc_type)ff_val, 0},
372
        {0,TOK_FN2,"map", (pfunc_type)ff_map, 0},
373
        {0,TOK_FN2,"min", (pfunc_type)ff_min, 0},
374
        {0,TOK_FN2,"max", (pfunc_type)ff_max, 0},
375
        {0,TOK_FN1,"abs", (pfunc_type)ff_abs, 0},
376
        {0,TOK_FN3,"add", (pfunc_type)ff_add, 0},
377
        {0,TOK_FN3,"sub", (pfunc_type)ff_sub, 0},
378
        {0,TOK_FN2,"dif", (pfunc_type)ff_dif, 0},
379
        {0,TOK_FN2,"rnd", (pfunc_type)ff_rnd, 0},
380
        {0,TOK_FN4,"mix", (pfunc_type)ff_mix, 0},
381
        {0,TOK_FN5,"scl", (pfunc_type)ff_scl, 0},
382
        {0,TOK_FN1,"sqr", (pfunc_type)ff_sqr, 0},
383
        {0,TOK_FN1,"sqrt", (pfunc_type)ff_sqr, 0}, // sqrt() is synonym to sqr() in Premiere
384
        {0,TOK_FN1,"sin", (pfunc_type)ff_sin, 0},
385
        {0,TOK_FN1,"cos", (pfunc_type)ff_cos, 0},
386
        {0,TOK_FN1,"tan", (pfunc_type)ff_tan, 0},
387
        {0,TOK_FN2,"r2x", (pfunc_type)ff_r2x, 0},
388
        {0,TOK_FN2,"r2y", (pfunc_type)ff_r2y, 0},
389
        {0,TOK_FN2,"c2d", (pfunc_type)ff_c2d, 0},
390
        {0,TOK_FN2,"c2m", (pfunc_type)ff_c2m, 0},
391
        {0,TOK_FN1,"get", (pfunc_type)ff_get, 0},
392
        {0,TOK_FN2,"put", (pfunc_type)ff_put, 0},
393
        {0,TOK_FN10,"cnv",(pfunc_type)ff_cnv, 0},
394
        {0,TOK_FN1,"rst", (pfunc_type)ff_rst, 0}, // undocumented FilterFactory function
395
 
396
        /* predefined variables (names with more than 1 character); most of them are undocumented in FilterFactory */
397
        /* the predefined variables with 1 character are defined in lexer.l and process.c */
398
        /* in this table, you must not add TOK_VAR with only 1 character (since this case is not defined in parser.y) */
399
 
400
        {0,TOK_VAR,"rmax",0, &max_channel_val}, // alias of 'R' (defined in lexer.l, line 129)
401
        {0,TOK_VAR,"gmax",0, &max_channel_val}, // alias of 'G' (defined in lexer.l, line 129)
402
        {0,TOK_VAR,"bmax",0, &max_channel_val}, // alias of 'B' (defined in lexer.l, line 129)
403
        {0,TOK_VAR,"amax",0, &max_channel_val}, // alias of 'A' (defined in lexer.l, line 129)
404
        {0,TOK_VAR,"cmax",0, &max_channel_val}, // alias of 'C' (defined in lexer.l, line 129)
405
        {0,TOK_VAR,"imax",0, &max_channel_val}, // alias of 'I' (defined in lexer.l, line 129)
406
        {0,TOK_VAR,"umax",0, &max_channel_val}, // alias of 'U' (defined in lexer.l, line 129)
407
        {0,TOK_VAR,"vmax",0, &max_channel_val}, // alias of 'V' (defined in lexer.l, line 129)
408
        {0,TOK_VAR,"dmax",0, &var['D']},
409
        {0,TOK_VAR,"mmax",0, &var['M']},
410
        {0,TOK_VAR,"pmax",0, &var['Z']},
411
        {0,TOK_VAR,"xmax",0, &var['X']},
412
        {0,TOK_VAR,"ymax",0, &var['Y']},
413
        {0,TOK_VAR,"zmax",0, &var['Z']},
414
 
415
        {0,TOK_VAR,"rmin",0, &zero_val},
416
        {0,TOK_VAR,"gmin",0, &zero_val},
417
        {0,TOK_VAR,"bmin",0, &zero_val},
418
        {0,TOK_VAR,"amin",0, &zero_val},
419
        {0,TOK_VAR,"cmin",0, &zero_val},
420
        {0,TOK_VAR,"imin",0, &zero_val},
421
        {0,TOK_VAR,"umin",0, &zero_val},
422
        {0,TOK_VAR,"vmin",0, &zero_val},
423
        {0,TOK_VAR,"dmin",0, &zero_val},
424
        {0,TOK_VAR,"mmin",0, &zero_val},
425
        {0,TOK_VAR,"pmin",0, &zero_val},
426
        {0,TOK_VAR,"xmin",0, &zero_val},
427
        {0,TOK_VAR,"ymin",0, &zero_val},
428
        {0,TOK_VAR,"zmin",0, &zero_val},
429
 
430
        /* Undocumented synonyms of FilterFactory for compatibility with Premiere */
431
        {0,TOK_FN10,"cnv0",(pfunc_type)ff_cnv, 0},
432
        {0,TOK_FN3,"src0", (pfunc_type)ff_src, 0},
433
        {0,TOK_FN3,"rad0", (pfunc_type)ff_rad, 0},
434
        {0,TOK_FN10,"cnv1",(pfunc_type)ff_cnv, 0},
435
        {0,TOK_FN3,"src1", (pfunc_type)ff_src, 0},
436
        {0,TOK_FN3,"rad1", (pfunc_type)ff_rad, 0},
437
        {0,TOK_VAR,"r0",0, &var['r']},
438
        {0,TOK_VAR,"g0",0, &var['g']},
439
        {0,TOK_VAR,"b0",0, &var['b']},
440
        {0,TOK_VAR,"a0",0, &var['a']},
441
        {0,TOK_VAR,"c0",0, &var['c']},
442
        {0,TOK_VAR,"i0",0, &var['i']},
443
        {0,TOK_VAR,"u0",0, &var['u']},
444
        {0,TOK_VAR,"v0",0, &var['v']},
445
        {0,TOK_VAR,"d0",0, &var['d']},
446
        {0,TOK_VAR,"m0",0, &var['m']},
447
        {0,TOK_VAR,"r1",0, &var['r']},
448
        {0,TOK_VAR,"g1",0, &var['g']},
449
        {0,TOK_VAR,"b1",0, &var['b']},
450
        {0,TOK_VAR,"a1",0, &var['a']},
451
        {0,TOK_VAR,"c1",0, &var['c']},
452
        {0,TOK_VAR,"i1",0, &var['i']},
453
        {0,TOK_VAR,"u1",0, &var['u']},
454
        {0,TOK_VAR,"v1",0, &var['v']},
455
        {0,TOK_VAR,"d1",0, &var['d']},
456
        {0,TOK_VAR,"m1",0, &var['m']},
457
        {0,TOK_VAR,"tmin",0, &zero_val},
458
        {0,TOK_VAR,"tmax",0, &one_val},
459
        {0,TOK_VAR,"total",0, &one_val},
460
 
461
        {0,0,0,0,0}
462
};