diff --git a/EffectLab/Effect.py b/EffectLab/Effect.py index 14cfe7f..df946cd 100755 --- a/EffectLab/Effect.py +++ b/EffectLab/Effect.py @@ -14,6 +14,7 @@ import math, operator from math import sqrt, sin, cos, atan2 +# 尝试加载C语言实现的部分 try: import EffectLabCore as core except: @@ -209,7 +210,7 @@ def filter(self, img): ''' try: - return core.global_warp(img) + return core.lens_warp(img, self.formula, self.antialias) except: pass @@ -260,6 +261,8 @@ def __init__(self, formula, antialias=2): self.antialias = antialias def filter(self, img): + return core.radian_warp(img, self.formula, self.antialias) + def radian_formula(x, y): '''transform formula func is a function that like f(r, phi) => (r, phi) @@ -299,6 +302,9 @@ def transform(self, x, y, width, height, delta_w, delta_h): return x, y + offset def filter(self, img): + return core.wave_warp(img, self.dw, self.dh, self.antialias) + + width, height = img.size f = lambda x, y: self.transform(x, y, width, height, self.dw, self.dh) warp = RegionWarpEffect(f, self.antialias) diff --git a/EffectLab/core.c b/EffectLab/core.c index d6eab86..28fda2f 100644 --- a/EffectLab/core.c +++ b/EffectLab/core.c @@ -65,31 +65,64 @@ typedef struct { } ImagingObject; -static PyObject* global_warp(PyObject *self, PyObject *args) +static int _radian_warp(PyObject *func, double x, double y, double *xnew, double *ynew) +{ + double phi,radius,radius2; + PyObject *ret; + + radius2 = x * x + y * y; + radius = sqrt(radius2); + phi = atan2(y, x); + + if ((ret = PyObject_CallFunction(func, "dd", radius, phi)) == NULL) + { + return 0; + } + if (!PyArg_ParseTuple(ret, "dd", &radius, &phi)) + { + return 0; + } + + *xnew = radius * cos(phi); + *ynew = radius * sin(phi); + + return 1; +} + +static int _xy_warp(PyObject *func, double x, double y, double *xnew, double *ynew) +{ + PyObject *ret; + if ((ret = PyObject_CallFunction(func, "dd", x, y)) == NULL) + { + return 0; + } + if (!PyArg_ParseTuple(ret, "dd", xnew, ynew)) + { + return 0; + } + + return 1; +} + +/* 镜头变形效果 */ +static PyObject* _lens_warp(PyObject *self, PyObject *args, int (*warp)(PyObject*, double, double, double *, double*)) { - const char *text; - int result; PyObject *image; PyObject *newimage; ImagingObject *core; Imaging imIn, imOut; int i, j, ai, aj; int found, rsum, gsum, bsum, asum; - int antialias; + int antialias = 2; double xx, yy; int width, height; double i2, j2; double xnew, ynew; - int index; - UINT8 *pixel; - - double phi,radius,radius2; - double xtmp,ytmp; - double denom; + UINT8 *pixel; int i3, j3; + PyObject *func, *ret; - - if (!PyArg_ParseTuple(args, "O", &image)) + if (!PyArg_ParseTuple(args, "OOi", &image, &func, &antialias)) { return NULL; } @@ -111,9 +144,10 @@ static PyObject* global_warp(PyObject *self, PyObject *args) width = imIn->xsize; height = imIn->ysize; - antialias = 4; - for (j = 0; j < height; j++) { - for (i = 0; i < width; i++) { + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { found = 0; rsum = 0; gsum = 0; @@ -139,13 +173,24 @@ static PyObject* global_warp(PyObject *self, PyObject *args) ynew = yy; /* ----------- */ - radius2 = xx * xx + yy * yy; - radius = sqrt(radius2); - phi = atan2(yy, xx); + warp(func, xx, yy, &xnew, &ynew); + + /* if ((ret = PyObject_CallFunction(func, "dd", xx, yy)) == NULL) */ + /* { */ + /* return NULL; */ + /* } */ + /* if (!PyArg_ParseTuple(ret, "dd", &xnew, &ynew)) */ + /* { */ + /* return NULL; */ + /* } */ - radius = sqrt(radius); - xnew = radius * cos(phi); - ynew = radius * sin(phi); + /* radius2 = xx * xx + yy * yy; */ + /* radius = sqrt(radius2); */ + /* phi = atan2(yy, xx); */ + + /* radius = sqrt(radius); */ + /* xnew = radius * cos(phi); */ + /* ynew = radius * sin(phi); */ /* ------------------------- */ @@ -171,6 +216,126 @@ static PyObject* global_warp(PyObject *self, PyObject *args) } } + if (found > 0) + { + pixel = imOut->image[j]; + pixel += i * 4; + pixel[0] = rsum / found; + pixel[1] = gsum / found; + pixel[2] = bsum / found; + pixel[3] = asum / found; + } + } + } + + return (PyObject *)newimage; +} + +static PyObject* lens_warp(PyObject *self, PyObject *args) +{ + return _lens_warp(self, args, _xy_warp); +} + +static PyObject* radian_warp(PyObject *self, PyObject *args) +{ + return _lens_warp(self, args, _radian_warp); +} + +static PyObject* wave_warp(PyObject *self, PyObject *args) +{ + PyObject *image; + PyObject *newimage; + ImagingObject *core; + Imaging imIn, imOut; + int i, j, ai, aj; + int found, rsum, gsum, bsum, asum; + int antialias = 2; + double xx, yy; + int width, height; + double i2, j2; + double xnew, ynew; + UINT8 *pixel; + int i3, j3; + PyObject *ret; + double dw = 1, dh=0.3; + double radian; + double offset; + + if (!PyArg_ParseTuple(args, "Oddi", &image, &dw, &dh, &antialias)) + { + return NULL; + } + + if ((core = (ImagingObject *)PyObject_GetAttrString(image, "im")) == NULL) + { + return NULL; + } + imIn = core->image; + + /* copy a new image */ + newimage = PyObject_CallMethod(image, "copy", NULL); + if ((core = (ImagingObject *)PyObject_GetAttrString(newimage, "im")) == NULL) + { + return NULL; + } + imOut = core->image; + + width = imIn->xsize; + height = imIn->ysize; + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + found = 0; + rsum = 0; + gsum = 0; + bsum = 0; + asum = 0; + + pixel = imOut->image[j]; + pixel += i * 4; + pixel[0] = 128; + pixel[1] = 128; + pixel[2] = 128; + pixel[3] = 128; + + for (ai = 0; ai < antialias; ai++) + { + xx = i + ai / (double)antialias; + + for (aj = 0; aj < antialias; aj++) + { + yy = j + aj / (double)antialias; + + /* ------------------------- */ + radian = 2 * 3.14159265 * xx / (double)width * dw; + offset = 0.5 * sin(radian) * height * dh; + + xnew = xx; + ynew = yy + offset; + + /* ------------------------- */ + + i3 = round(xnew); + j3 = round(ynew); + /* printf("%d %d %d %d\n", i, j, i3, j3); */ + + if (i3 < 0 || i3 >= width || j3 < 0 || j3 >= height) + { + continue; + } + + pixel = (UINT8*)imIn->image[j3]; + pixel += i3 * 4; + + rsum += pixel[0]; + gsum += pixel[1]; + bsum += pixel[2]; + asum += pixel[3]; + found++; + } + } if (found > 0) { @@ -188,7 +353,9 @@ static PyObject* global_warp(PyObject *self, PyObject *args) } static PyMethodDef CoreMethods[] = { - {"global_warp", global_warp, METH_VARARGS, "Global warp"}, + {"lens_warp", lens_warp, METH_VARARGS, "Global warp"}, + {"radian_warp", radian_warp, METH_VARARGS, "Radian Warp"}, + {"wave_warp", wave_warp, METH_VARARGS, "Wave"}, {NULL, NULL, 0, NULL} }; @@ -196,3 +363,12 @@ PyMODINIT_FUNC initEffectLabCore() { Py_InitModule("EffectLabCore", CoreMethods); } + + + + + + + + + diff --git a/TestEffectLab.py b/TestEffectLab.py index 331eb3a..fd090cd 100755 --- a/TestEffectLab.py +++ b/TestEffectLab.py @@ -38,12 +38,14 @@ def __init__(self, img): def main(): print 'Started' + os.system('mkdir tmp') + effects = [ # LocalWarpEffect((50, 20), (80, 40), 30), - RadianSqrtEffect(), + # RadianSqrtEffect(), # LensWarpEffect(lambda x, y: (sign(x) * x ** 2, sign(y) * y ** 2)), # RadianFormulaEffect(lambda r, phi: (r ** 2, phi), 4), - # GlobalWaveEffect(), + GlobalWaveEffect(1, 0.5), # LensWarpEffect(lambda x, y: (sin(x * math.pi / 2), sin(y * math.pi / 2))), # RadianFormulaEffect(lambda r, phi: (r ** 1.5 * math.cos(r), phi)), ] @@ -78,12 +80,13 @@ def main(): offset += char_img[last].width - 1 for index, effect in enumerate(effects): - for i in xrange(100): + for i in xrange(1): merge_origin_and_new(img, effect).save('tmp/%d-%d.jpg' % (index, i), quality=90) print '.', print 'done' if __name__ == '__main__': + os.system('rm tmp/*') # autoreload.main(main) main()