![]() |
|
Determine if an image is solid |
Nazerith
Member #12,551
February 2011
|
Hey guys. I'm working with a bitmap image from an old piece of software (2001-ish). The image is a tile sheet of tiles used in the game. I'm creating a map editor for the game, so I need to read and write the map files in the exact same format. In the map files, tiles are numerically ordered starting from one, based on the order they appear in the sheet (tiles are 100x100 pixels). However, not all spots in the sheet contain images. In some cases, the spot is filled in with a single color (which the program uses as transparent on its tile). In cases where a tile is absent, that spot is skipped for the purposes of assigning numbers to the tiles. So I need a way to do one of two things: 1) Test if a bitmap is a solid color. or 2) Test if two bitmaps are equal. I couldn't find a function for either in allegro, and I was curious if I missed it. Worse comes to worse, I'll write the function if it doesn't exist, but prefer not to do that if I can avoid it. Or am I just missing a totally obvious solution? I kinda feel like I am. |
Trent Gamblin
Member #261
April 2000
![]() |
I'd be interested in a solution that doesn't have to compare every pixel (i.e., is faster than doing that). I don't know of one. Allegro does not have either function though.
|
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
Nazerith said: 1) Test if a bitmap is a solid color. 2) Test if two bitmaps are equal. You'll have to do both yourself. The first is easy, and the second is only slightly harder. 1) 2) int are_bitmaps_equal(BITMAP* b1 , BITMAP* b2) { if (!b1 || !b2) {return 0;} if (b1 == b2) {return 1;} if (bitmap_color_depth(b1) != bitmap_color_depth(b2)) {return 0;} if ((b1->w != b2->w) || (b1->h != b2->h)) {return 0;} for (int y = 0 ; y < b1->h ; ++y) { for (int x = 0 ; x < b1->w ; ++x) { if (getpixel(b1,x,y) != getpixel(b2,x,y)) {return 0;} } } return 1; } I just wrote them myself, since they only took a couple minutes. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Nazerith
Member #12,551
February 2011
|
Appreciate the effort Edgar. I knew how to write them, but was hoping for a more elegant solution than a per pixel comparison [EDIT] I just noticed you put getpixel. I assume you meant al_get_pixel. |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
You didn't specify A4 or A5, so I just used A4. Using A5 will be somewhat different : int is_bitmap_solid_color(ALLEGRO_BITMAP* bmp , ALLEGRO_COLOR color) { if (!bmp) {return 0;} al_lock_bitmap(bmp , al_get_bitmap_format(bmp) , ALLEGRO_LOCK_READONLY); for (int y = 0 ; y < al_get_bitmap_height(bmp) ; ++y) { for (int x = 0 ; x < al_get_bitmap_width(bmp) ; ++x) { if (color != al_get_pixel(bmp , x , y)) { al_unlock_bitmap(bmp); return 0; } } } al_unlock_bitmap(bmp); return 1; } 2) 1int are_bitmaps_equal(ALLEGRO_BITMAP* b1 , ALLEGRO_BITMAP* b2) {
2 if (!b1 || !b2) {return 0;}
3 if (b1 == b2) {return 1;}
4 if (al_get_bitmap_format(b1) != al_get_bitmap_format(b2)) {return 0;}
5 if ((al_get_bitmap_width(b1) != al_get_bitmap_width(b2)) ||
6 (al_get_bitmap_height(b1) != al_get_bitmap_height(b2))) {return 0;}
7
8 al_lock_bitmap(b1 , al_get_bitmap_format(b1) , ALLEGRO_LOCK_READONLY);
9 al_lock_bitmap(b2 , al_get_bitmap_format(b2) , ALLEGRO_LOCK_READONLY);
10
11 for (int y = 0 ; y < al_get_bitmap_height(b1) ; ++y) {
12 for (int x = 0 ; x < al_get_bitmap_width(b1) ; ++x) {
13 if (al_get_pixel(b1,x,y) != al_get_pixel(b2,x,y)) {
14 al_unlock_bitmap(b1);
15 al_unlock_bitmap(b2);
16 return 0;
17 }
18 }
19 }
20 al_unlock_bitmap(b1);
21 al_unlock_bitmap(b2);
22 return 1;
23}
A5 takes more code. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Nazerith
Member #12,551
February 2011
|
[EDIT] Text removed because I am dumb. |
Audric
Member #907
January 2001
|
With allegro 4 bitmaps, you could use memcmp() on each bmp->line[y] to speed up the comparison. It would also avoid the bit-shifting that occurs in al_get_pixel() to re-order the R G B components. |
Tobias Dammers
Member #2,604
August 2002
![]() |
Trent Gamblin said: I'd be interested in a solution that doesn't have to compare every pixel (i.e., is faster than doing that). I don't know of one. Allegro does not have either function though.
For checking whether two images are exactly identical, I can think of a few optimizations: --- |
Audric
Member #907
January 2001
|
Looks like ML already posted some code for fast image comparison: // Do once b1_lock = al_lock_bitmap(b1, ALLEGRO_PIXEL_FORMAT_ARGB_8888, ALLEGRO_LOCK_READONLY); b2_lock = al_lock_bitmap(b2, ALLEGRO_PIXEL_FORMAT_ARGB_8888, ALLEGRO_LOCK_READONLY); b1_data = b1_lock->data; b2_data = b2_lock->data; // Do for each y line of bitmaps: if (memcmp( (uint8_t*)&b1_data[x1] + b1_lock->pitch * (y1+y), (uint8_t*)&b2_data[x2] + b2_lock->pitch * (y2+y), width)) {...} // is different (with x1,y1 the coordinates of the block in bitmap b1, and x2,y2 the coordinates in bitmap b2) |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
You should use al_get_bitmap_format(bmp) as the 2nd parameter to pass to al_lock_bitmap though, otherwise format conversion would slow it down. And you should also use width*locked_region.pixel_size as the number of bytes to compare. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
|