[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] Fubared set_alpha()



Pete Shinners wrote:
looks good. now what is unfortunately causing you trouble is that the blitting does try to blend, so if we blit this again you can see the values will not match..

>>> s2.blit(s1, (0,0))
<rect(0, 0, 9, 18)>
>>> s1.get_at((7,7)), s2.get_at((7,7))
((128, 64, 32, 240), (127, 63, 31, 255))

this should be easy enough to solve by clearing the destination first.
	What do you mean by "clearing the destination first"?

sure. the whole problem comes down to the fact that SDL support for pixel alphas is pretty weak in my opinion.
Indeed; consider the face that the Surface constructor is called SDL_CreateRGBSurface(), but there is no corresponding "SDL_CreateRGBASurface()" to go with it. In fact, the only way I could find to create a blank RGBA surface was to create a new surface with pygame.Surface() and then call Surface.convert() and pass in the RGBA surface I got back from the TTF function.

disables the SRCALPHA. the other problem is when blitting to a destination with SRCALPHA, none of SDL's blitters set the destination SRCALPHA (well, all except the one you've just pointed out). in this case pygame hijacks the blit with it's own built-in blit functions that actually do what you want. this is what has changed and is throwing off your desired effect.
Hmm.. my reading of http://sdldoc.csn.ul.ie/sdlsetalpha.php makes it sound like the SRCALPHA bit of the destination is irrelevant.

It looks to me like SRCALPHA flag of the source Surface is the only one that matters when blitting.


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

ah, this is a potentially strange, but no one has been snubbed by it before now. still, it seems it shouldn't effect anything in SDL since if there is no SDL_SRCALPHA flag, SDL ignores all surface and pixel alpha values. in your case, if the surface does have pixel alphas, then the surface alpha is entirely ignored anyway. i'm trying to guess if this is what is the real problem.
Yes, this was a little weird for me, too.

[...]

I just did some more testing. It looks like I made a mistake. I thought that the SRCALPHA on the _source_ image was what mattered. But, after playing with it, I need to clear the "SRCALPHA" flag on BOTH _source_ and the _destination_ image before doing the blit.

That is, using standard PyGame 1.5.5, without that patch I posted, I can get my RGBA->RGBA blit to work correctly if I do this:

dest.set_alpha(None, 0) # Clear SRCALPHA flag on dest
source.set_alpha(None, 0) # Clear it on the source also
dest.blit(source, [0,0])

...and ta-da, things work.

I'm not sure what is up with this. I think it may be this snipped from surface.c, in the C function PySurface_Blit():

if(dst->format->Amask && dst->flags&SDL_SRCALPHA &&
(dst->format->BytesPerPixel == 2 || dst->format->BytesPerPixel==4))
{
result = pygame_AlphaBlit(src, srcrect, dst, dstrect);
}

Is this why I need to clear the SRCALPHA bit on the _destination_ image? I don't know.

But, in any event, it looks like reverting out that patch I posted is the best course of action. I will let somebody more familiar with SDL figure this out... right now, my code is working with standard PyGame, and I have a GUI to build :)

And now in venting mode, it took me several hours to find and correct this (highly frustrating and very well-hidden) bug.
	...and so I apologize for this.  :)

i've got this all fixed up in pygame cvs now (phew, first checkin in a month)
Again, please revert that checkin until this problem has been more fully analyzed. (Also, my test results from before must be ignored, as I was clearing the SRCALPHA on my _destination_ surface without knowing it.)

My question is, with SDL, am I supposed to clear the SRCALPHA on the destination surface, the source surface, or both? I was always under the impression it had to be on the cleared on the source surface. And my second question is, what does that translate into with PyGame?

Thank you for all your help.


--Derek