/* * The Python Imaging Library * * a simple math add-on for the Python Imaging Library * * history: * 1999-02-15 fl Created * 2005-05-05 fl Simplified and cleaned up for PIL 1.1.6 * * Copyright (c) 1999-2005 by Secret Labs AB * Copyright (c) 2005 by Fredrik Lundh * * See the README file for information on usage and redistribution. */ #include "Python.h" #include "Imaging.h" #include "py3.h" #include "math.h" #include "float.h" #define MAX_INT32 2147483647.0 #define MIN_INT32 -2147483648.0 #if defined(_MSC_VER) && _MSC_VER < 1500 /* python 2.1/2.2/2.3 = VC98 = VER 1200 */ /* python 2.4/2.5 = VS.NET 2003 = VER 1310 */ /* python 2.6 = VS 9.0 = VER 1500 */ #define powf(a, b) ((float) pow((double) (a), (double) (b))) #endif #define UNOP(name, op, type)\ void name(Imaging out, Imaging im1)\ {\ int x, y;\ for (y = 0; y < out->ysize; y++) {\ type* p0 = (type*) out->image[y];\ type* p1 = (type*) im1->image[y];\ for (x = 0; x < out->xsize; x++) {\ *p0 = op(type, *p1);\ p0++; p1++;\ }\ }\ } #define BINOP(name, op, type)\ void name(Imaging out, Imaging im1, Imaging im2)\ {\ int x, y;\ for (y = 0; y < out->ysize; y++) {\ type* p0 = (type*) out->image[y];\ type* p1 = (type*) im1->image[y];\ type* p2 = (type*) im2->image[y];\ for (x = 0; x < out->xsize; x++) {\ *p0 = op(type, *p1, *p2);\ p0++; p1++; p2++;\ }\ }\ } #define NEG(type, v1) -(v1) #define INVERT(type, v1) ~(v1) #define ADD(type, v1, v2) (v1)+(v2) #define SUB(type, v1, v2) (v1)-(v2) #define MUL(type, v1, v2) (v1)*(v2) #define MIN(type, v1, v2) ((v1)<(v2))?(v1):(v2) #define MAX(type, v1, v2) ((v1)>(v2))?(v1):(v2) #define AND(type, v1, v2) (v1)&(v2) #define OR(type, v1, v2) (v1)|(v2) #define XOR(type, v1, v2) (v1)^(v2) #define LSHIFT(type, v1, v2) (v1)<<(v2) #define RSHIFT(type, v1, v2) (v1)>>(v2) #define ABS_I(type, v1) abs((v1)) #define ABS_F(type, v1) fabs((v1)) /* -------------------------------------------------------------------- * some day, we should add FPE protection mechanisms. see pyfpe.h for * details. * * PyFPE_START_PROTECT("Error in foobar", return 0) * PyFPE_END_PROTECT(result) */ #define DIV_I(type, v1, v2) ((v2)!=0)?(v1)/(v2):0 #define DIV_F(type, v1, v2) ((v2)!=0.0F)?(v1)/(v2):0.0F #define MOD_I(type, v1, v2) ((v2)!=0)?(v1)%(v2):0 #define MOD_F(type, v1, v2) ((v2)!=0.0F)?fmod((v1),(v2)):0.0F static int powi(int x, int y) { double v = pow(x, y) + 0.5; if (errno == EDOM) return 0; if (v < MIN_INT32) v = MIN_INT32; else if (v > MAX_INT32) v = MAX_INT32; return (int) v; } #define POW_I(type, v1, v2) powi(v1, v2) #define POW_F(type, v1, v2) powf(v1, v2) /* FIXME: EDOM handling */ #define DIFF_I(type, v1, v2) abs((v1)-(v2)) #define DIFF_F(type, v1, v2) fabs((v1)-(v2)) #define EQ(type, v1, v2) (v1)==(v2) #define NE(type, v1, v2) (v1)!=(v2) #define LT(type, v1, v2) (v1)<(v2) #define LE(type, v1, v2) (v1)<=(v2) #define GT(type, v1, v2) (v1)>(v2) #define GE(type, v1, v2) (v1)>=(v2) UNOP(abs_I, ABS_I, INT32) UNOP(neg_I, NEG, INT32) BINOP(add_I, ADD, INT32) BINOP(sub_I, SUB, INT32) BINOP(mul_I, MUL, INT32) BINOP(div_I, DIV_I, INT32) BINOP(mod_I, MOD_I, INT32) BINOP(pow_I, POW_I, INT32) BINOP(diff_I, DIFF_I, INT32) UNOP(invert_I, INVERT, INT32) BINOP(and_I, AND, INT32) BINOP(or_I, OR, INT32) BINOP(xor_I, XOR, INT32) BINOP(lshift_I, LSHIFT, INT32) BINOP(rshift_I, RSHIFT, INT32) BINOP(min_I, MIN, INT32) BINOP(max_I, MAX, INT32) BINOP(eq_I, EQ, INT32) BINOP(ne_I, NE, INT32) BINOP(lt_I, LT, INT32) BINOP(le_I, LE, INT32) BINOP(gt_I, GT, INT32) BINOP(ge_I, GE, INT32) UNOP(abs_F, ABS_F, FLOAT32) UNOP(neg_F, NEG, FLOAT32) BINOP(add_F, ADD, FLOAT32) BINOP(sub_F, SUB, FLOAT32) BINOP(mul_F, MUL, FLOAT32) BINOP(div_F, DIV_F, FLOAT32) BINOP(mod_F, MOD_F, FLOAT32) BINOP(pow_F, POW_F, FLOAT32) BINOP(diff_F, DIFF_F, FLOAT32) BINOP(min_F, MIN, FLOAT32) BINOP(max_F, MAX, FLOAT32) BINOP(eq_F, EQ, FLOAT32) BINOP(ne_F, NE, FLOAT32) BINOP(lt_F, LT, FLOAT32) BINOP(le_F, LE, FLOAT32) BINOP(gt_F, GT, FLOAT32) BINOP(ge_F, GE, FLOAT32) static PyObject * _unop(PyObject* self, PyObject* args) { Imaging out; Imaging im1; void (*unop)(Imaging, Imaging); long op, i0, i1; if (!PyArg_ParseTuple(args, "lll", &op, &i0, &i1)) return NULL; out = (Imaging) i0; im1 = (Imaging) i1; unop = (void*) op; unop(out, im1); Py_INCREF(Py_None); return Py_None; } static PyObject * _binop(PyObject* self, PyObject* args) { Imaging out; Imaging im1; Imaging im2; void (*binop)(Imaging, Imaging, Imaging); long op, i0, i1, i2; if (!PyArg_ParseTuple(args, "llll", &op, &i0, &i1, &i2)) return NULL; out = (Imaging) i0; im1 = (Imaging) i1; im2 = (Imaging) i2; binop = (void*) op; binop(out, im1, im2); Py_INCREF(Py_None); return Py_None; } static PyMethodDef _functions[] = { {"unop", _unop, 1}, {"binop", _binop, 1}, {NULL, NULL} }; static void install(PyObject *d, char* name, void* value) { PyObject *v = PyInt_FromLong((long) value); if (!v || PyDict_SetItemString(d, name, v)) PyErr_Clear(); Py_XDECREF(v); } static int setup_module(PyObject* m) { PyObject* d = PyModule_GetDict(m); install(d, "abs_I", abs_I); install(d, "neg_I", neg_I); install(d, "add_I", add_I); install(d, "sub_I", sub_I); install(d, "diff_I", diff_I); install(d, "mul_I", mul_I); install(d, "div_I", div_I); install(d, "mod_I", mod_I); install(d, "min_I", min_I); install(d, "max_I", max_I); install(d, "pow_I", pow_I); install(d, "invert_I", invert_I); install(d, "and_I", and_I); install(d, "or_I", or_I); install(d, "xor_I", xor_I); install(d, "lshift_I", lshift_I); install(d, "rshift_I", rshift_I); install(d, "eq_I", eq_I); install(d, "ne_I", ne_I); install(d, "lt_I", lt_I); install(d, "le_I", le_I); install(d, "gt_I", gt_I); install(d, "ge_I", ge_I); install(d, "abs_F", abs_F); install(d, "neg_F", neg_F); install(d, "add_F", add_F); install(d, "sub_F", sub_F); install(d, "diff_F", diff_F); install(d, "mul_F", mul_F); install(d, "div_F", div_F); install(d, "mod_F", mod_F); install(d, "min_F", min_F); install(d, "max_F", max_F); install(d, "pow_F", pow_F); install(d, "eq_F", eq_F); install(d, "ne_F", ne_F); install(d, "lt_F", lt_F); install(d, "le_F", le_F); install(d, "gt_F", gt_F); install(d, "ge_F", ge_F); return 0; } #if PY_VERSION_HEX >= 0x03000000 PyMODINIT_FUNC PyInit__imagingmath(void) { PyObject* m; static PyModuleDef module_def = { PyModuleDef_HEAD_INIT, "_imagingmath", /* m_name */ NULL, /* m_doc */ -1, /* m_size */ _functions, /* m_methods */ }; m = PyModule_Create(&module_def); if (setup_module(m) < 0) return NULL; return m; } #else PyMODINIT_FUNC init_imagingmath(void) { PyObject* m = Py_InitModule("_imagingmath", _functions); setup_module(m); } #endif