18,8 → 18,10 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
*/ |
|
// Strict compatibility to Filter Factory |
// Tested OK! |
// Strict compatibility to Filter Factory by using an alternative |
// implementation which is a 100% replica of the Filter Factory 3.0.4 |
// for Windows. |
#ifdef WIN_ENV |
#define use_filterfactory_implementation_rad |
//#define use_filterfactory_implementation_i |
//#define use_filterfactory_implementation_u |
33,12 → 35,11 |
#define use_filterfactory_implementation_sin |
#define use_filterfactory_implementation_tan |
#define use_filterfactory_implementation_sqr |
#define use_filterfactory_implementation_d |
#define use_filterfactory_implementation_m |
#define use_filterfactory_implementation_M |
#endif |
|
// Not yet implemented! |
//#define use_filterfactory_implementation_d |
//#define use_filterfactory_implementation_m |
//#define use_filterfactory_implementation_M |
|
#ifdef MAC_ENV |
#include <fp.h> |
#endif |
345,6 → 346,54 |
|
// ------------------------------------------------------------------------------------------- |
|
/* r2x(d,m) x displacement of the pixel m units away, at an angle of d, |
from an arbitrary center */ |
|
value_type factory_r2x(value_type d, value_type m) { |
// https://misc.daniel-marschall.de/projects/filter_factory/function_r2x.html |
int eax = m; |
int ebx = d; |
ebx &= 1023; |
ebx = FACTORY_COS_LOOKUP[ebx]; |
return (((int64_t)eax * (int64_t)ebx) + 8191) >> 14; |
} |
|
value_type foundry_r2x(value_type d, value_type m) { |
return (value_type)RINT(m * costab[abs(d) % COSTABSIZE]); |
} |
|
value_type ff_r2x(value_type d, value_type m) { |
#ifdef use_filterfactory_implementation_r2x |
return factory_r2x(d, m); |
#else |
return foundry_r2x(d, m); |
#endif |
} |
|
// ------------------------------------------------------------------------------------------- |
|
/* r2y(d,m) y displacement of the pixel m units away, at an angle of d, |
from an arbitrary center */ |
|
value_type factory_r2y(value_type d, value_type m) { |
// https://misc.daniel-marschall.de/projects/filter_factory/function_r2y.html |
return factory_r2x(d - 256, m); |
} |
|
value_type foundry_r2y(value_type d, value_type m) { |
return (value_type)RINT(m * costab[abs(d - 256) % COSTABSIZE]); |
} |
|
value_type ff_r2y(value_type d, value_type m) { |
#ifdef use_filterfactory_implementation_r2y |
return factory_r2y(d, m); |
#else |
return foundry_r2y(d, m); |
#endif |
} |
|
// ------------------------------------------------------------------------------------------- |
|
/* rad(d,m,z) Channel z in the source image, which is m units away, |
at an angle of d, from the center of the image */ |
|
716,11 → 765,13 |
value_type factory_sqr(value_type x) { |
// https://misc.daniel-marschall.de/projects/filter_factory/function_sqr.html |
|
int ebx = x; |
int eax, ebx, ecx; |
|
ebx = x; |
if (ebx > 1) { |
int ecx = ebx; |
ecx = ebx; |
ebx = ebx >> 1; |
int eax = 2; |
eax = 2; |
while (ebx > eax) { |
eax = ecx; |
eax /= ebx; |
842,54 → 893,111 |
|
// ------------------------------------------------------------------------------------------- |
|
/* r2x(d,m) x displacement of the pixel m units away, at an angle of d, |
from an arbitrary center */ |
/* c2d(x,y) Angle displacement of the pixel at coordinates x,y */ |
|
value_type factory_r2x(value_type d, value_type m) { |
// https://misc.daniel-marschall.de/projects/filter_factory/function_r2x.html |
int eax = m; |
int ebx = d; |
ebx &= 1023; |
ebx = FACTORY_COS_LOOKUP[ebx]; |
return (((int64_t)eax * (int64_t)ebx) + 8191) >> 14; |
value_type factory_c2d(value_type x, value_type y) { |
// https://misc.daniel-marschall.de/projects/filter_factory/function_c2d.html |
int32_t eax, ebx, ecx; |
eax = y; |
ebx = x; |
ecx = 0; |
if (eax < 0) { |
eax = -eax; |
ecx |= 4/*0b0100*/; |
} |
if (ebx < 0) { |
ebx = -ebx; |
ecx |= 3/*0b0011*/; |
} |
if (eax > ebx) { |
int tmp; |
ecx ^= 1/*0b0001*/; |
tmp = eax; |
eax = ebx; |
ebx = tmp; |
} |
if (eax > 0) { |
eax = eax << 10; |
eax /= ebx; |
if (eax != 0) { |
eax = (eax & 0xFFFF0000) | (FACTORY_C2D_LOOKUP[eax - 1] & 0xFFFF); |
eax = eax << 9; |
ebx = 205888; // 205888/65536 == pi |
eax /= ebx; |
} |
} |
if ((ecx & 1/*0b0001*/) != 0) { |
eax = -eax; |
eax += 256; |
} |
if ((ecx & 2/*0b0010*/) != 0) { |
eax += 256; |
} |
if ((ecx & 4/*0b0100*/) != 0) { |
eax = -eax; |
} |
return eax; |
} |
|
value_type foundry_r2x(value_type d, value_type m) { |
return (value_type)RINT(m * costab[abs(d) % COSTABSIZE]); |
value_type foundry_c2d(value_type x, value_type y) { |
// 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))); |
} |
|
value_type ff_r2x(value_type d,value_type m){ |
#ifdef use_filterfactory_implementation_r2x |
return factory_r2x(d,m); |
value_type ff_c2d(value_type x, value_type y) { |
#ifdef use_filterfactory_implementation_c2d |
return factory_c2d(x, y); |
#else |
return foundry_r2x(d, m); |
return foundry_c2d(x, y); |
#endif |
} |
|
// ------------------------------------------------------------------------------------------- |
|
/* r2y(d,m) y displacement of the pixel m units away, at an angle of d, |
from an arbitrary center */ |
/* c2m(x,y) Magnitude displacement of the pixel at coordinates x,y */ |
|
value_type factory_r2y(value_type d, value_type m) { |
// https://misc.daniel-marschall.de/projects/filter_factory/function_r2y.html |
return factory_r2x(d - 256, m); |
value_type factory_c2m(value_type x, value_type y) { |
// https://misc.daniel-marschall.de/projects/filter_factory/function_c2m.html |
int32_t eax, ebx; |
ebx = y < 0 ? -y : y; |
eax = x < 0 ? -x : x; |
if (eax == ebx) { |
eax = 27146; // 27146/65536 == sqrt(1)-1 |
} |
else { |
if (eax > ebx) { |
int tmp = eax; |
eax = ebx; |
ebx = tmp; |
} |
eax = eax << 10; |
eax /= ebx; |
eax = FACTORY_C2M_LOOKUP[eax]; |
} |
eax = ((int64_t)eax * (int64_t)ebx) >> 16; |
eax += ebx; |
return eax; |
} |
|
value_type foundry_r2y(value_type d, value_type m) { |
return (value_type)RINT(m * costab[abs(d - 256) % COSTABSIZE]); |
value_type foundry_c2m(value_type x, value_type y) { |
return isqrt((long)x * x + (long)y * y); |
} |
|
value_type ff_r2y(value_type d,value_type m){ |
#ifdef use_filterfactory_implementation_r2y |
return factory_r2y(d, m); |
value_type ff_c2m(value_type x, value_type y) { |
#ifdef use_filterfactory_implementation_c2m |
return factory_c2m(x, y); |
#else |
return foundry_r2y(d, m); |
return foundry_c2m(x, y); |
#endif |
} |
|
// ------------------------------------------------------------------------------------------- |
|
/* Range of angles within the image, where D is always 1024 */ |
|
value_type ff_D() { |
return 1024; |
} |
896,9 → 1004,57 |
|
// ------------------------------------------------------------------------------------------- |
|
/* Direction(angle) of the current pixel from the center of the image, |
where d is an integer between 0 and 1024 inclusive */ |
|
value_type factory_d() { |
return 0; // TODO! |
// https://misc.daniel-marschall.de/projects/filter_factory/symbol_d_lowercase.html |
|
int eax, ebx, ecx; |
const xmin = 0, ymin = 0; |
|
eax = -(var['Y'] - ymin) / 2; |
ebx = -(var['X'] - xmin) / 2; |
ecx = 0; |
eax += var['y']; |
if (eax < 0) { |
eax = -eax; |
ecx |= 4/*0b0100*/; |
} |
ebx += var['x']; |
if (ebx < 0) { |
ebx = -ebx; |
ecx |= 3/*0b0011*/; |
} |
if (eax > ebx) { |
int tmp; |
ecx ^= 1/*0b0001*/; |
tmp = eax; |
eax = ebx; |
ebx = tmp; |
} |
if (eax > 0) { |
eax = eax << 10; |
eax /= ebx; |
if (eax != 0) { // C2D_LOOKUP[-1] will never be called. Good! |
eax = (eax & 0xFFFF0000) + (FACTORY_C2D_LOOKUP[eax - 1] & 0xFFFF); |
eax = eax << 9; |
ebx = 205888; // 205888/65536 == pi |
eax /= ebx; |
} |
} |
if ((ecx & 1/*0b0001*/) != 0) { |
eax = -eax; |
eax += 256; |
} |
if ((ecx & 2/*0b0010*/) != 0) { |
eax += 256; |
} |
if ((ecx & 4/*0b0100*/) != 0) { |
eax = -eax; |
} |
return eax; |
} |
|
value_type foundry_c2d_negated(int x, int y) { |
return (value_type)RINT(TO_FFANGLE(atan2(-y, -x))); |
910,7 → 1066,7 |
// Sign of y difference is negated, as we are dealing with top-down coordinates angle is "observed" |
int x = var['X'] / 2 - var['x']; |
int y = var['Y'] / 2 - var['y']; |
return ff_c2d_negated(x, y); |
return foundry_c2d_negated(x, y); |
} |
|
value_type ff_d() { |
923,9 → 1079,33 |
|
// ------------------------------------------------------------------------------------------- |
|
/* Range of magnitudes with the image, where M is one half the diagonal size of the image */ |
|
value_type factory_M() { |
return 0; // TODO! |
// https://misc.daniel-marschall.de/projects/filter_factory/symbol_m_uppercase.html |
|
int eax, ebx; |
const int xmin = 0, ymin = 0; |
|
eax = (var['X'] - xmin) >> 1; |
ebx = (var['Y'] - ymin) >> 1; |
if (eax == ebx) { |
eax = 27146; // 27146/65536 == sqrt(1)-1 |
} |
else { |
if (eax > ebx) { |
int tmp = eax; |
eax = ebx; |
ebx = tmp; |
} |
eax = eax << 10; |
eax /= ebx; |
eax = FACTORY_C2M_LOOKUP[eax]; |
} |
eax = ((int64_t)eax * (int64_t)ebx) >> 16; |
eax += ebx; |
return eax; |
} |
|
value_type foundry_M() { |
return foundry_c2m(var['X'], var['Y']) / 2; |
941,9 → 1121,34 |
|
// ------------------------------------------------------------------------------------------- |
|
/* Distance (magnitude) from the center of the image to the current pixel */ |
|
value_type factory_m() { |
return 0; // TODO! |
// https://misc.daniel-marschall.de/projects/filter_factory/symbol_m_lowercase.html |
|
int eax, ebx; |
const int xmin = 0, ymin = 0; |
|
eax = ((xmin - var['X']) >> 1) + var['x']; |
ebx = ((ymin - var['Y']) >> 1) + var['y']; |
eax = eax < 0 ? -eax : eax; |
ebx = ebx < 0 ? -ebx : ebx; |
|
if (eax == ebx) { |
eax = 27146; // 27146/65536 == sqrt(1)-1 |
} |
else { |
if (eax > ebx) { |
int tmp = eax; |
eax = ebx; |
ebx = tmp; |
} |
eax = FACTORY_C2M_LOOKUP[1024 * eax / ebx]; |
} |
eax = ((int64_t)eax * (int64_t)ebx) >> 16; |
eax += ebx; |
return eax; |
} |
|
value_type foundry_m() { |
return foundry_c2m(var['X'] / 2 - var['x'], var['Y'] / 2 - var['y']); |
959,6 → 1164,8 |
|
// ------------------------------------------------------------------------------------------- |
|
/* "Y" value of the YUV color-space */ |
|
value_type factory_i() { |
return ((76L * var['r']) + (150L * var['g']) + (29L * var['b'])) / 256; // range: [0..254] |
} |
978,6 → 1185,8 |
|
// ------------------------------------------------------------------------------------------- |
|
/* "U" value of the YUV color-space */ |
|
value_type factory_u() { |
return ((-19L * var['r']) + (-37L * var['g']) + (56L * var['b'])) / 256; // range: [-55..55] |
} |
997,6 → 1206,8 |
|
// ------------------------------------------------------------------------------------------- |
|
/* "V" value of the YUV color-space */ |
|
value_type factory_v() { |
return ((78L * var['r']) + (-65L * var['g']) + (-13L * var['b'])) / 256; // range: [-77..77] |
} |
1016,108 → 1227,6 |
|
// ------------------------------------------------------------------------------------------- |
|
/* c2d(x,y) Angle displacement of the pixel at coordinates x,y */ |
|
value_type factory_c2d(value_type x, value_type y) { |
// https://misc.daniel-marschall.de/projects/filter_factory/function_c2d.html |
int32_t aaa, bbb, ccc; |
aaa = y; |
bbb = x; |
ccc = 0; |
if (aaa < 0) { |
aaa = -aaa; |
ccc |= 0b0100; |
} |
if (bbb < 0) { |
bbb = -bbb; |
ccc |= 0x0011; |
} |
if (aaa > bbb) { |
ccc ^= 0b0001; |
int xxx = aaa; |
aaa = bbb; |
bbb = xxx; |
} |
if (aaa > 0) { |
aaa = aaa << 10; |
aaa /= bbb; |
if (aaa != 0) { |
aaa = (aaa & 0xFFFF0000) | (FACTORY_C2D_LOOKUP[aaa - 1] & 0xFFFF); |
aaa = aaa << 9; |
bbb = 205888; // 205888/65536 == pi |
aaa /= bbb; |
} |
} |
if ((ccc & 0b0001) != 0) { |
aaa = -aaa; |
aaa += 256; |
} |
if ((ccc & 0b0010) != 0) { |
aaa += 256; |
} |
if ((ccc & 0b0100) != 0) { |
aaa = -aaa; |
} |
return aaa; |
} |
|
value_type foundry_c2d(value_type x, value_type y) { |
// 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))); |
} |
|
value_type ff_c2d(value_type x, value_type y) { |
#ifdef use_filterfactory_implementation_c2d |
return factory_c2d(x, y); |
#else |
return foundry_c2d(x, y); |
#endif |
} |
|
// ------------------------------------------------------------------------------------------- |
|
/* c2m(x,y) Magnitude displacement of the pixel at coordinates x,y */ |
|
value_type factory_c2m(value_type x, value_type y) { |
// https://misc.daniel-marschall.de/projects/filter_factory/function_c2m.html |
int32_t aaa, bbb; |
bbb = y < 0 ? -y : y; |
aaa = x < 0 ? -x : x; |
if (aaa == bbb) { |
aaa = 27146; // 27146/65536 == sqrt(1)-1 |
} |
else { |
if (aaa > bbb) { |
int xxx = aaa; |
aaa = bbb; |
bbb = xxx; |
} |
aaa = aaa << 10; |
aaa /= bbb; |
aaa = FACTORY_C2M_LOOKUP[aaa]; |
} |
aaa = ((int64_t)aaa * (int64_t)bbb) >> 16; |
aaa += bbb; |
return aaa; |
} |
|
value_type foundry_c2m(value_type x, value_type y) { |
return isqrt((long)x * x + (long)y * y); |
} |
|
value_type ff_c2m(value_type x, value_type y) { |
#ifdef use_filterfactory_implementation_c2m |
return factory_c2m(x, y); |
#else |
return foundry_c2m(x, y); |
#endif |
} |
|
// ------------------------------------------------------------------------------------------- |
|
/* get(i) Returns the current cell value at i */ |
value_type ff_get(value_type i){ |
// Filter Factory: |