Skip to content

Commit

Permalink
波浪C实现
Browse files Browse the repository at this point in the history
  • Loading branch information
cedricporter committed Jul 30, 2012
1 parent 4876da0 commit 9b7efa9
Show file tree
Hide file tree
Showing 3 changed files with 211 additions and 26 deletions.
8 changes: 7 additions & 1 deletion EffectLab/Effect.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import math, operator
from math import sqrt, sin, cos, atan2

# 尝试加载C语言实现的部分
try:
import EffectLabCore as core
except:
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
220 changes: 198 additions & 22 deletions EffectLab/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
Expand All @@ -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); */

/* ------------------------- */

Expand All @@ -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)
{
Expand All @@ -188,11 +353,22 @@ 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}
};

PyMODINIT_FUNC initEffectLabCore()
{
Py_InitModule("EffectLabCore", CoreMethods);
}









9 changes: 6 additions & 3 deletions TestEffectLab.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)),
]
Expand Down Expand Up @@ -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()

0 comments on commit 9b7efa9

Please sign in to comment.