Skip to content

Commit

Permalink
C语言实现了部分库。
Browse files Browse the repository at this point in the history
  • Loading branch information
cedricporter committed Jul 29, 2012
1 parent 34dc3c6 commit 4876da0
Show file tree
Hide file tree
Showing 5 changed files with 296 additions and 8 deletions.
11 changes: 11 additions & 0 deletions EffectLab/Effect.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
import math, operator
from math import sqrt, sin, cos, atan2

try:
import EffectLabCore as core
except:
pass

# Effect是特效处理流程中的过滤器,输入PIL中的Image,然后输出处理好的Image
# 其中,()是经过重载的,默认调用成员函数filter(img)。这样可以方便的与其他普通过滤器函数组合在一起。
#
Expand Down Expand Up @@ -202,6 +207,12 @@ def filter(self, img):
'''Effect Kernel of radius based Effect.
@param formula is a function like f(x, y) => (x', y'), -1 <= x <= 1 and -1 <= y <= 1
'''

try:
return core.global_warp(img)
except:
pass

width, height = img.size
nx, ny = width, height
new_img = img.copy()
Expand Down
72 changes: 72 additions & 0 deletions EffectLab/ImPlatform.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* The Python Imaging Library
* $Id$
*
* platform declarations for the imaging core library
*
* Copyright (c) Fredrik Lundh 1995-2003.
*/

#include "Python.h"

/* Check that we have an ANSI compliant compiler */
#ifndef HAVE_PROTOTYPES
#error Sorry, this library requires support for ANSI prototypes.
#endif
#ifndef STDC_HEADERS
#error Sorry, this library requires ANSI header files.
#endif

#if defined(_MSC_VER)
#ifndef WIN32
#define WIN32
#endif
/* VC++ 4.0 is a bit annoying when it comes to precision issues (like
claiming that "float a = 0.0;" would lead to loss of precision). I
don't like to see warnings from my code, but since I still want to
keep it readable, I simply switch off a few warnings instead of adding
the tons of casts that VC++ seem to require. This code is compiled
with numerous other compilers as well, so any real errors are likely
to be catched anyway. */
#pragma warning(disable: 4244) /* conversion from 'float' to 'int' */
#endif

#if defined(_MSC_VER)
#define inline __inline
#elif !defined(USE_INLINE)
#define inline
#endif

#if SIZEOF_SHORT == 2
#define INT16 short
#elif SIZEOF_INT == 2
#define INT16 int
#else
#define INT16 short /* most things works just fine anyway... */
#endif

#if SIZEOF_SHORT == 4
#define INT32 short
#elif SIZEOF_INT == 4
#define INT32 int
#elif SIZEOF_LONG == 4
#define INT32 long
#else
#error Cannot find required 32-bit integer type
#endif

#if SIZEOF_LONG == 8
#define INT64 long
#elif SIZEOF_LONG_LONG == 8
#define INT64 long
#endif

/* assume IEEE; tweak if necessary (patches are welcome) */
#define FLOAT32 float
#define FLOAT64 double

#define INT8 signed char
#define UINT8 unsigned char

#define UINT16 unsigned INT16
#define UINT32 unsigned INT32
5 changes: 5 additions & 0 deletions EffectLab/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
EffectLabCore.so: core.c
gcc -I/usr/include/python2.7 -fPIC -shared core.c -o EffectLabCore.so

clean:
rm *.so
198 changes: 198 additions & 0 deletions EffectLab/core.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
#include <Python.h>
#include <stdio.h>
#include <math.h>
#include "ImPlatform.h"

/* 1.9.1 pil */

typedef struct ImagingMemoryInstance* Imaging;
typedef struct ImagingAccessInstance* ImagingAccess;
typedef struct ImagingPaletteInstance* ImagingPalette;

struct ImagingMemoryInstance {

/* Format */
char mode[6+1]; /* Band names ("1", "L", "P", "RGB", "RGBA", "CMYK", "YCbCr", "BGR;xy") */
int type; /* Data type (IMAGING_TYPE_*) */
int depth; /* Depth (ignored in this version) */
int bands; /* Number of bands (1, 2, 3, or 4) */
int xsize; /* Image dimension. */
int ysize;

/* Colour palette (for "P" images only) */
ImagingPalette palette;

/* Data pointers */
UINT8 **image8; /* Set for 8-bit images (pixelsize=1). */
INT32 **image32; /* Set for 32-bit images (pixelsize=4). */

/* Internals */
char **image; /* Actual raster data. */
char *block; /* Set if data is allocated in a single block. */

int pixelsize; /* Size of a pixel, in bytes (1, 2 or 4) */
int linesize; /* Size of a line, in bytes (xsize * pixelsize) */

/* Virtual methods */
void (*destroy)(Imaging im);
};


struct ImagingAccessInstance {
const char* mode;
void* (*line)(Imaging im, int i, int j);
void (*get_pixel)(Imaging im, int i, int j, void* pixel);
void (*put_pixel)(Imaging im, int i, int j, const void* pixel);
};

struct ImagingPaletteInstance {

/* Format */
char mode[4+1]; /* Band names */

/* Data */
UINT8 palette[1024];/* Palette data (same format as image data) */

INT16* cache; /* Palette cache (used for predefined palettes) */
int keep_cache; /* This palette will be reused; keep cache */

};

typedef struct {
PyObject_HEAD
Imaging image;
ImagingAccess access;
} ImagingObject;


static PyObject* global_warp(PyObject *self, PyObject *args)
{
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;
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;
int i3, j3;


if (!PyArg_ParseTuple(args, "O", &image))
{
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;

antialias = 4;
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 = 2.0 * (i + ai / (double)antialias) / width - 1;

for (aj = 0; aj < antialias; aj++)
{
yy = 2.0 * (j + aj / (double)antialias) / height - 1;

xnew = xx;
ynew = yy;

/* ----------- */
radius2 = xx * xx + yy * yy;
radius = sqrt(radius2);
phi = atan2(yy, xx);

radius = sqrt(radius);
xnew = radius * cos(phi);
ynew = radius * sin(phi);

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

i2 = 0.5 * width * (xnew + 1);
j2 = 0.5 * height * (ynew + 1);

i3 = round(i2);
j3 = round(j2);

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)
{
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 PyMethodDef CoreMethods[] = {
{"global_warp", global_warp, METH_VARARGS, "Global warp"},
{NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC initEffectLabCore()
{
Py_InitModule("EffectLabCore", CoreMethods);
}
18 changes: 10 additions & 8 deletions TestEffectLab.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ def main():
print 'Started'

effects = [
LocalWarpEffect((50, 20), (80, 40), 30),
# LocalWarpEffect((50, 20), (80, 40), 30),
RadianSqrtEffect(),
LensWarpEffect(lambda x, y: (sign(x) * x ** 2, sign(y) * y ** 2)),
RadianFormulaEffect(lambda r, phi: (r ** 2, phi), 4),
GlobalWaveEffect(),
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)),
# LensWarpEffect(lambda x, y: (sign(x) * x ** 2, sign(y) * y ** 2)),
# RadianFormulaEffect(lambda r, phi: (r ** 2, phi), 4),
# GlobalWaveEffect(),
# 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)),
]

# if os.path.exists('z.jpg'):
Expand Down Expand Up @@ -78,10 +78,12 @@ def main():
offset += char_img[last].width - 1

for index, effect in enumerate(effects):
merge_origin_and_new(img, effect).save('%d.jpg' % index, quality=90)
for i in xrange(100):
merge_origin_and_new(img, effect).save('tmp/%d-%d.jpg' % (index, i), quality=90)
print '.',
print 'done'


if __name__ == '__main__':
autoreload.main(main)
# autoreload.main(main)
main()

0 comments on commit 4876da0

Please sign in to comment.