38,6 → 38,7 |
#define use_filterfactory_implementation_d |
#define use_filterfactory_implementation_m |
#define use_filterfactory_implementation_M |
//#define use_filterfactory_implementation_get |
#endif |
|
#ifdef MAC_ENV |
49,6 → 50,11 |
|
#ifndef PARSERTEST |
#include "ff.h" |
#else |
#define value_type int |
#define uint16_t int |
#define uint32_t int |
#define int32_t int |
#endif |
|
#include "funcs.h" |
278,6 → 284,9 |
double costab[COSTABSIZE]; |
double tantab[TANTABSIZE]; |
void init_trigtab(){ |
#ifdef PARSERTEST |
return 0; |
#else |
int i; |
for(i=0;i<COSTABSIZE;++i){ |
costab[i] = cos(FFANGLE(i)); |
290,6 → 299,7 |
tantab[i] = tan(FFANGLE(i)); |
} |
} |
#endif |
} |
|
// ------------------------------------------------------------------------------------------- |
297,6 → 307,9 |
/* Channel z for the input pixel at coordinates x,y. |
* Coordinates are relative to the input image data (pb->inData) */ |
static value_type rawsrc(value_type x,value_type y,value_type z){ |
#ifdef PARSERTEST |
return 0; |
#else |
if (HAS_BIG_DOC(gpb)) { |
if (x < BIGDOC_IN_RECT(gpb).left) |
x = BIGDOC_IN_RECT(gpb).left; |
320,6 → 333,7 |
return ((unsigned char*)gpb->inData)[(long)gpb->inRowBytes * (y - IN_RECT(gpb).top) |
+ (long)nplanes * (x - IN_RECT(gpb).left) + z]; |
} |
#endif |
} |
|
// ------------------------------------------------------------------------------------------- |
351,15 → 365,23 |
|
value_type factory_r2x(value_type d, value_type m) { |
// https://misc.daniel-marschall.de/projects/filter_factory/function_r2x.html |
#ifdef PARSERTEST |
return 0; |
#else |
int eax = m; |
int ebx = d; |
ebx &= 1023; |
ebx = FACTORY_COS_LOOKUP[ebx]; |
return (((int64_t)eax * (int64_t)ebx) + 8191) >> 14; |
#endif |
} |
|
value_type foundry_r2x(value_type d, value_type m) { |
#ifdef PARSERTEST |
return 0; |
#else |
return (value_type)RINT(m * costab[abs(d) % COSTABSIZE]); |
#endif |
} |
|
value_type ff_r2x(value_type d, value_type m) { |
376,12 → 398,20 |
from an arbitrary center */ |
|
value_type factory_r2y(value_type d, value_type m) { |
#ifdef PARSERTEST |
return 0; |
#else |
// https://misc.daniel-marschall.de/projects/filter_factory/function_r2y.html |
return factory_r2x(d - 256, m); |
#endif |
} |
|
value_type foundry_r2y(value_type d, value_type m) { |
#ifdef PARSERTEST |
return 0; |
#else |
return (value_type)RINT(m * costab[abs(d - 256) % COSTABSIZE]); |
#endif |
} |
|
value_type ff_r2y(value_type d, value_type m) { |
398,6 → 428,9 |
at an angle of d, from the center of the image */ |
|
value_type factory_rad(value_type d, value_type m, value_type z) { |
#ifdef PARSERTEST |
return 0; |
#else |
// https://misc.daniel-marschall.de/projects/filter_factory/function_rad.html |
|
const int xmin = 0; |
437,10 → 470,15 |
ebx *= gpb->inRowBytes; |
ecx *= var['Z'] - zmin; |
return image_ptr[z+ebx+ecx]; |
#endif |
} |
|
value_type foundry_rad(value_type d, value_type m, value_type z) { |
#ifdef PARSERTEST |
return 0; |
#else |
return ff_src(foundry_r2x(d, m) + var['X'] / 2, foundry_r2y(d, m) + var['Y'] / 2, z); |
#endif |
} |
|
value_type ff_rad(value_type d,value_type m,value_type z){ |
455,7 → 493,11 |
|
/* ctl(i) Value of slider i, where i is an integer between 0 and 7, inclusive */ |
value_type ff_ctl(value_type i){ |
#ifdef PARSERTEST |
return 0; |
#else |
return i>=0 && i<=7 ? slider[i] : 0; |
#endif |
} |
|
// ------------------------------------------------------------------------------------------- |
462,7 → 504,11 |
|
/* val(i,a,b) Value of slider i, mapped onto the range a to b */ |
value_type ff_val(value_type i,value_type a,value_type b){ |
#ifdef PARSERTEST |
return 0; |
#else |
return ((long)ff_ctl(i)*(b-a))/255 + a; |
#endif |
} |
|
// ------------------------------------------------------------------------------------------- |
471,6 → 517,9 |
0 and 3, inclusive, and n is and integer between 0 and 255, |
inclusive */ |
value_type ff_map(value_type i,value_type n){ |
#ifdef PARSERTEST |
return 0; |
#else |
/* |
if( i>=0 && i<=3 && n>=0 && n<=255 ){ |
int H = slider[i*2],L = slider[i*2+1]; |
482,6 → 531,7 |
value_type x = ff_ctl(i*2), |
y = ff_ctl(i*2+1); |
return abs(((long)n*(y-x) / 255)+x); |
#endif |
} |
|
// ------------------------------------------------------------------------------------------- |
488,7 → 538,11 |
|
/* min(a,b) Lesser of a and b */ |
value_type ff_min(value_type a,value_type b){ |
#ifdef PARSERTEST |
return 0; |
#else |
return a < b ? a : b; |
#endif |
} |
|
// ------------------------------------------------------------------------------------------- |
495,7 → 549,11 |
|
/* max(a,b) Greater of a and b */ |
value_type ff_max(value_type a,value_type b){ |
#ifdef PARSERTEST |
return 0; |
#else |
return a > b ? a : b; |
#endif |
} |
|
// ------------------------------------------------------------------------------------------- |
502,7 → 560,11 |
|
/* abs(a) Absolute value of a */ |
value_type ff_abs(value_type a){ |
#ifdef PARSERTEST |
return 0; |
#else |
return abs(a); |
#endif |
} |
|
// ------------------------------------------------------------------------------------------- |
509,7 → 571,11 |
|
/* add(a,b,c) Sum of a and b, or c, whichever is lesser */ |
value_type ff_add(value_type a,value_type b,value_type c){ |
#ifdef PARSERTEST |
return 0; |
#else |
return ff_min(a+b,c); |
#endif |
} |
|
// ------------------------------------------------------------------------------------------- |
516,7 → 582,11 |
|
/* sub(a,b,c) Difference of a and b, or c, whichever is greater */ |
value_type ff_sub(value_type a,value_type b,value_type c){ |
#ifdef PARSERTEST |
return 0; |
#else |
return ff_max(ff_dif(a,b),c); |
#endif |
} |
|
// ------------------------------------------------------------------------------------------- |
523,7 → 593,11 |
|
/* dif(a,b) Absolute value of the difference of a and b */ |
value_type ff_dif(value_type a,value_type b){ |
#ifdef PARSERTEST |
return 0; |
#else |
return abs(a-b); |
#endif |
} |
|
// ------------------------------------------------------------------------------------------- |
539,6 → 613,9 |
} gFactoryRngState; |
|
void factory_fill_rnd_lookup(uint32_t seed, struct factoryRngState* state) { |
#ifdef PARSERTEST |
return 0; |
#else |
// Algorithm of Filter Factory |
// Filter Factory uses Donald E.Knuth's subtractive |
// random number generator algorithm ("ran3"), which has been published |
573,9 → 650,13 |
state->seedSave = seed; |
|
return; |
#endif |
} |
|
uint32_t factory_rnd(uint32_t a, uint32_t b, struct factoryRngState* state) { |
#ifdef PARSERTEST |
return 0; |
#else |
uint32_t mj; // Note: This must be "uint32_t". With "long" (as described by Knuth), it won't match FilterFactory's algorithm |
int range; |
|
627,11 → 708,16 |
default: |
return a + (mj % (range + 1)); |
} |
#endif |
} |
|
value_type foundry_rnd(value_type a, value_type b) { |
#ifdef PARSERTEST |
return 0; |
#else |
return (int)((abs(a-b)+1)*(rand()/(RAND_MAX+1.))) + ff_min(a,b); |
// return ((unsigned)rand() % (ff_dif(a,b)+1)) + ff_min(a,b); |
#endif |
} |
|
value_type ff_rnd(value_type a,value_type b){ |
645,12 → 731,20 |
// ------------------------------------------------------------------------------------------- |
|
void factory_initialize_rnd_variables() { |
#ifdef PARSERTEST |
return 0; |
#else |
gFactoryRngState.seed = 0; // default seed |
gFactoryRngState.seedSave = gFactoryRngState.seed + 1; // force rnd() to call factory_fill_rnd_lookup() |
#endif |
} |
|
void foundry_initialize_rnd_variables() { |
srand(691204); |
#ifdef PARSERTEST |
return 0; |
#else |
foundry_rst(691204); |
#endif |
} |
|
void initialize_rnd_variables() { |
667,6 → 761,9 |
Added by DM, 18 Dec 2018 */ |
|
int32_t factory_rst(uint32_t seed, struct factoryRngState* state) { |
#ifdef PARSERTEST |
return 0; |
#else |
// Attention: This is NOT the FilterFactory rst() implementation! |
|
// We implement rst(i) completely differently in Filter Foundry: |
688,11 → 785,16 |
state->seedSave = seed + 1; |
|
return 0; |
#endif |
} |
|
value_type foundry_rst(value_type seed) { |
#ifdef PARSERTEST |
return 0; |
#else |
srand(seed); |
return 0; |
#endif |
} |
|
value_type ff_rst(value_type seed) { |
707,7 → 809,11 |
|
/* mix(a,b,n,d) Mixture of a and b by fraction n/d, a*n/d+b*(d-n)/d */ |
value_type ff_mix(value_type a,value_type b,value_type n,value_type d){ |
#ifdef PARSERTEST |
return 0; |
#else |
return d ? ((long)a*n)/d + ((long)b*(d-n))/d : 0; |
#endif |
} |
|
// ------------------------------------------------------------------------------------------- |
716,7 → 822,11 |
to output range (ol to oh) */ |
value_type ff_scl(value_type a,value_type il,value_type ih, |
value_type ol,value_type oh){ |
#ifdef PARSERTEST |
return 0; |
#else |
return ih==il ? 0 : ol + ((long)(oh-ol)*(a-il))/(ih-il); |
#endif |
} |
|
// ------------------------------------------------------------------------------------------- |
724,6 → 834,9 |
/* sqr(x) Square root of x */ |
|
static uint32_t isqrt(uint32_t x) { |
#ifdef PARSERTEST |
return 0; |
#else |
// based on https://gist.github.com/orlp/3481770 |
|
static uint32_t lkpSquares[65535]; |
760,9 → 873,13 |
if (p[1] <= x) p += 1; |
|
return (uint32_t)(p - lkpSquares); |
#endif |
} |
|
value_type factory_sqr(value_type x) { |
#ifdef PARSERTEST |
return 0; |
#else |
// https://misc.daniel-marschall.de/projects/filter_factory/function_sqr.html |
|
int eax, ebx, ecx; |
780,11 → 897,16 |
} |
} |
return ebx; |
#endif |
} |
|
value_type foundry_sqr(value_type x) { |
#ifdef PARSERTEST |
return 0; |
#else |
// Note: FilterFactory has sqr(x)=x if x<0 . Here we set sqr(x)=0 for x<0 |
return x < 0 ? 0 : isqrt(x); |
#endif |
} |
|
value_type ff_sqr(value_type x){ |
803,6 → 925,9 |
1024, inclusive (Mac OS) */ |
|
value_type factory_cos(value_type x) { |
#ifdef PARSERTEST |
return 0; |
#else |
// https://misc.daniel-marschall.de/projects/filter_factory/function_cos.html |
int res; |
if (x < 0) x = -x; |
809,11 → 934,16 |
x &= 0x3ff; // 1023 |
res = FACTORY_COS_LOOKUP[x]; |
return res >= 0 ? (res / 32) : res / 32 - 1; |
#endif |
} |
|
value_type foundry_cos(value_type x) { |
#ifdef PARSERTEST |
return 0; |
#else |
//return RINT(TRIGAMP*cos(FFANGLE(x))); |
return (value_type)RINT(TRIGAMP * costab[abs(x) % COSTABSIZE]); |
#endif |
} |
|
value_type ff_cos(value_type x){ |
832,13 → 962,21 |
1024, inclusive (Mac OS) */ |
|
value_type factory_sin(value_type x) { |
#ifdef PARSERTEST |
return 0; |
#else |
// https://misc.daniel-marschall.de/projects/filter_factory/function_sin.html |
return factory_cos(x - 256); |
#endif |
} |
|
value_type foundry_sin(value_type x) { |
#ifdef PARSERTEST |
return 0; |
#else |
//return RINT(TRIGAMP*sin(FFANGLE(x))); |
return foundry_cos(x - 256); |
#endif |
} |
|
value_type ff_sin(value_type x) { |
857,6 → 995,9 |
-1024 and 1024, inclusive (Mac OS), the output is actually NOT bounded! */ |
|
value_type factory_tan(value_type x) { |
#ifdef PARSERTEST |
return 0; |
#else |
// https://misc.daniel-marschall.de/projects/filter_factory/function_tan.html |
int v1 = x; |
int v2 = v1 < 0 ? -v1 : v1; |
869,9 → 1010,13 |
if (v2 == 0) return 0; |
v1 = v1 << 10; // v1 *= 1024; |
return v1 / v2; |
#endif |
} |
|
value_type foundry_tan(value_type x){ |
#ifdef PARSERTEST |
return 0; |
#else |
// Following filter shows that the Filter Factory manual differs from the implementation. |
// R = cos(x) > 1024 || cos(x) < -1024 || cos(-x) > 1024 || cos(-x) < -1024 ? 255 : 0 |
// G = tan(x) > 1024 || tan(x) < -1024 || tan(-x) > 1024 || tan(-x) < -1024 ? 255 : 0 |
881,6 → 1026,7 |
if (x < 0) x--; /* required for Filter Factory compatibility */ |
while (x < 0) x += TANTABSIZE; |
return (value_type)RINT(2*TRIGAMP*tantab[x % TANTABSIZE]); // We need the x2 multiplicator for some reason |
#endif |
} |
|
value_type ff_tan(value_type x) { |
896,6 → 1042,9 |
/* c2d(x,y) Angle displacement of the pixel at coordinates x,y */ |
|
value_type factory_c2d(value_type x, value_type y) { |
#ifdef PARSERTEST |
return 0; |
#else |
// https://misc.daniel-marschall.de/projects/filter_factory/function_c2d.html |
int32_t eax, ebx, ecx; |
eax = y; |
937,14 → 1086,19 |
eax = -eax; |
} |
return eax; |
#endif |
} |
|
value_type foundry_c2d(value_type x, value_type y) { |
#ifdef PARSERTEST |
return 0; |
#else |
// Behavior of FilterFoundry <1.7: |
//return foundry_c2d_negated(x,y); |
|
// Behavior in FilterFoundry 1.7+: Matches FilterFactory |
return (value_type)RINT(TO_FFANGLE(atan2(y, x))); |
#endif |
} |
|
value_type ff_c2d(value_type x, value_type y) { |
960,6 → 1114,9 |
/* c2m(x,y) Magnitude displacement of the pixel at coordinates x,y */ |
|
value_type factory_c2m(value_type x, value_type y) { |
#ifdef PARSERTEST |
return 0; |
#else |
// https://misc.daniel-marschall.de/projects/filter_factory/function_c2m.html |
int32_t eax, ebx; |
ebx = y < 0 ? -y : y; |
980,10 → 1137,15 |
eax = ((int64_t)eax * (int64_t)ebx) >> 16; |
eax += ebx; |
return eax; |
#endif |
} |
|
value_type foundry_c2m(value_type x, value_type y) { |
#ifdef PARSERTEST |
return 0; |
#else |
return isqrt((long)x * x + (long)y * y); |
#endif |
} |
|
value_type ff_c2m(value_type x, value_type y) { |
1008,6 → 1170,9 |
where d is an integer between 0 and 1024 inclusive */ |
|
value_type factory_d() { |
#ifdef PARSERTEST |
return 0; |
#else |
// https://misc.daniel-marschall.de/projects/filter_factory/symbol_d_lowercase.html |
|
int eax, ebx, ecx; |
1054,13 → 1219,21 |
eax = -eax; |
} |
return eax; |
#endif |
} |
|
value_type foundry_c2d_negated(int x, int y) { |
#ifdef PARSERTEST |
return 0; |
#else |
return (value_type)RINT(TO_FFANGLE(atan2(-y, -x))); |
#endif |
} |
|
value_type foundry_d() { |
#ifdef PARSERTEST |
return 0; |
#else |
// NOTE: FilterFactory uses c2d(x,y):=atan2(y,x), but d:=atan2(-y,-x) |
// Due to compatibility reasons, we implement it the same way! |
// Sign of y difference is negated, as we are dealing with top-down coordinates angle is "observed" |
1067,6 → 1240,7 |
int x = var['X'] / 2 - var['x']; |
int y = var['Y'] / 2 - var['y']; |
return foundry_c2d_negated(x, y); |
#endif |
} |
|
value_type ff_d() { |
1082,6 → 1256,9 |
/* Range of magnitudes with the image, where M is one half the diagonal size of the image */ |
|
value_type factory_M() { |
#ifdef PARSERTEST |
return 0; |
#else |
// https://misc.daniel-marschall.de/projects/filter_factory/symbol_m_uppercase.html |
|
int eax, ebx; |
1105,10 → 1282,15 |
eax = ((int64_t)eax * (int64_t)ebx) >> 16; |
eax += ebx; |
return eax; |
#endif |
} |
|
value_type foundry_M() { |
#ifdef PARSERTEST |
return 0; |
#else |
return foundry_c2m(var['X'], var['Y']) / 2; |
#endif |
} |
|
value_type ff_M() { |
1124,6 → 1306,9 |
/* Distance (magnitude) from the center of the image to the current pixel */ |
|
value_type factory_m() { |
#ifdef PARSERTEST |
return 0; |
#else |
// https://misc.daniel-marschall.de/projects/filter_factory/symbol_m_lowercase.html |
|
int eax, ebx; |
1148,10 → 1333,15 |
eax = ((int64_t)eax * (int64_t)ebx) >> 16; |
eax += ebx; |
return eax; |
#endif |
} |
|
value_type foundry_m() { |
#ifdef PARSERTEST |
return 0; |
#else |
return foundry_c2m(var['X'] / 2 - var['x'], var['Y'] / 2 - var['y']); |
#endif |
} |
|
value_type ff_m() { |
1167,12 → 1357,20 |
/* "Y" value of the YUV color-space */ |
|
value_type factory_i() { |
#ifdef PARSERTEST |
return 0; |
#else |
return ((76L * var['r']) + (150L * var['g']) + (29L * var['b'])) / 256; // range: [0..254] |
#endif |
} |
|
value_type foundry_i() { |
#ifdef PARSERTEST |
return 0; |
#else |
// These formulas are more accurate, e.g. pure white has now i=255 instead of 254 |
return ((299L * var['r']) + (587L * var['g']) + (114L * var['b'])) / 1000; // range: [0..255] |
#endif |
} |
|
value_type ff_i() { |
1188,12 → 1386,20 |
/* "U" value of the YUV color-space */ |
|
value_type factory_u() { |
#ifdef PARSERTEST |
return 0; |
#else |
return ((-19L * var['r']) + (-37L * var['g']) + (56L * var['b'])) / 256; // range: [-55..55] |
#endif |
} |
|
value_type foundry_u() { |
#ifdef PARSERTEST |
return 0; |
#else |
// These formulas are more accurate, e.g. pure white has now i=255 instead of 254 |
return ((-147407L * var['r']) + (-289391L * var['g']) + (436798L * var['b'])) / 2000000; // range: [-55..55] |
#endif |
} |
|
value_type ff_u() { |
1209,12 → 1415,20 |
/* "V" value of the YUV color-space */ |
|
value_type factory_v() { |
#ifdef PARSERTEST |
return 0; |
#else |
return ((78L * var['r']) + (-65L * var['g']) + (-13L * var['b'])) / 256; // range: [-77..77] |
#endif |
} |
|
value_type foundry_v() { |
#ifdef PARSERTEST |
return 0; |
#else |
// These formulas are more accurate, e.g. pure white has now i=255 instead of 254 |
return ((614777L * var['r']) + (-514799L * var['g']) + (-99978L * var['b'])) / 2000000; // range: [-78..78] |
#endif |
} |
|
value_type ff_v() { |
1228,21 → 1442,42 |
// ------------------------------------------------------------------------------------------- |
|
/* get(i) Returns the current cell value at i */ |
value_type ff_get(value_type i){ |
// Filter Factory: |
//return i>=0 && i<NUM_CELLS ? cell[i] : i; |
|
// Filter Foundry: |
value_type factory_get(value_type i) { |
#ifdef PARSERTEST |
return 0; |
#else |
return i>=0 && i<NUM_CELLS ? cell[i] : i; |
#endif |
} |
|
value_type foundry_get(value_type i) { |
#ifdef PARSERTEST |
return 0; |
#else |
return i>=0 && i<NUM_CELLS ? cell[i] : 0; |
#endif |
} |
|
value_type ff_get(value_type i) { |
#ifdef use_filterfactory_implementation_get |
return factory_get(i); |
#else |
return foundry_get(i); |
#endif |
} |
|
// ------------------------------------------------------------------------------------------- |
|
/* put(v,i) Puts the new value v into cell i */ |
value_type ff_put(value_type v,value_type i){ |
#ifdef PARSERTEST |
return 0; |
#else |
if(i>=0 && i<NUM_CELLS) |
cell[i] = v; |
return v; |
#endif |
} |
|
// ------------------------------------------------------------------------------------------- |