From 0446e89bfeca59e587529d27e43fe0b883259dd4 Mon Sep 17 00:00:00 2001 From: Virgil Dupras Date: Sun, 31 Jan 2010 10:27:59 +0100 Subject: [PATCH] Converted core_pe's "block" module from Cython to C. --- .hgignore | 1 - core_pe/modules/block/block.c | 277 ++++++++++++++++++++++++++++++++ core_pe/modules/block/block.pyx | 96 ----------- core_pe/modules/block/setup.py | 4 +- 4 files changed, 278 insertions(+), 100 deletions(-) create mode 100644 core_pe/modules/block/block.c delete mode 100644 core_pe/modules/block/block.pyx diff --git a/.hgignore b/.hgignore index a7e41fd4..fda43040 100644 --- a/.hgignore +++ b/.hgignore @@ -8,7 +8,6 @@ syntax: glob *.tm_build_errors conf.yaml build -core_pe/modules/block/block.c cocoa/*/Info.plist cocoa/*/build cocoa/*/dg_cocoa.plugin diff --git a/core_pe/modules/block/block.c b/core_pe/modules/block/block.c new file mode 100644 index 00000000..968d7ae7 --- /dev/null +++ b/core_pe/modules/block/block.c @@ -0,0 +1,277 @@ +/* Created By: Virgil Dupras + * Created On: 2010-01-30 + * Copyright 2010 Hardcoded Software (http://www.hardcoded.net) + */ + +#define PY_SSIZE_T_CLEAN +#include "Python.h" + +/* avgdiff/maxdiff has been called with empty lists */ +static PyObject *NoBlocksError; +/* avgdiff/maxdiff has been called with 2 block lists of different size. */ +static PyObject *DifferentBlockCountError; + +static inline int +max(int a, int b) +{ + return b > a ? b : a; +} + +static inline int +min(int a, int b) +{ + return b < a ? b : a; +} + +/* Create a tuple out of an array of integers. */ +static PyObject* +inttuple(int numbers[], int count) +{ + int i; + PyObject *pnumber; + PyObject *result; + + result = PyTuple_New(count); + + for (i=0; i limit*iteration_count) && (iteration_count >= min_iterations)) { + return PyInt_FromSsize_t(limit + 1); + } + } + + result = sum / count; + if (!result && sum) { + result = 1; + } + return PyInt_FromSsize_t(result); +} + +static PyMethodDef BlockMethods[] = { + {"getblocks2", block_getblocks2, METH_VARARGS, block_getblocks2_doc}, + {"avgdiff", block_avgdiff, METH_VARARGS, block_avgdiff_doc}, + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + +PyMODINIT_FUNC +init_block(void) +{ + PyObject *m = Py_InitModule("_block", BlockMethods); + if (m == NULL) { + return; + } + + NoBlocksError = PyErr_NewException("_block.NoBlocksError", NULL, NULL); + PyModule_AddObject(m, "NoBlocksError", NoBlocksError); + DifferentBlockCountError = PyErr_NewException("_block.DifferentBlockCountError", NULL, NULL); + PyModule_AddObject(m, "DifferentBlockCountError", DifferentBlockCountError); +} \ No newline at end of file diff --git a/core_pe/modules/block/block.pyx b/core_pe/modules/block/block.pyx deleted file mode 100644 index eb7a5758..00000000 --- a/core_pe/modules/block/block.pyx +++ /dev/null @@ -1,96 +0,0 @@ -# Created By: Virgil Dupras -# Created On: 2009-04-23 -# Copyright 2010 Hardcoded Software (http://www.hardcoded.net) -# -# This software is licensed under the "HS" License as described in the "LICENSE" file, -# which should be included with this package. The terms are also available at -# http://www.hardcoded.net/licenses/hs_license - -cdef extern from "stdlib.h": - int abs(int n) # required so that abs() is applied on ints, not python objects - -class NoBlocksError(Exception): - """avgdiff/maxdiff has been called with empty lists""" - -class DifferentBlockCountError(Exception): - """avgdiff/maxdiff has been called with 2 block lists of different size.""" - - -cdef object getblock(object image): - """Returns a 3 sized tuple containing the mean color of 'image'. - - image: a PIL image or crop. - """ - cdef int pixel_count, red, green, blue, r, g, b - if image.size[0]: - pixel_count = image.size[0] * image.size[1] - red = green = blue = 0 - for r, g, b in image.getdata(): - red += r - green += g - blue += b - return (red // pixel_count, green // pixel_count, blue // pixel_count) - else: - return (0, 0, 0) - -def getblocks2(image, int block_count_per_side): - """Returns a list of blocks (3 sized tuples). - - image: A PIL image to base the blocks on. - block_count_per_side: This integer determine the number of blocks the function will return. - If it is 10, for example, 100 blocks will be returns (10 width, 10 height). The blocks will not - necessarely cover square areas. The area covered by each block will be proportional to the image - itself. - """ - if not image.size[0]: - return [] - cdef int width, height, block_width, block_height, ih, iw, top, bottom, left, right - width, height = image.size - block_width = max(width // block_count_per_side, 1) - block_height = max(height // block_count_per_side, 1) - result = [] - for ih in range(block_count_per_side): - top = min(ih * block_height, height - block_height) - bottom = top + block_height - for iw in range(block_count_per_side): - left = min(iw * block_width, width - block_width) - right = left + block_width - box = (left, top, right, bottom) - crop = image.crop(box) - result.append(getblock(crop)) - return result - -cdef int diff(first, second): - """Returns the difference between the first block and the second. - - It returns an absolute sum of the 3 differences (RGB). - """ - cdef int r1, g1, b1, r2, g2, b2 - r1, g1, b1 = first - r2, g2, b2 = second - return abs(r1 - r2) + abs(g1 - g2) + abs(b1 - b2) - -def avgdiff(first, second, int limit, int min_iterations): - """Returns the average diff between first blocks and seconds. - - If the result surpasses limit, limit + 1 is returned, except if less than min_iterations - iterations have been made in the blocks. - """ - cdef int count, sum, i, iteration_count - count = len(first) - if count != len(second): - raise DifferentBlockCountError() - if not count: - raise NoBlocksError() - sum = 0 - for i in range(count): - iteration_count = i + 1 - item1 = first[i] - item2 = second[i] - sum += diff(item1, item2) - if sum > limit * iteration_count and iteration_count >= min_iterations: - return limit + 1 - result = sum // count - if (not result) and sum: - result = 1 - return result \ No newline at end of file diff --git a/core_pe/modules/block/setup.py b/core_pe/modules/block/setup.py index 9502488a..97a95657 100644 --- a/core_pe/modules/block/setup.py +++ b/core_pe/modules/block/setup.py @@ -8,9 +8,7 @@ from distutils.core import setup from distutils.extension import Extension -from Cython.Distutils import build_ext setup( - cmdclass = {'build_ext': build_ext}, - ext_modules = [Extension("_block", ["block.pyx"])] + ext_modules = [Extension("_block", ["block.c"])] ) \ No newline at end of file