Subversion Repositories filter_foundry

Compare Revisions

Regard whitespace Rev 294 → Rev 295

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