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

@@ -22,7 +22,8 @@
* PIL paste if this extension is not found.
*/
#include "overviewer.h"
#include "overviewer.h"
#include <stdio.h>
typedef struct {
PyObject_HEAD
@@ -489,3 +490,154 @@ draw_triangle(PyObject *dest, int inclusive,
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 composite function"},
{"resize_half", resize_half_wrap, METH_VARARGS,
"downscale image to half size"},
{"render_loop", chunk_render, METH_VARARGS,
"Renders stuffs"},

View File

@@ -69,6 +69,8 @@ PyObject *draw_triangle(PyObject *dest, int inclusive,
int x2, int y2,
unsigned char r2, unsigned char g2, unsigned char b2,
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 */
typedef struct _RenderMode RenderMode;

View File

@@ -35,6 +35,7 @@ from .files import FileReplacer
from .optimizeimages import optimize_image
import rendermodes
import c_overviewer
from c_overviewer import resize_half
"""
@@ -858,13 +859,17 @@ class TileSet(object):
# Create the actual image now
img = Image.new("RGBA", (384, 384), self.options['bgcolor'])
# we'll use paste (NOT alpha_over) for quadtree generation because
# this is just straight image stitching, not alpha blending
for path in quadPath_filtered:
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])
except Exception, e:
logging.warning("Couldn't open %s. It may be corrupt. Error was '%s'", path[1], e)