[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[pygame] Fubared set_alpha()
- To: pygame-users@seul.org
- Subject: [pygame] Fubared set_alpha()
- From: Derek Simkowiak <dereks@realloc.net>
- Date: Fri, 09 May 2003 15:00:38 -0700
- Delivered-to: archiver@seul.org
- Delivered-to: pygame-users-outgoing@seul.org
- Delivered-to: pygame-users@seul.org
- Delivery-date: Fri, 09 May 2003 18:01:22 -0400
- Reply-to: pygame-users@seul.org
- Sender: owner-pygame-users@seul.org
- User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.3) Gecko/20030313
I just fired up some code I wrote about a year ago. The PyGame API has
changed and now I can't see how to make my PyGame code work again.
I need to copy one RGBA surface onto another RGBA surface. The source
surface has per-pixel alpha information (instead of a single byte alpha
value for the whole surface). I want to keep that per-pixel alpha
information when I blit the source surface into my destination surface,
rather than "blending" or using the destination alpha.
The way to do that with SDL is to clear the bit SDL_SRCALPHA bit on the
source surface before doing the blit. Here is the SDL documentation:
--------
RGBA->RGBA without SDL_SRCALPHA
The RGBA data is copied to the destination surface. If SDL_SRCCOLORKEY
is set, only the pixels not matching the colorkey value are copied.
--------
Hence, the SDL_SRCALPHA bit must be cleared for me to do what I want
(which, FYI, is render an anti-aliased font created with the SDL TTF
library using OpenGL).
Here is the PyGame code that worked successfully before. "source" and
"dest" are my RGBA surfaces with per-pixel alpha information:
# Turn off SRCALPHA so the alpha value is copied directly (instead of
blending)
source.set_alpha(flags=0)
dest.blit(source, [0, 0])
But the new and "improved" API does not use the named argument "flags".
The above code results in this error:
TypeError: set_alpha() takes no keyword arguments
set_alpha() is now designed with both the alpha argument AND the flags
argument. To pass the flags argument, one MUST, with the new (broken)
API, also pass in an alpha argument.
Well, fine, no biggie, except for this little nugget in the surface.c
"set_alpha()" function:
if(alpha_obj && alpha_obj!=Py_None)
{
[...]
hasalpha = 1;
}
if(hasalpha)
flags |= SDL_SRCALPHA;
So, unless I pass in an alpha value that is PyNone, SDL_SRCALPHA
automatically gets set for me.
"Fine", you say, "just pass in an alpha argument of None and the flags
will be left alone". Except that when the alpha argument is None, the
value passed to the underlying SDL_SetAlpha() is a default of zero,
a.k.a. SDL_ALPHA_TRANSPARENT, a.k.a. "Fully Transparent", a.k.a. I'm
forced to make my image invisible if I want to clear the SDL_SRCALPHA
flag and blit with the per-pixel alpha data.
This is not the desired behaviour, and it makes it impossible to blit
one RGBA surface onto another whilst retaining the per-pixel alpha data.
Attached is the patch to fix this bug. It makes my code work again.
And now in venting mode, it took me several hours to find and correct
this (highly frustrating and very well-hidden) bug. Everytime something
like this happens to me it's a matter of some developer deciding he
knows better than me what arguments I wanted to pass in. There are two
other places in surface.c where flags are "automagically" set. Please,
remove that "feature" and just give me SDL from Python. (End venting mode.)
Thanks,
Derek Simkowiak
--- /home/dereks/PyGame/pygame-1.5.5/src/surface.c 2002-12-02 23:10:45.000000000 -0800
+++ /usr/src/RPM/SOURCES/pygame-1.5.5/src/surface.c 2003-05-09 14:10:49.000000000 -0700
@@ -624,7 +624,7 @@
Uint32 flags = 0;
PyObject* alpha_obj = NULL, *intobj=NULL;
Uint8 alpha;
- int result, alphaval=0, hasalpha=0;
+ int result, alphaval=0;
if(!PyArg_ParseTuple(args, "|Oi", &alpha_obj, &flags))
return NULL;
@@ -641,10 +641,7 @@
}
else
return RAISE(PyExc_TypeError, "invalid alpha argument");
- hasalpha = 1;
}
- if(hasalpha)
- flags |= SDL_SRCALPHA;
if(alphaval>255) alpha = 255;
else if(alphaval<0) alpha = 0;