added overall_alpha parameter to alpha_over, speeding up lighting
This commit is contained in:
@@ -58,52 +58,20 @@ imaging_python_to_c(PyObject *obj)
|
|||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/* convenience alpha_over with 1.0 as overall_alpha */
|
||||||
* img should be an Image object, type 'L' or 'RGBA'
|
inline PyObject* alpha_over(PyObject *dest, PyObject *src, PyObject *mask,
|
||||||
* for RGBA images, operates on the alpha only
|
int dx, int dy, int xsize, int ysize) {
|
||||||
* factor should be between 0 and 1, inclusive
|
return alpha_over_full(dest, src, mask, 1.0f, dx, dy, xsize, ysize);
|
||||||
*/
|
|
||||||
PyObject *brightness(PyObject *img, float factor) {
|
|
||||||
Imaging imDest;
|
|
||||||
|
|
||||||
int offset, stride, x, y, xsize, ysize;
|
|
||||||
|
|
||||||
imDest = imaging_python_to_c(img);
|
|
||||||
if (!imDest)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (strcmp(imDest->mode, "RGBA") != 0 && strcmp(imDest->mode, "L") != 0) {
|
|
||||||
PyErr_SetString(PyExc_ValueError,
|
|
||||||
"given image does not have mode \"RGBA\" or \"L\"");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* how far into image the first alpha byte resides */
|
|
||||||
offset = (imDest->pixelsize == 4 ? 3 : 0);
|
|
||||||
/* how many bytes to skip to get to the next alpha byte */
|
|
||||||
stride = imDest->pixelsize;
|
|
||||||
|
|
||||||
xsize = imDest->xsize;
|
|
||||||
ysize = imDest->ysize;
|
|
||||||
|
|
||||||
for (y = 0; y < ysize; y++) {
|
|
||||||
UINT8 *out = (UINT8 *)imDest->image[y] + offset;
|
|
||||||
|
|
||||||
for (x = 0; x < xsize; x++) {
|
|
||||||
*out *= factor;
|
|
||||||
out += stride;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the alpha_over function, in a form that can be called from C */
|
/* the full alpha_over function, in a form that can be called from C
|
||||||
/* if xsize, ysize are negative, they are instead set to the size of the image in src */
|
* overall_alpha is multiplied with the whole mask, useful for lighting...
|
||||||
/* returns NULL on error, dest on success. You do NOT need to decref the return! */
|
* if xsize, ysize are negative, they are instead set to the size of the image in src
|
||||||
PyObject *
|
* returns NULL on error, dest on success. You do NOT need to decref the return!
|
||||||
alpha_over(PyObject *dest, PyObject *src, PyObject *mask, int dx, int dy,
|
*/
|
||||||
int xsize, int ysize)
|
inline PyObject *
|
||||||
{
|
alpha_over_full(PyObject *dest, PyObject *src, PyObject *mask, float overall_alpha,
|
||||||
|
int dx, int dy, int xsize, int ysize) {
|
||||||
/* libImaging handles */
|
/* libImaging handles */
|
||||||
Imaging imDest, imSrc, imMask;
|
Imaging imDest, imSrc, imMask;
|
||||||
/* cached blend properties */
|
/* cached blend properties */
|
||||||
@@ -114,6 +82,12 @@ alpha_over(PyObject *dest, PyObject *src, PyObject *mask, int dx, int dy,
|
|||||||
unsigned int x, y, i;
|
unsigned int x, y, i;
|
||||||
/* temporary calculation variables */
|
/* temporary calculation variables */
|
||||||
int tmp1, tmp2, tmp3;
|
int tmp1, tmp2, tmp3;
|
||||||
|
/* integer [0, 255] version of overall_alpha */
|
||||||
|
UINT8 overall_alpha_int = 255 * overall_alpha;
|
||||||
|
|
||||||
|
/* short-circuit this whole thing if overall_alpha is zero */
|
||||||
|
if (overall_alpha_int == 0)
|
||||||
|
return dest;
|
||||||
|
|
||||||
imDest = imaging_python_to_c(dest);
|
imDest = imaging_python_to_c(dest);
|
||||||
imSrc = imaging_python_to_c(src);
|
imSrc = imaging_python_to_c(src);
|
||||||
@@ -202,9 +176,18 @@ alpha_over(PyObject *dest, PyObject *src, PyObject *mask, int dx, int dy,
|
|||||||
UINT8 *inmask = (UINT8 *)imMask->image[sy + y] + sx * mask_stride + mask_offset;
|
UINT8 *inmask = (UINT8 *)imMask->image[sy + y] + sx * mask_stride + mask_offset;
|
||||||
|
|
||||||
for (x = 0; x < xsize; x++) {
|
for (x = 0; x < xsize; x++) {
|
||||||
|
UINT8 in_alpha;
|
||||||
|
|
||||||
|
/* apply overall_alpha */
|
||||||
|
if (overall_alpha_int != 255 && *inmask != 0) {
|
||||||
|
in_alpha = MULDIV255(*inmask, overall_alpha_int, tmp1);
|
||||||
|
} else {
|
||||||
|
in_alpha = *inmask;
|
||||||
|
}
|
||||||
|
|
||||||
/* special cases */
|
/* special cases */
|
||||||
if (*inmask == 255 || *outmask == 0) {
|
if (in_alpha == 255 || *outmask == 0) {
|
||||||
*outmask = *inmask;
|
*outmask = in_alpha;
|
||||||
|
|
||||||
*out = *in;
|
*out = *in;
|
||||||
out++, in++;
|
out++, in++;
|
||||||
@@ -213,18 +196,18 @@ alpha_over(PyObject *dest, PyObject *src, PyObject *mask, int dx, int dy,
|
|||||||
*out = *in;
|
*out = *in;
|
||||||
out++, in++;
|
out++, in++;
|
||||||
}
|
}
|
||||||
else if (*inmask == 0) {
|
else if (in_alpha == 0) {
|
||||||
/* do nothing -- source is fully transparent */
|
/* do nothing -- source is fully transparent */
|
||||||
out += 3;
|
out += 3;
|
||||||
in += 3;
|
in += 3;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* general case */
|
/* general case */
|
||||||
int alpha = *inmask + MULDIV255(*outmask, 255 - *inmask, tmp1);
|
int alpha = in_alpha + MULDIV255(*outmask, 255 - in_alpha, tmp1);
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
/* general case */
|
/* general case */
|
||||||
*out = MULDIV255(*in, *inmask, tmp1) +
|
*out = MULDIV255(*in, in_alpha, tmp1) +
|
||||||
MULDIV255(MULDIV255(*out, *outmask, tmp2), 255 - *inmask, tmp3);
|
MULDIV255(MULDIV255(*out, *outmask, tmp2), 255 - in_alpha, tmp3);
|
||||||
|
|
||||||
*out = (*out * 255) / alpha;
|
*out = (*out * 255) / alpha;
|
||||||
out++, in++;
|
out++, in++;
|
||||||
|
|||||||
@@ -38,10 +38,11 @@
|
|||||||
|
|
||||||
/* in composite.c */
|
/* in composite.c */
|
||||||
Imaging imaging_python_to_c(PyObject *obj);
|
Imaging imaging_python_to_c(PyObject *obj);
|
||||||
PyObject *alpha_over(PyObject *dest, PyObject *src, PyObject *mask, int dx,
|
PyObject *alpha_over(PyObject *dest, PyObject *src, PyObject *mask,
|
||||||
int dy, int xsize, int ysize);
|
int dx, int dy, int xsize, int ysize);
|
||||||
|
PyObject *alpha_over_full(PyObject *dest, PyObject *src, PyObject *mask, float overall_alpha,
|
||||||
|
int dx, int dy, int xsize, int ysize);
|
||||||
PyObject *alpha_over_wrap(PyObject *self, PyObject *args);
|
PyObject *alpha_over_wrap(PyObject *self, PyObject *args);
|
||||||
PyObject *brightness(PyObject *img, float factor);
|
|
||||||
|
|
||||||
/* in iterate.c */
|
/* in iterate.c */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -135,9 +135,8 @@ get_lighting_coefficient(RenderModeLighting *self, RenderState *state,
|
|||||||
lighting results from (x, y, z) */
|
lighting results from (x, y, z) */
|
||||||
static inline void
|
static inline void
|
||||||
do_shading_with_mask(RenderModeLighting *self, RenderState *state,
|
do_shading_with_mask(RenderModeLighting *self, RenderState *state,
|
||||||
int x, int y, int z, PyObject *facemask) {
|
int x, int y, int z, PyObject *mask) {
|
||||||
float black_coeff;
|
float black_coeff;
|
||||||
PyObject *mask;
|
|
||||||
|
|
||||||
/* first, check for occlusion if the block is in the local chunk */
|
/* first, check for occlusion if the block is in the local chunk */
|
||||||
if (x >= 0 && x < 16 && y >= 0 && y < 16 && z >= 0 && z < 128) {
|
if (x >= 0 && x < 16 && y >= 0 && y < 16 && z >= 0 && z < 128) {
|
||||||
@@ -149,11 +148,7 @@ do_shading_with_mask(RenderModeLighting *self, RenderState *state,
|
|||||||
}
|
}
|
||||||
|
|
||||||
black_coeff = get_lighting_coefficient(self, state, x, y, z, NULL);
|
black_coeff = get_lighting_coefficient(self, state, x, y, z, NULL);
|
||||||
|
alpha_over_full(state->img, self->black_color, mask, black_coeff, state->imgx, state->imgy, 0, 0);
|
||||||
mask = PyObject_CallMethod(facemask, "copy", NULL); // new ref
|
|
||||||
brightness(mask, black_coeff);
|
|
||||||
alpha_over(state->img, self->black_color, mask, state->imgx, state->imgy, 0, 0);
|
|
||||||
Py_DECREF(mask);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|||||||
Reference in New Issue
Block a user