I was stuck using a platform that did not support extended image formats, but I absolutely had to have per-pixel-alpha. To overcome, I wrote this nifty little module.

""" bmp32.py Load a 32-bit, RGBA Windows Bitmap file for use with PyGame. 2007 Michael Thomas Greer Released to the Public Domain. Overview PyGame does not always come with the ability to load all image types. This is inconvenient because sometimes you just really, really want to play with per-pixel alpha images, but PyGame's BMP support doesn't understand a bitmap's alpha channel, and if you are stuck using a platform without extended image support, who do you call? Windows BMP files have always been capable of storing alpha data, but it was only with the release of Windows XP that Microsoft actually supported such use. As a result, most BMP readers/editors ignore or clobber alpha data in your bitmap. PyGame is no different. This module addresses that problem in pure python code. Example of How to Use Here's a very simple example. You'll need two files to run it. The first, named "background.bmp", is any normal BMP file to use for the background image. The other, "foreground.bmp32", is a 32-bit BMP with alpha channel which follows the cursor as you move it around the PyGame display window. import pygame import bmp32 pygame.init() bg = pygame.image.load( 'background.bmp' ) screen = pygame.display.set_mode( bg.get_size() ) bg = bg.convert() fg = bmp32.load( 'foreground.bmp32' ).convert_alpha() screen.blit( bg, (0, 0) ) pygame.display.update() pygame.mouse.set_visible( False ) done = False while not done: for event in pygame.event.get(): if event.type in [pygame.QUIT, pygame.KEYDOWN]: done = True break elif event.type == pygame.MOUSEMOTION: screen.blit( bg, (0, 0) ) screen.blit( fg, event.pos ) pygame.display.update() Building a 32-bit BMP with alpha channel Photoshop is one of the few programs that can load and save a BMP with alpha data. If you don't have access to Photoshop (as I don't), here's a little cross-platform C++ source to compile a bitmap with alpha. It requires the EasyBMP library at "http://easybmp.sourceforge.net/". EasyBMP is specifically cross-platform, small, and self-contained. Just unzip everything to a new directory. Create a new CPP file in that same directory and paste the following into it. // bmp32.cpp // // Takes two BMP files and combines them into a 32-bit, RGBA Bitmap. // 2007 Michael Thomas Greer #include #include #include "EasyBMP.h" using namespace std; int usage() { cerr << "usage:" << endl << " bmp32 rgb.bmp alpha.bmp result.bmp32" << endl << endl << "where:" << endl << " rgb.bmp is the name of the image with colors." << endl << " alpha.bmp is a grayscale image representing the" << endl << " alpha channel. Black is fully" << endl << " transparent and white is fully opaque." << endl << " result.bmp is the name of the file you wish to" << endl << " create (overwrites existing files)." << endl; return EXIT_FAILURE; } int failure( const char *message ) { cout << message << endl; return EXIT_FAILURE; } int main( int argc, char **argv ) { BMP rgb_file, alpha_file; if (argc < 4) return usage(); if (!rgb_file .ReadFromFile( argv[ 1 ] )) return failure( "Could not read RGB color bitmap" ); if (!alpha_file.ReadFromFile( argv[ 2 ] )) return failure( "Could not read alpha data bitmap" ); if ((rgb_file.TellHeight() != alpha_file.TellHeight()) || (rgb_file.TellWidth() != alpha_file.TellWidth())) return failure( "The source bitmaps are not the same size!" ); rgb_file.SetBitDepth( 32 ); for (int y = 0; y < rgb_file.TellHeight(); y++) for (int x = 0; x < rgb_file.TellWidth(); x++) rgb_file( x, y )->Alpha = alpha_file( x, y )->Red; if (!rgb_file.WriteToFile( argv[ 3 ] )) return failure( "Failed to create or overwrite output file." ); return EXIT_SUCCESS; } // end bmp32.cpp Compile it with your favorite C++ compiler. I use the GCC: g++ -o bmp32 bmp32.cpp EasyBMP.cpp """ import pygame #----------------------------------------------------------------------------- def load( filename ): """ Load a 32-bit BMP image file containing per-pixel-alpha. You will probably want to call convert_alpha() on the result. Returns the new surface, or None on error. """ #........................................................................... def get_word( bytes ): result = 0 is_neg = bool( ord( bytes[ -1 ] ) >> 7 ) for shift, value in enumerate( bytes ): if is_neg: result -= (255 - ord( value )) << (shift *8) else: result += ord( value ) << (shift *8) if is_neg: return result -1 else: return result # Initialize ............................................................... try: f = open( filename, 'rb' ) data = f.read() f.close() # Assert: this is a Windows BMP if data[:2] != 'BM': raise Exception() pixel_data_offset = get_word( data[ 10:14 ] ) bitmap_info_header = data[ 14:(14+40) ] # Assert: this is a valid Windows BMP if get_word( bitmap_info_header[ :4 ] ) != 40: raise Exception() # Assert: image type is BI_RGB (not compressed) if get_word( bitmap_info_header[ 16:20 ] ) != 0: raise Exception() width = get_word( bitmap_info_header[ 4:8 ] ) height = get_word( bitmap_info_header[ 8:12 ] ) bitcount = get_word( bitmap_info_header[ 14:16 ] ) # Assert: bitmap has bitdepth of 32-bits per pixel if bitcount != 32: raise Exception() is_inverted = (height < 0) if is_inverted: height = -height # Load and store the image data .......................................... result = pygame.Surface( (width, height), pygame.SRCALPHA, 32 ) result.lock() try: for y in xrange( height ): if not is_inverted: y = height -y for x in xrange( width ): result.set_at( (x, y), (ord( data[ pixel_data_offset +2 ] ), # Red ord( data[ pixel_data_offset +1 ] ), # Green ord( data[ pixel_data_offset +0 ] ), # Blue ord( data[ pixel_data_offset +3 ] )) # Alpha ) pixel_data_offset += 4 finally: result.unlock() except: return None return result # end bmp32.py

It looks like the wiki code is broken when dealing with C++ include directives. That last line with iostream and fstream doesn't belong there.

Alas, I also can't figure out how to get rid of & lt; in the code block. If you copy this file, you'll have to do a search and replace to change them back to the less-than and left-shift operators.

--Duoas