The following tutorial was created by Blue Dino Code, for the purpose of helping people like you learn SDL. This tutorial, though not purposely a part of the or created for the series, may be a branch or addition to the series. Please read notes by the author for any additional code and/or framework used by the author. does not endorse or reject any of the coding practices outlined in the tutorial, and is not responsible for any code or files belonging to this tutorial that harms your computer.

The Ins and Outs (and Overlays) of Alpha-blending
Some knowledge of SDL

Alpha-blending is the process of using an extra value (alpha) to combine color values (like partial transparency) instead of just replacing one with the other. Commonly in SDL, this is done with entire surfaces. One surface, the 'source', is blitted (drawn) onto another 'destination' surface (also 'dest'). Now, there are a few ways to do this and several of them are, sadly, not possible through SDL's built-in blitter (accessible through SDL_BlitSurface). I'll cover the readily possible ones first, then get to the ones that you need either Sprig or some other software for.

There are three paths to transparency:
Path 1: Colorkeying (aka CK)
Path 2: Per-Surface Alpha (PSA)
Path 3: Per-Pixel Alpha (PPA)

All three of these can be used in various combinations to acheive visual awesomeness, with the exception that in SDL, per-pixel alpha takes priority over per-surface alpha.

Colorkeying is your first choice. If you use RGB surfaces (no alpha channel) and you want some areas to be transparent and others not, then this is the way to go. First, load an image with one particular color as the background (very often people choose bright pink: RGB=255,0,255). Now, we can use SDL_SetColorKey (note the capital K)...
SDL_SetColorKey(mySurface, SDL_SRCCOLORKEY, 0xFF00FF);
// Or, more portably:
SDL_SetColorKey(mySurface, SDL_SRCCOLORKEY, SDL_MapRGB(mySurface->format, 255, 0, 255));

// You can see why Sprig has a convenience function for this:
// Using Sprig and SDL_ColorDef (new version)
SPG_SetColorkey(mySurface, RGB_BRIGHTPINK(mySurface));

// Here's how to disable it
SDL_SetColorKey(mySurface, 0, mySurface->format->colorkey);
// I used the surface's current colorkey just so I'm not throwing away info that I might use later
Colorkeying has advantages in that it is easy to use and it is processed quickly. It can only give you either full transparency or full opacity, however.

The second option is per-surface alpha. This is a nice feature of SDL that allows you to control the alpha value of the entire surface all at once. This is great for certain fading effects and runs faster than per-pixel alpha. In SDL, alpha is a measure of opacity (how opaque something is). It ranges from 0 to 255 (n.b. 256 different values), 0 being fully transparent, and 255 being fully opaque. You can use SDL_SetAlpha to control your per-surface alpha...
SDL_SetAlpha(mySurface, SDL_SRCALPHA, 200);  // Mostly opaque
SDL_SetAlpha(mySurface, SDL_SRCALPHA, 16);  // Barely there

// To disable PSA (and PPA for that matter):
SDL_SetAlpha(mySurface, 0, mySurface->format->alpha);
// Again, I'm saving the PSA value for later

Per-pixel alpha is found as an extra color channel on true-color surfaces, those that store color information in each pixel rather than in a palette. This is the real alpha-blending that you might normally think of. PNG (Portable Network Graphics) and TGA (Truevision Graphics Adapter, commonly 'Targa') are two common image file formats that support per-pixel alpha. There is a surprising lack of simple utilities that help you to work well with the alpha channel in images... I'm hoping to pop out one if someone doesn't beat me to it. You can load these formats with the SDL_Image library.
SDL_Surface* mySurface = IMG_Load("mypic.png");
// Boom!  Instant alpha channel!

Now you have a few more choices... The SDL documentation has a list of the options, but a table would do much better...
Type SDL_SRCALPHA SDL_SRCCOLORKEY Per-pixel blend? Per-surface blend? Colorkey?
RGB->RGB(A) On On > No Yes Yes
RGB->RGB(A) On Off > No Yes No
RGB->RGB(A) Off On > No No Yes
RGB->RGB(A) Off Off > No No No
RGBA->RGB On On > Yes No No
RGBA->RGB On Off > Yes No No
RGBA->RGB Off On > No No No
RGBA->RGB Off Off > No No No
RGBA->RGBA On On > Yes No No
RGBA->RGBA On Off > Yes No No
RGBA->RGBA Off On > No No Yes
RGBA->RGBA Off Off > No No No

Wow! There it is! Good job, self. This summarizes what you can do with transparency in SDL. There are waaay too many 'No's up there... No wonder I thought the Sprig blitter was a good idea. Look at the three columns on the right for what you want to do, then apply the appropriate flags to the source surface. Keep in mind that when performing alpha-blending in SDL, there is no way to blend the destination alpha (see Sprig).

To round things out, we should chat about creating surfaces. This is done with two functions: SDL_CreateRGBSurface and SDL_CreateRGBSurfaceFrom. The first one makes a surface from scratch. The second one takes some existing pixel data and creates a new surface with it.
// Create a 32-bit 40x45 software surface
SDL_Surface* surf1 = SDL_CreateRGBSurface(SDL_SWSURFACE, 40, 45, 32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000);

// Now a 32-bit 50x70 surface from memory
SDL_Surface* surf2 = SDL_CreateRGBSurfaceFrom(myPixelArray, 50, 70, 32, 50*4, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000);
Now the picky stuff comes in... See all those hexidecimal values I threw in there? Those are the masks for each color channel, RGBA. Surfaces can come in all different configurations, so these values tell the blitter how to handle the data I throw at it. Each pair of characters represents 8 bits and has a max value of 255. So you can look at a single 32-bit color value like so: 0xAABBGGRR (or ABGR). I know, it looks backwards, but that's how these are represented in little endian format. Don't get me started on that. If you don't want to mess with endianess, then just use SPG_CreateAlphaSurface (again with the convenience!). You can look into SPG_CreateAlphaSurface in sprig_inline.h to see how I deal with it (or check the SDL docs). I only really mess with 32-bit images, so if you use a different format, make sure that your color masks isolate their respective color with a bit-wise AND (&). The spot where I put '50*4' is the pitch of the image. That is the number of bytes that total one horizontal scanline. In this case, 32 bits means 4 bytes, so I'm just multiplying the width by that number. The way that SDL determines if a particular surface has an alpha channel or not is by looking at its alpha mask. So, to disable the alpha channel...
SDL_Surface* surf3 = SDL_CreateRGBSurface(SDL_SWSURFACE, 40, 45, 32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0);

// or...
surf1->format->Amask = 0;
Okay. That's it for built-in SDL stuff. Sprig (slowly) implements a few (slow) more (slow!) options. By pushing a flag onto the blending stack, we can change the mode of the Sprig blitter and the Sprig primitives. Oh, by the way, the blitter can be a little slow sometimes. These effects are not good for real-time usage. You should render them once before you need them, then use them wherever.
// Set it

// Do it
SPG_Blit(mySurf, NULL, screen, NULL);

// Restore the old one so nobody else is messed up
The SPG_COMBINE_ALPHA flag makes the blitter perform alpha-blending on the destination alpha channel as well as the other color channels. This is an 'overlay' effect. You can apply a partially transparent surface to a fully opaque surface and get a partially transparent result. You can apply a surface to a fully transparent dest and get a visible result. A nice set of flags are the SPG_COPY_ALPHA_ONLY and SPG_COMBINE_ALPHA_ONLY flags. You can mess with the transparency and leave the colors untouched. Check out the Sprig documentation for more.

Sweet. If you want to talk more alpha to me, go right on ahead.

Jonny D