Allegro.cc Forums » Programming Questions » Determine if an image is solid

 This thread is locked; no one can reply to it.
 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.or2) 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 Member #8,592 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) ```int is_bitmap_solid_color(BITMAP* bmp , int color) { if (!bmp) {return 0;} for (int y = 0 ; y < bmp->h ; ++y) { for (int x = 0 ; x < bmp->w ; ++x) { if (color != getpixel(bmp , x , y)) {return 0;} } } return 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.
 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 . Guess we can't have everything in life can we?[EDIT] I just noticed you put getpixel. I assume you meant al_get_pixel.
 Edgar Reynaldo Member #8,592 May 2007 You didn't specify A4 or A5, so I just used A4.Using A5 will be somewhat different :1) ```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) #SelectExpand 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.
 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:1. Use some heuristic to determine the areas where images are most likely to be different, and start comparison there (e.g., the center of an image is more likely to be distinctive than the edges)2. Upon loading each bitmap, create a digest hash and keep it around. Only do the per-pixel comparison when the hash matches. If your hash is large enough and has sufficient entropy, you might even take the risk of a hash collision and skip the pixel test altogether.3. Use a few quick checks to weed out obvious non-matches: differing sizes, color depths, file sizes, etc. ---Me make music: Triofobie---"We need Tobias and his awesome trombone, too." - Johan HalmÃ©n
 Audric Member #907 January 2001 Looks like ML already posted some code for fast image comparison:http://www.allegro.cc/forums/thread/606084/898790#targetIn the linked post he compared only edges, ie. lines on top, bottom, left and right.The critical code is: ``` // 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 Member #8,592 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.
 Go to: Allegro Development Installation, Setup & Configuration Allegro.cc Comments Off-Topic Ordeals The Depot Game Design & Concepts Programming Questions Recent Threads