Use embedded bitmap with Allegro 5
Gatleos

So, I'm trying to embed some small graphical resource files (in .bmp form) into my executable. The only way I've found to do this is with resource scripts, and loading the bitmaps into the program with the windows.h function LoadBitmap(). The problem is, the LoadBitmap() function returns a HBITMAP handle. And the Allegro library uses its own data type, ALLEGRO_BITMAP *. So, is there any way to load this embedded bitmap using Allegro, or do I have to use external files for my graphical resources?

Edgar Reynaldo

You'll have to write a function to convert an HBITMAP into an ALLEGRO_BITMAP*. Allegro 4 has these functions, named convert_hbitmap_to_bitmap and convert_bitmap_to_hbitmap. You should take a look at the Allegro 4 source code for these functions to see how they did it, and then adapt them to use Allegro 5 instead.

Gatleos

That seems like an awfully important thing to "forget" to port to Allegro 5... :-/

Anyway, thanks. This should help a lot!

EDIT: Wait... is there any documentation that shows the source code, or am I just going to have to download Allegro 4 and comb through the source?

Mark Oates

I've come to the conclusion that for most of your graphics, you should keep your bitmaps separate from your executable. For compactness may want to keep them in a dat or zip file. This can easily be done with the PhysicsFS addon.

The exception I've seen is if you want to set up some kind of system where you get a default fallback when the bitmap you're trying to access is missing. This can make sprint programming easier - a default_sound, default_font, default_bitmap, etc. In this case, you'd want to embed the image in the program.

For windows-specific programs you can do this relatively easily, but for cross-platform code you'll want to embed binary code. Here's an example where I embedded some binary, and loaded it as a memfile.

#SelectExpand
1ALLEGRO_BITMAP *default_image = NULL; // global, in this case // 2 3static bool create_default_image() 4{ 5 if (default_image) return true; 6 7 // default image, in png format: 8 unsigned char default_img[] = { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 9 0x0A, 0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 10 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x08, 0x06, 0x00, 0x00, 0x00, 11 0x3B, 0xD6, 0x95, 0x4A, 0x00, 0x00, 0x00, 0x19, 0x74, 0x45, 0x58, 12 0x74, 0x53, 0x6F, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x00, 0x41, 13 0x64, 0x6F, 0x62, 0x65, 0x20, 0x49, 0x6D, 0x61, 0x67, 0x65, 0x52, 14 0x65, 0x61, 0x64, 0x79, 0x71, 0xC9, 0x65, 0x3C, 0x00, 0x00, 0x00, 15 0xB3, 0x49, 0x44, 0x41, 0x54, 0x78, 0xDA, 0xA4, 0x53, 0x31, 0x0E, 16 0x83, 0x30, 0x0C, 0x8C, 0x51, 0xB6, 0xCE, 0x5D, 0x3A, 0x75, 0xE0, 17 0x09, 0x4C, 0xFC, 0x5F, 0x9D, 0x78, 0x42, 0x17, 0x16, 0x3A, 0x30, 18 0x33, 0x1B, 0x8C, 0xB8, 0xE8, 0x62, 0x82, 0x04, 0xF4, 0xA4, 0x28, 19 0xC9, 0xD9, 0x67, 0x27, 0x8E, 0x23, 0xAA, 0x1A, 0x3C, 0x44, 0x64, 20 0x47, 0x2E, 0x7E, 0xE2, 0xB9, 0x58, 0x12, 0x4D, 0xE3, 0xEB, 0x30, 21 0x20, 0x07, 0x11, 0x64, 0x36, 0x63, 0x49, 0xE4, 0xF1, 0x78, 0x0E, 22 0x29, 0x40, 0xE5, 0x85, 0x66, 0xB4, 0xE1, 0x05, 0xE0, 0xCC, 0x2F, 23 0x5D, 0x6B, 0xCB, 0x6C, 0x62, 0xC5, 0xCC, 0xEB, 0x23, 0xCE, 0x74, 24 0xB2, 0x11, 0xE1, 0x2A, 0xEC, 0x24, 0x91, 0x37, 0x67, 0x81, 0x64, 25 0xD1, 0x3D, 0x07, 0x8A, 0x17, 0xF8, 0x09, 0x79, 0x6F, 0x6B, 0x60, 26 0x2D, 0xD8, 0xAF, 0x7F, 0x5F, 0x3A, 0x32, 0xFC, 0xAB, 0xF0, 0x0F, 27 0x50, 0xED, 0x6F, 0xD7, 0xA2, 0x8A, 0x69, 0x06, 0x98, 0x27, 0xBF, 28 0x3C, 0xF3, 0x62, 0xC8, 0xEE, 0xE4, 0x3A, 0x6C, 0xB5, 0x67, 0x1C, 29 0x77, 0x18, 0x8C, 0x75, 0xF3, 0xD9, 0x89, 0xD9, 0x86, 0x0E, 0x13, 30 0x57, 0x55, 0x65, 0x47, 0x06, 0x02, 0x16, 0x7B, 0xFB, 0xCE, 0xAF, 31 0x9A, 0x05, 0x18, 0x00, 0xE7, 0x13, 0x9E, 0x16, 0xD5, 0x9E, 0x99, 32 0x41, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 33 0x60, 0x82 }; 34 35 //ALLEGRO_FILE *file = al_open_memfile(sizeof(default_img), default_img); // <-- 4.9.22 36 ALLEGRO_FILE *file = al_open_memfile(default_img, sizeof(default_img), "rw"); // <-- since 5.0.0 RC4 37 if (!file) std::cout << "memfile loading didn't work :(" << std::endl; 38 39 default_image = al_load_bitmap_f(file, ".png"); 40 if (!default_image) std::cout << "loading default_image didn't work :(" << std::endl; 41 else al_lock_bitmap(default_image, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READONLY); 42 43 al_fclose(file); 44 45 return true; 46}

This is a small 15x15 image. Larger binary data will quickly bloat using this technique. I've experimented with encoding/compressing/decompressing larger images with some success.

for more, search with something like "embed binary image in c++".

Gatleos

That code looks promising... I've already tried loading in images with XPM files, and I already have the code for it (no points for guessing what it's a picture of):

#SelectExpand
1/* XPM */ 2static char *SQUARE_xpm[]={ 3"180 180 2 1", 4" c #FF00FF", 5"0 c #FFFFFF", 6" 000000000000 000000000000 ", 7" 000000 000000 00 00 000000000000 000000000000 00000 0000 00000 00000000 ", 8" 00 00 00000000 00 00 0 0000 0000 000000000000 0000 0000 0000 000 00 00 00 0 00 00 ", 9" 0 0 00000000 0000 0000 000 0000 000000 000000000000 000000 000 000 000 0 00 00 00 0 00000000 ", 10" 0 0 0 0 00 00 00 000000000 00000 00000000 00000000 0000 0000 0000 000 000 00 00 00 000 0 00 00 00000 00 00 ", 11" 0 0 00000000 000000000 0000000 0000 0000 00000000 000000 000 000 00 00 00 0000 00 00000 0000 00 00 00 ", 12" 0 0000 0 00 00 0000000 0000000 0000 0000 000000 000000 000 000 00 00 00 0000 00 00 00 00 00 00 00 ", 13" 0 00 0 000 000 00000 00000 00 00 00 00 0000 0000 0000 000 000 00 00 00 00 00 000000 0000 00 000 ", 14" 00 00 00000000 000 000 00 00 000000000000 000000 000 000 00 00 00 00000 000 0000 ", 15" 000000 000000 0 0 000000 000000 000000000000 0000 0000 0000 0000 00 000 0000 00 ", 16" 000000000000 000000000000 00 ", 17" 000000000000 000000000000 ", 18" 0 0 ", 19" 00 00 00 00 00 0000000 000000 00 00 00 0 ", 20" 000 000 0000 00 00 00 00 00 00 00 0000 0000 00 0 ", 21" 00000 00000 000000 00 00 00 00 00 00 000000 000000 00 00 00 0 0 000 ", 22" 0000000 0000000 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 000 ", 23" 000000000 000000000 00 00 00 0000 00 00 00 00 00 00 00000000 00000000 00 0000000000 00000 ", 24" 0000000 0000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00000 ", 25" 00000 00000 000000 00 00 0000 0000000000 000000 00 000000 00 00 0000000 0 0 0000000 ", 26" 000 000 0000 00 00 00 00 00 0000000000 0000 00 0000 0000000 ", 27" 00 00 00 00 00 00 00 00 00 0000000000 00 00 00 000000000 ", 28" 0 0 000000 000000 000000000 ", 29" ", 30" 00 ", 31" 00 00 00 00 00 00 000 00 00 00 ", 32" 0000 00 00 00 00 00000 00 00 00 00 00 ", 33" 0000 00 00 0000000 00 00 0 00 00 00 00 00 00 00 00 ", 34" 0000 0 0 00 00 00 00 00 000 00 00 00 0000 00 ", 35" 00 00 00 0000 00 00000 0 00 00 00000000 000000 000000000 ", 36" 00 00 00 00 00 00 0000 00 00 0000 000000 ", 37" 0000000 00 00 00 00 00 00 00 00 00 ", 38" 00 00 00 00000 00 00 00 000 00 00 00 000 000 ", 39" 00 00 00 00 0 00 000 00 00 00 000 000 ", 40" 00 00 ", 41" ", 42" ", 43" 00000 0 0000 0000 00 000000 000 0000000 0000 0000 00 00 ", 44" 00 00 00 00 00 00 00 000 00 00 00 00 00 00 00 00 00 00 ", 45" 00 000 0000 00 00 00 0000 00 00 00 00 00 00 00 00 000 000 00 00 ", 46" 00 0000 00 00 00 00 00 00 00 00 000 00 00 00 000 000 00 000000 00 ", 47" 00 0 00 00 00 000 00 00 00000 00000 00 0000 00000 00 00 ", 48" 0000 00 00 00 00 0000000 00 00 00 00 00 000 00 00 000000 00 ", 49" 000 00 00 00 00 00 00 00 00 00 00 00 00 000 000 00 00 ", 50" 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000 000 00 00 ", 51" 00000 000000 000000 0000 0000 0000 0000 00 0000 000 00 00 00 ", 52" 00 ", 53" ", 54" ", 55" 00000 00 000000 0000 00000 0000000 0000000 0000 00 00 0000 0000 000 00 0000 00 00 00 00 ", 56" 00 00 0000 00 00 00 00 00 00 00 0 00 00 00 00 00 00 00 00 00 00 00 000 000 00 00 ", 57" 00 00 00 00 00 00 00 00 00 00 00 00 0 00 00 00 00 00 00 00 00 00 0000000 000 00 ", 58" 00 0000 00 00 00 00 00 00 00 00 0 00 0 00 00 00 00 00 00 00 00 0000000 0000 00 ", 59" 00 0000 00 00 00000 00 00 00 00000 00000 00 000000 00 00 0000 00 00 0 00 0000000 ", 60" 00 0000 000000 00 00 00 00 00 00 0 00 0 00 000 00 00 00 00 00 00 00 00 0 00 00 00 0000 ", 61" 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000 ", 62" 00 00 00 00 00 00 00 00 00 00 0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ", 63" 00000 00 00 000000 0000 00000 0000000 0000 00000 00 00 0000 0000 000 00 0000000 00 00 00 00 ", 64" ", 65" ", 66" 0 ", 67" 000000 000 000000 0000 000000 00 00 00 00 00 00 00 00 00 00 0000000 0000 0 0000 000 ", 68" 00 00 00 00 00 00 00 00 0 00 0 00 00 00 00 00 00 00 00 00 00 00 000 00 00 00 00 00 ", 69" 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0 00 00 00 00 00 00 ", 70" 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 ", 71" 00000 00 00 00000 000 00 00 00 00 00 00 0 00 00 0000 00 00 00 00 ", 72" 00 00 000 00 00 00 00 00 00 00 00 00 0 00 0000 00 00 00 00 00 ", 73" 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0 00 00 00 ", 74" 00 00000 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 ", 75" 0000 00 000 00 0000 0000 0000 00 00 00 00 00 0000 0000000 0000 0 0000 ", 76" 0000 ", 77" ", 78" 00 ", 79" 00 000 000 000 000 00 00 000 0000 ", 80" 00 00 00 00 00 00 00 00 00 00 ", 81" 00 00 00 00 00 00 ", 82" 0000 00000 0000 00000 0000 00 000 00 00 00 0000 0000 00 00 00 000000 00000 ", 83" 00 00 00 00 00 00 00 00 00 00000 00 00 000 00 00 00 00 00 00 00 0 00 00 00 ", 84" 00000 00 00 00 00 00 000000 00 00 00 00 00 00 00 0000 00 00 0 00 00 00 ", 85" 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0 00 00 00 ", 86" 00 00 00 00 00 00 00 00 00 00 00 00000 00 00 00 00 00 00 00 00 0 00 00 00 ", 87" 000 00 00 000 0000 000 00 0000 0000 00 000 00 000000 00 00 000 00 000000 00 00 00 00 ", 88" 00 00 00 00 ", 89" 0000 0000 ", 90" ", 91" 000 00 000 000 00 ", 92" 0 00 00 00 00 00 0 ", 93" 00 00 00 00 00 000 ", 94" 00 000 000 00 000 00 0000 000000 00 00 00 00 00 00 00 00 00 00 000000 00 00 00 ", 95" 00 00 00 00 00 000 00 00 00 00 00 00 00 00 00 00 00 00 00 0 00 00 00 ", 96" 00 00 00 00 000 00 00 00 00 00 00 00 00 0 00 000 00 00 00 00 00 00 ", 97" 00 00 00 00 00 00 00 00 00 00 00 00 0 00 000 00 00 00 00 00 00 ", 98" 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 0000 00 0 00 00 00 ", 99" 00000 00000 0000 0000 000 000 00 00 00 00 00 00 00 000000 000 00 000 ", 100" 00 00 00 ", 101" 0000 0000 0000 ", 102" 00 00 00 000 00 00 0 00 ", 103" 0000 00 00 00 0000 00 00 00 00 00 0000 00 00 00 00 00 000 00 00 00 ", 104" 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ", 105" 00 00 000 00 ", 106" 00 00 00 0000 0000 0000 0000 00000 0000 0000 0000 0000 0000 0000 0000 0000 ", 107" 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ", 108" 00 00 00 000000 00000 00000 00000 00000 00 000000 000000 000000 00 00 00 00 00 ", 109" 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000000 ", 110" 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ", 111" 0000 000 00 0000 000 00 000 00 000 00 000 00 0000 00000 00000 00000 000000 000000 000000 00 00 ", 112" 00 00 ", 113" 0000 0000 ", 114" 00 00 00 00 00 00 00 00 00 0000 00 00 0000 ", 115" 00 00000 0000 00 00 00 0000 00 00 00 00 00 00 00 00 0 0 ", 116" 00 0000 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 0 0 ", 117" 000000 00 00 00 00 00 00 0000 00 00 00 0 0 ", 118" 00 0 0000000 00 00 0000 0000 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 0000 ", 119" 00 00 00 0000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000000 000000 0 0 ", 120" 00000 0000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0 0000 ", 121" 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000000 0 00 ", 122" 00 0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 0000 00 00 0 00 0 ", 123" 000000 000 0000 00 0000 0000 0000 0000 000 00 000 00 00 0000 0000 00 0000000 00 0 00 ", 124" 00 00 ", 125" 0000 ", 126" 00 00 00 00 000 00 ", 127" 00 00 00 00 000 00 00 000 0000 0000 00 00 00 00 00 00 ", 128" 00 00 00 00 00 000 00 00 00 00 00 000 00 000 00 00 ", 129" 00 00 00 00 00 00 00 00 00 00 ", 130" 0000 0000 0000 00 00 00000 000 00 000000 0000 00 00000000 00000000 00 00 00 00 00 00 00 ", 131" 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 000 00 00 00 ", 132" 00000 00 00 00 00 00 00 00 00 0000 0000000 0000000 00 00 00 00 0000 00 0000 0000 00 00 ", 133" 00 00 00 00 00 00 00 00 00 00 000 00 00 00 00 00 00 00 00 0000 00 00 ", 134" 00 00 00 00 00 00 00 00 00 00 00 00 00 0 00 0 00 00 0000 00 00 ", 135" 000 00 000000 0000 000 00 00 00 00 00 0000 00 000000 00 00 00 ", 136" 00000 00 ", 137" ", 138"0 0 0 0 0 0 0 0 0 0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ", 139" 0 0 0 0 0 0 0 0 0 0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ", 140" 0 0 0 0 0 0 0 0 0 00 00 00 00 0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ", 141"0 0 0 0 0 0 0 0 0 0 00 00 00 00 00 00 0000000 00 00 0000000 00000 00 00 00 000000000 00000 00 00 00 0000000 ", 142" 0 0 0 0 0 0 0 0 0 000 00 00 00 00 00 0000000 00 00 0000000 00000 00 00 00 000000000 00000 00 00 00 0000000 ", 143" 0 0 0 00 0 0 0 0 0 0 00 00 00 0 00 0000000 00 00000 00 000000000 00 00 00 00 00 00 000000000 00 ", 144"0 0 0 0 0 0 0 0 0 0 00 00 00 00 00 0000000 00 00000 00 000000000 00 00 00 00 00 00 000000000 00 ", 145" 0 0 0 0 0 0 0 0 0 0 00 00 00 00 00 00 0000000 00 00 00 00 0000000 00000 00 00 00 00000 00 000000000 0000000 ", 146" 0 0 0 0 0 0 0 0 0 00 00 00 00 0 00 00 0000000 00 00 00 00 0000000 00000 00 00 00 00000 00 000000000 0000000 ", 147"0 0 0 0 0 0 0 0 0 0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ", 148" 0 0 0 0 0 0 0 0 0 000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ", 149" 0 0 0 00 0 0 0 0 0 0 00 00 00 0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ", 150" 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ", 151" 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ", 152" 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ", 153" 00 00 00 00 0000000 00 00 00 00000 00000000000000 00000000000000000 00 0000000000000000000000 00000", 154" 00 00 00 00 0000000 00 00 00 00000 00000000000000 00000000000000000 00 0000000000000000000000 00000", 155" 0000000000000000000000000000000 0000000000000000000000000000000 00 00 00000 00 00 00 ", 156" 0000000000000000000000000000000 0000000000000000000000000000000 00 00 00000 00 00 00 ", 157" 00 00 00 0000000 00 00 000000000 00 0000000000000000000000 00000 00 0000000000000000000000 00000", 158" 00 00 00 0000000 00 00 000000000 00 0000000000000000000000 00000 00 0000000000000000000000 00000", 159" 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ", 160" 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ", 161" 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ", 162" 00 00 00 00 00 00 00 00 00 000000000000 000000 000000", 163" 00 00 00 00 00 00 00 00 00 000000000000 000000 000000", 164" 00 00 00 00 00 00 00 00 00 000000000000 000000 000000", 165" 00 00 000000000000 00 00 0000000 0000000 00 00 000000000000 00 000000000000 000000 000000", 166" 00 00 000000000000 00 00 0000000 0000000 00 00 000000000000 00 000000000000 000000 000000", 167"000000000000 000000000000000000000000 00 00 00000000000000 00000 0000000 0000000000000000000 000000 000000", 168"000000000000 000000000000000000000000 00 00 00000000000000 00000 0000000 0000000000000000000000000000000000000 000000", 169" 000000000000 00 00 0000000 0000000 00 00 00 00 000000000000 00 000000000000000000000000000000 000000", 170" 000000000000 00 00 0000000 0000000 00 00 00 00 000000000000 00 000000000000000000000000000000 000000", 171" 00 00 00 00 00 00 00 00 00 00 000000000000000000000000000000 000000", 172" 00 00 00 00 00 00 00 00 00 00 000000000000000000000000000000 000000", 173" 00 00 00 00 00 00 00 00 00 00 000000000000000000000000000000 000000", 174" ", 175" 0000 000000 00000000 000000 000000 0000 00000 0000 0000 ", 176" 00 00 00 00 00 00 00 0 00 00 00 00 00 00 00 00 ", 177" 000 00 00 00 00 00 00 00 00 0 000 00 0000 00 00 00 00 00 000 00 00000 00 ", 178" 00 0000 00 00 00 00 00 00 000000 00 00 00 000 00 00 00 00 00 00 0000 00 00 00 00 0000 00 ", 179" 00 00 00 00 00 00 00 00 00 0 00 00 00 00 00 000000 00 00 00 00 00 00 00 00 0 00 000000 ", 180" 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 ", 181" 00 0000 00 00 00 00 00 00 0 00 00 00 00 00 0000 00 00 00 00 00 00 00 000 00000 00 ", 182" 000 00 00000 00 00 00 00 0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ", 183" 00 00 00 00 000000 0000 0000 00 000 000000 0000 000 000 0000 0000 ", 184" 00 00 ", 185" 00 "};

Is there a good way to load in XPM files with the same method?

Mark Oates
Gatleos said:

Is there a good way to load in XPM files with the same method?

I don't think there is a native allegro function for loading xpm files. But it doesn't look like it would be to hard to write.

Gatleos

Okay, that leaves one question: how does al_load_bitmap_f load the bitmap from the memfile? Is the memfile just an array of contiguous memory? Does each "cell" in the array represent the color of one pixel? What values should I assign to them to get different colors?

I guess that was more than one question.

Trent Gamblin

If you're going to go the "use only built-in stuff" route, then just convert the xpm to a png or some other supported format and put the array of bytes in your code. If you want to use xpm, then you'll have to write a loader which you can register with the image addon.

Allegro (and most other graphics stuff) pack pixels into (most commonly) 16 or 32 bits per pixel. The easiest way to load that image you have there, assuming you want spaces to be blank and Os to be white, is to do something like that:

const char *myimage = {
   0x200, 0x0, // put width here (this shows 16 bit little endian format)
   0x200, 0x0, // height
   // your xpm here
   0, 0, 1, // continue for all bytes (I'm assuming it's monochrome here, see below)
};

When you load the image, read the width and height then you get to the pixels. If it's monochrome then each byte could represent the color. If you want lots of colors, say 32 bit color, then you'd use 4 bytes per pixel. Look up "endianness" on wikipedia for all the info about storing multibyte patterns in memory. I'll assume you're using monochrome images here.

Allegro let's you grab a memory buffer for an image and read/write to it as an array of bytes which represents the colors. Probably the easiest format to read and write is ALLEGRO_PIXEL_FORMAT_ABGR_8888_LE. Here's some code for loading an image as described above.

#SelectExpand
1int count = 0; 2int width = myimage[0] | (myimage[1] << 8); // read about endianness to understand this 3count += 2; 4int height = myimage[2] | (myimage[3] << 8); 5count += 2; 6ALLEGRO_BITMAP *bmp = al_create_bitmap(width, height); 7al_set_target_bitmap(bmp); 8al_clear_to_color(al_map_rgba_f(0, 0, 0, 0)); // clear the bitmap to pure alpha 9ALLEGRO_LOCKED_REGION *lr = al_lock_bitmap(bmp, ALLEGRO_PIXEL_FORMAT_ABGR_8888_LE); 10 11for (int y = 0; y < height; y++) { 12 // uint32_t is an integer type that is always 32 bits big. 13 // this creates a pointer that points to the beginning of each row of the bitmap. 14 // as you go through the loop it's reset to the next line and so on. 15 uint32_t *ptr = ((unsigned char *)lr->data + lr->pitch * y); 16 for (int x = 0; x < width; x++) { 17 int byte = myimage[count++]; 18 uint32_t result; 19 unsigned char r, g, b, a; // red, green, blue, alpha from 0-255 (none to full) 20 if (byte == 0) { 21 r = g = b = a = 0; // zero byte is pure alpha 22 } 23 else { 24 r = g = b = a = 255; // 1 is pure white 25 } 26 // assemble the pixel. We locked it as ABGR_8888_LE which means the first byte 27 // is red, second green, third blue and last alpha 28 result = r | (g << 8) | (b << 16) | (a << 24); 29 // These two lines first assign the resulting pixel we created to the current 30 // position in the bitmaps memory buffer, then advance that position by 1 pixel. 31 (*ptr) = result; 32 ptr++; 33 } 34} 35 36al_unlock_bitmap(bmp);

Voila, you've loaded a bitmap (though the code is untested). You can simplify it by using al_put_pixel but that's significantly slower if you're using a lot of these bitmaps.

Mark Oates
Gatleos said:

Is the memfile just an array of contiguous memory? Does each "cell" in the array represent the color of one pixel? What values should I assign to them to get different colors?

Yes. No. You can't.

That's a png file (which was created using photoshop, and then later viewed as binary in hex in a hex editor). I typed the hex into an array, put it into a virtual file, and then tell allegro to open it like it was png file. You can't just change a value and change a pixel, it's a little more intricate than that.

Since you know the width and height of your image and you know exactly what images you're going to use, there's no need to include that in any new image format you may come up with. And you also wouldn't need to come up with any color definitions, either.

In your case, probably easiest to just make an array of chars, where each char represents a color, getting those colors in a function:

inline ALLEGRO_COLOR get_color_from_char(char c)
{
   switch(c)
   {
      case 'x': return al_color_name("green");
      case 'y': return al_color_name("orange");
      case '#': return al_map_rgba_f(0.5f, 0.5f, 0.5f, 0.5f);
      // etc //
      default: return al_color_name("black");
   }
}

And compose your image with something like this (also untested):

#SelectExpand
1ALLEGRO_BITMAP *load_my_pic(char *array, int width, int height) 2{ 3 ALLEGRO_BITMAP *bitmap = al_create_bitmap(width, height); 4 ALLEGRO_STATE state; 5 al_store_state(&state, ALLEGRO_STATE_TARGET_BITMAP); 6 al_lock_bitmap(bitmap, al_get_bitmap_format(bitmap), ALLEGRO_LOCK_WRITEONLY); 7 al_set_target_bitmap(bitmap); 8 al_clear_to_color(al_map_rgba_f(0, 0, 0, 0)); 9 10 for (int y=0; y<height; y++) 11 { 12 for (int x=0; x<width; x++) 13 { 14 al_put_pixel(x, y, get_color_from_char(array[x + y*width])); 15 } 16 } 17 18 al_restore_state(&state); 19 al_unlock_bitmap(bitmap); 20 return bitmap; 21}

al_put_pixel but that's significantly slower if you're using a lot of these bitmaps.

actually.... I profiled some different methods a while back and found that al_put_pixel performed as fast (marginally faster) than packing the bits manually (you have to lock the bitmap other wise it's slow as molasses, obviously). I had a thread on it some time back.

No matter what the performance was too slow for real-time use beyond 10,000pixels/frame or so if I recall correctly. I would only use it for loading and such.

Edgar Reynaldo

         al_put_pixel(x, y, get_color_from_char(array[x+y]));

Shouldn't that be array[y*width + x] there?

Gatleos said:

That seems like an awfully important thing to "forget" to port to Allegro 5... :-/

Anyway, thanks. This should help a lot!

EDIT: Wait... is there any documentation that shows the source code, or am I just going to have to download Allegro 4 and comb through the source?

The functions are in allegro\src\win\gdi.c on lines 505-535 and 539-568. They use several helper functions though, so you'll have to look those up yourself. I suggest using grep for windows to do it.

Mark Oates

Shouldn't that be array[y*width + x] there?

Dangit! I made that same mistake a week ago and it took me ~15 min to debug!

Gatleos

Thanks for all the help! You were right; I already know the size of the bitmap in question, only one bitmap will be loaded at a time, and it's only got two colors, one of which is transparency. So it's pretty simple, I just needed to know how to load it in.

Thanks again!

Matthew Leverton

This won't really help you much but I just had to write some ALLEGRO_BITMAP to HBITMAP code.

I think you can get by with using GetDIBits to go in the other direction, along with some supporting code similar to what I've linked above.

Desmond Taylor

There is a simple way of doing this with WindowsAPI. But LennyLen's code should work for you and his is cross platform load_PE_bmp. It opens PE files and should also get the bitmap data from the executable. He has posted an example of using it and the source is also included so you can see how he done it.

Trent Gamblin

actually.... I profiled some different methods a while back and found that al_put_pixel performed as fast (marginally faster) than packing the bits manually (you have to lock the bitmap other wise it's slow as molasses, obviously). I had a thread on it some time back.

That's quite not possible since al_put_pixel packs the bits itself and then you have the extra function call overhead. If done right (and I've benchmarked this too), manual locking and packing is quite a lot faster. And even if it was inline, you have to pack and unpack pixels into ALLEGRO_COLORs on top of it.

Thread #607852. Printed from Allegro.cc