in pygame we had this same problem. there are some easily
extractable ‘alpha to alpha’ blitting functions you should
be able to use (they are LGPL, like SDL).
currently they are a bit “hacky”, and i’d love if someone
more mathematically knowledgeable could make the “correct”.
if the destination alpha is 0, then the source alpha is
copied. otherwise the source and destination alphas are
properly blended.
What you’re doing sounds correct. What happens in professional compositing
programs when using the standard over operation is this:
1. If the foreground image is premultiplied, go to step 3
2. Multiply the foreground image against its own alpha channel
3. Invert the foreground image’s alpha channel
4. Multiply the background image (all channels) by the foreground
image’s newly inverted alpha channel.
5. Revert the foreground image’s alpha channel to its original state
6. Add the foreground image to the background image (all channels)
Now, if the destination alpha is 0, then just copying the source alpha would
accomplish the same thing as all the steps above, at least as far as the
alpha channel is concerned. So you are correct in that optimization.
Whether or not this is what SDL does is another matter. As far as blitting a
surface with an alpha channel to another surface with an alpha channel, and
then blitting that surface to the screen goes, it seems to work OK for me.
On my system (Linux, SDL 1.2.5, GeForce2 MX), the following program works
exactly as expected (the image used, test.png, is available at
http://kewlpc.org/pics/test.png )
/* compile with
gcc sdltest.c -o sdltest sdl-config --cflags --libs
-lSDL_image
*/
#include <stdio.h>
#include “SDL.h”
#include “SDL_image.h”
int main(void)
{
SDL_Surface *screen;
SDL_Surface *image;
SDL_Surface *target;
SDL_Event event;
int quit = 0;
SDL_Init(SDL_INIT_VIDEO);
atexit(SDL_Quit);
screen = SDL_SetVideoMode(640,480,32,SDL_DOUBLEBUF);
SDL_WM_SetCaption("SDL TEST",NULL);
image = IMG_Load("test.png");
SDL_SetAlpha(image,SDL_RLEACCEL|SDL_SRCALPHA,255);
target = SDL_DisplayFormatAlpha(image);
SDL_FillRect(target,NULL,SDL_MapRGBA(target->format,0,0,0,0));
SDL_BlitSurface(image,NULL,target,NULL);
SDL_FillRect(screen,NULL,SDL_MapRGB(screen->format,0,128,128));
SDL_BlitSurface(target,NULL,screen,NULL);
SDL_Flip(screen);
while(!quit) {
while(SDL_PollEvent(&event)) {
switch(event.type) {
case SDL_MOUSEBUTTONDOWN:
quit = 1;
break;
case SDL_QUIT:
quit = 1;
break;
default:
break;
}
}
}
return 0;
}
the problem with always blending, if the dest has 0 alpha,
it ends up darkening the pixels blended onto it. is there a
compositing method that factors in the destination alpha to
the amount of destination color to mix? i tried a few things
and was not pleased with the results.
Even if you are always blending, when blended properly this shouldn’t happen.
The destination alpha should have nothing to do with it. On my machine, using
the above code (if you’ll notice, target has an alpha of 0), what you’re
describing doesn’t happen.
-Sean Ridenour