Blitting from-to surface with per-pixel alpha doesn't work

Hi there!

I know SDL’s problem about blitting with per-pixel alpha surfaces into
each other.

In the pygame (SDL binding for Python) documentation one can find the
following:
‘Surface alphas can be mixed with colorkeys, but an image with per pixel
alphas cannot use the other modes.’

I can interpret this like one can blit pixel data from any number of
surfaces to another with “only” one restriction: all of the surfaces’
transparency must be set to per-pixel alpha.

So, my problem is the following:
I have four surfaces: screen, background, tank and its parts.
The order of blitting: screen<-background and in another cycle
screen<-tank<-parts. All surfaces are having per-pixel-data of course.

Despite of this, the result in the tank surface (the surface I blit into
the parts) draws a strange black ‘belt’ around the parts, but other
transparent areas of the surfaces are showing up well.

I know it’s a little hard to imagine, but anyone meet a problem similar
to this?

Thank you, and sorry for my english!

Hi there!

I know SDL’s problem about blitting with per-pixel alpha surfaces into
each other.

In the pygame (SDL binding for Python) documentation one can find the
following:
‘Surface alphas can be mixed with colorkeys, but an image with per pixel
alphas cannot use the other modes.’

I can interpret this like one can blit pixel data from any number of
surfaces to another with “only” one restriction: all of the surfaces’
transparency must be set to per-pixel alpha.

So, my problem is the following:
I have four surfaces: screen, background, tank and its parts.
The order of blitting: screen<-background and in another cycle
screen<-tank<-parts. All surfaces are having per-pixel-data of course.

Despite of this, the result in the tank surface (the surface I blit into
the parts) draws a strange black ‘belt’ around the parts, but other
transparent areas of the surfaces are showing up well.

I know it’s a little hard to imagine, but did anyone meet a problem similar
to this?

Thank you, and sorry for my english!

El mi?, 16-11-2005 a las 23:05 +0100, D. Gyimesi escribi?:

I have four surfaces: screen, background, tank and its parts.
The order of blitting: screen<-background and in another cycle
screen<-tank<-parts. All surfaces are having per-pixel-data of course.

Despite of this, the result in the tank surface (the surface I blit into
the parts) draws a strange black ‘belt’ around the parts, but other
transparent areas of the surfaces are showing up well.

I know it’s a little hard to imagine, but did anyone meet a problem similar
to this?

No, and assuming you have everything set up correctly, it should work as
you describe it. Are you completely sure that the problem isn’t in the
images themselves? If the “strange black belt” is not rectangular and
contains the complete image, I’d say that’s the most likely cause.

How do you get SDL_Surfaces with alpha? Load from PNGs or are you doing
something else? Are you messing with the surface flags after loading
them?–
Gabriel Gambetta
Mystery Studio - http://www.mysterystudio.com
Gabriel on Graphics - http://gabrielongraphics.blogspot.com

Hi Gabriel!

All of the images are PNGs with initial transparency fill from Gimp.
The blit is working great with per-pixel alpha but only when I blit the
parts into ‘display’, not to the ‘tank’ and then to ‘display’ surface.
The black belt isn’t rectangular, it is on the boundary of the
transparency and the image.

I don’t know who to get SDL_Surfaces with alpha in SDL, because I’m
using PyGame, but I assuming there aren’t much differences. In PyGame
one can get a surface like this:
pygame.Surface((width, height), flags=0, depth=0, masks=None):return
SurfaceOn Thu, 2005-11-17 at 13:26 -0300, Gabriel wrote:

El mi?, 16-11-2005 a las 23:05 +0100, D. Gyimesi escribi?:

I have four surfaces: screen, background, tank and its parts.
The order of blitting: screen<-background and in another cycle
screen<-tank<-parts. All surfaces are having per-pixel-data of course.

Despite of this, the result in the tank surface (the surface I blit into
the parts) draws a strange black ‘belt’ around the parts, but other
transparent areas of the surfaces are showing up well.

I know it’s a little hard to imagine, but did anyone meet a problem similar
to this?

No, and assuming you have everything set up correctly, it should work as
you describe it. Are you completely sure that the problem isn’t in the
images themselves? If the “strange black belt” is not rectangular and
contains the complete image, I’d say that’s the most likely cause.

How do you get SDL_Surfaces with alpha? Load from PNGs or are you doing
something else? Are you messing with the surface flags after loading
them?

How do you get SDL_Surfaces with alpha? Load from PNGs or are you
doing
something else? Are you messing with the surface flags after loading
them?

There’s a method in the Surface class that can convert the pixel data of
the surface to per-pixel alpha. The following line loads the image, then
(if hasn’t got per-pixel alpha values) it converts it:
image = pygame.image.load(filename).convert_alpha()

All of the surfaces initialized with convert_alpha(), so they must have
alpha values.
I don’t touch the surface flags anyway.

self.original =
pygame.Surface(self.rect.size,SRCALPHA,32).convert_alpha() is the way
I’m making surfaces.

Hi there!

Btw, you can get a shot from the problem at:
http://www.cab.u-szeged.hu/~h370556/tc_shot.zip

All of the images are PNGs with initial transparency fill from Gimp.
The blit is working great with per-pixel alpha but only when I blit the
parts into ‘display’, not to the ‘tank’ and then to ‘display’ surface.

Wait, wait. When you said “screen<-tank<-parts” I assumed you meant
"(screen <- tank) <- parts". If you meant "screen <- (tank <- parts)"
then you’re correct, SDL doesn’t work as you expect - the SDL_SetAlpha
docs say “Note that RGBA->RGBA blits (with SDL_SRCALPHA set) keep the
alpha of the destination surface. This means that you cannot compose two
arbitrary RGBA surfaces this way and get the result you would expect
from “overlaying” them; the destination alpha will work as a mask.”

I have encountered this problem before, as many other people have; the
general consensus seems to be to code that blit manually, using whatever
alpha semantics you want. Since I only do this at load time, it doesn’t
matter that it isn’t optimized.

It may be a good idea to have at least a non-optimized function in SDL
to do this. Everyone : what kind of operation should be done for an
hypotethical SDL_ComposeSurface()?–
Gabriel Gambetta
Mystery Studio - http://www.mysterystudio.com
Gabriel on Graphics - http://gabrielongraphics.blogspot.com

Gabriel wrote:

All of the images are PNGs with initial transparency fill from Gimp.
The blit is working great with per-pixel alpha but only when I blit the
parts into ‘display’, not to the ‘tank’ and then to ‘display’ surface.

Wait, wait. When you said “screen<-tank<-parts” I assumed you meant
"(screen <- tank) <- parts". If you meant "screen <- (tank <- parts)"
then you’re correct, SDL doesn’t work as you expect - the SDL_SetAlpha
docs say “Note that RGBA->RGBA blits (with SDL_SRCALPHA set) keep the
alpha of the destination surface. This means that you cannot compose two
arbitrary RGBA surfaces this way and get the result you would expect
from “overlaying” them; the destination alpha will work as a mask.”

I have encountered this problem before, as many other people have; the
general consensus seems to be to code that blit manually, using whatever
alpha semantics you want. Since I only do this at load time, it doesn’t
matter that it isn’t optimized.

It may be a good idea to have at least a non-optimized function in SDL
to do this. Everyone : what kind of operation should be done for an
hypotethical SDL_ComposeSurface()?

The Porter & Duff ‘Over’ operator as described there :

Stephane