Subversion Repositories filter_foundry

Compare Revisions

Regard whitespace Rev 296 → Rev 297

/trunk/funcs.c
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
}
 
// -------------------------------------------------------------------------------------------