0

added a fast resize function

Added resize_half() and resize_half_wrap() functions to composite.c and
overviewer.h, to replace the call to PIL's resize function made by
tileset.py. Also added "resize_half" to COverviewerMethods in main.c, so
it can be called from Python. Should increase performance by 10 to 20%
for the entire program.
This commit is contained in:
RamsesA
2012-07-03 20:26:23 -04:00
parent c79a646d10
commit 2b421d6d25
4 changed files with 165 additions and 3 deletions

View File

@@ -23,6 +23,7 @@
*/ */
#include "overviewer.h" #include "overviewer.h"
#include <stdio.h>
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
@@ -489,3 +490,154 @@ draw_triangle(PyObject *dest, int inclusive,
return dest; return dest;
} }
/* scales the image to half size
*/
inline PyObject *
resize_half(PyObject *dest, PyObject *src) {
/* libImaging handles */
Imaging imDest, imSrc;
/* alpha properties */
int src_has_alpha, dest_has_alpha;
/* iteration variables */
unsigned int x, y;
/* temp color variables */
unsigned int r, g, b, a;
/* size values for source and destination */
int src_width, src_height, dest_width, dest_height;
imDest = imaging_python_to_c(dest);
imSrc = imaging_python_to_c(src);
if (!imDest || !imSrc)
return NULL;
/* check the various image modes, make sure they make sense */
if (strcmp(imDest->mode, "RGBA") != 0) {
PyErr_SetString(PyExc_ValueError,
"given destination image does not have mode \"RGBA\"");
return NULL;
}
if (strcmp(imSrc->mode, "RGBA") != 0 && strcmp(imSrc->mode, "RGB") != 0) {
PyErr_SetString(PyExc_ValueError,
"given source image does not have mode \"RGBA\" or \"RGB\"");
return NULL;
}
src_width = imSrc->xsize;
src_height = imSrc->ysize;
dest_width = imDest->xsize;
dest_height = imDest->ysize;
/* make sure destination size is 1/2 src size */
if (src_width / 2 != dest_width || src_height / 2 != dest_height) {
PyErr_SetString(PyExc_ValueError,
"destination image size is not one-half source image size");
return NULL;
}
/* set up flags for the src/mask type */
src_has_alpha = (imSrc->pixelsize == 4 ? 1 : 0);
dest_has_alpha = (imDest->pixelsize == 4 ? 1 : 0);
/* check that there remains anything to resize */
if (dest_width <= 0 || dest_height <= 0) {
/* nothing to do, return */
return dest;
}
/* set to fully opaque if source has no alpha channel */
if(!src_has_alpha)
a = 0xFF << 2;
for (y = 0; y < dest_height; y++) {
UINT8 *out = (UINT8 *)imDest->image[y];
UINT8 *in_row1 = (UINT8 *)imSrc->image[y * 2];
UINT8 *in_row2 = (UINT8 *)imSrc->image[y * 2 + 1];
for (x = 0; x < dest_width; x++) {
// read first column
r = *in_row1;
r += *in_row2;
in_row1++;
in_row2++;
g = *in_row1;
g += *in_row2;
in_row1++;
in_row2++;
b = *in_row1;
b += *in_row2;
in_row1++;
in_row2++;
if (src_has_alpha)
{
a = *in_row1;
a += *in_row2;
in_row1++;
in_row2++;
}
// read second column
r += *in_row1;
r += *in_row2;
in_row1++;
in_row2++;
g += *in_row1;
g += *in_row2;
in_row1++;
in_row2++;
b += *in_row1;
b += *in_row2;
in_row1++;
in_row2++;
if (src_has_alpha)
{
a += *in_row1;
a += *in_row2;
in_row1++;
in_row2++;
}
// write blended color
*out = (UINT8)(r >> 2);
out++;
*out = (UINT8)(g >> 2);
out++;
*out = (UINT8)(b >> 2);
out++;
if (dest_has_alpha)
{
*out = (UINT8)(a >> 2);
out++;
}
}
}
return dest;
}
/* wraps resize_half so it can be called directly from python */
PyObject *
resize_half_wrap(PyObject *self, PyObject *args)
{
/* raw input python variables */
PyObject *dest, *src;
/* return value: dest image on success */
PyObject *ret;
if (!PyArg_ParseTuple(args, "OO", &dest, &src))
return NULL;
ret = resize_half(dest, src);
if (ret == dest) {
/* Python needs us to own our return value */
Py_INCREF(dest);
}
return ret;
}

View File

@@ -26,6 +26,9 @@ static PyMethodDef COverviewerMethods[] = {
{"alpha_over", alpha_over_wrap, METH_VARARGS, {"alpha_over", alpha_over_wrap, METH_VARARGS,
"alpha over composite function"}, "alpha over composite function"},
{"resize_half", resize_half_wrap, METH_VARARGS,
"downscale image to half size"},
{"render_loop", chunk_render, METH_VARARGS, {"render_loop", chunk_render, METH_VARARGS,
"Renders stuffs"}, "Renders stuffs"},

View File

@@ -69,6 +69,8 @@ PyObject *draw_triangle(PyObject *dest, int inclusive,
int x2, int y2, int x2, int y2,
unsigned char r2, unsigned char g2, unsigned char b2, unsigned char r2, unsigned char g2, unsigned char b2,
int tux, int tuy, int *touchups, unsigned int num_touchups); int tux, int tuy, int *touchups, unsigned int num_touchups);
PyObject *resize_half(PyObject *dest, PyObject *src);
PyObject *resize_half_wrap(PyObject *self, PyObject *args);
/* forward declaration of RenderMode object */ /* forward declaration of RenderMode object */
typedef struct _RenderMode RenderMode; typedef struct _RenderMode RenderMode;

View File

@@ -35,6 +35,7 @@ from .files import FileReplacer
from .optimizeimages import optimize_image from .optimizeimages import optimize_image
import rendermodes import rendermodes
import c_overviewer import c_overviewer
from c_overviewer import resize_half
""" """
@@ -864,7 +865,11 @@ class TileSet(object):
for path in quadPath_filtered: for path in quadPath_filtered:
try: try:
quad = Image.open(path[1]).resize((192,192), Image.ANTIALIAS) #quad = Image.open(path[1]).resize((192,192), Image.ANTIALIAS)
src = Image.open(path[1])
src.load()
quad = Image.new("RGBA", (192, 192), self.options['bgcolor'])
resize_half(quad, src)
img.paste(quad, path[0]) img.paste(quad, path[0])
except Exception, e: except Exception, e:
logging.warning("Couldn't open %s. It may be corrupt. Error was '%s'", path[1], e) logging.warning("Couldn't open %s. It may be corrupt. Error was '%s'", path[1], e)