Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » memcmp for comparing colors

This thread is locked; no one can reply to it. rss feed Print
memcmp for comparing colors
A. van Patmos
Member #15,349
October 2013

I want to compare colors of pixels (using 5.0.10) and after reading this:
https://www.allegro.cc/forums/thread/607895 I tried the following:

if(!memcmp(al_map_rgb(255,0,255), al_get_pixel(magenta, ev.mouse.x + cameraX, ev.mouse.y + cameraY), sizeof(ALLEGRO_COLOR);

where

magenta = al_load_bitmap("pictures/01magnta.bmp");

and

al_lock_bitmap(magenta, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READONLY)

The compiler says: error: incompatible type for argument 1 of 'memcmp'. The same for argument 2.
Do I need to declare variables

ALLEGRO_COLOR var1 = al_map_rgb(255,0,255)
ALLEGRO_COLOR var2 = al_get_pixel(magenta, ev.mouse.x + cameraX, ev.mouse.y + cameraY)

To get this to work? Or am I doing something wrong in the memcmp statement?

RPG Hacker
Member #12,492
January 2011
avatar

AFAIK, memcmp takes pointers to memory. So yeah, you should delcare var1 and var2 like that and then pass &var1 and &var2 to memcmp.

A. van Patmos
Member #15,349
October 2013

I misunderstood memcmp and maybe I still do.
So the idea is that if clicked on the playing field the color of the same (x,y) pixel gets read from the bitmap called veld_magenta (and copied to proefpixel). I have this:

#SelectExpand
1ALLEGRO_BITMAP *veld_magenta; 2veld_magenta = al_load_bitmap("m01mgnta.bmp"); 3... 4ALLEGRO_COLOR magenta = al_map_rgb(255,0,255); 5ALLEGRO_COLOR proefpixel; 6... 7al_lock_bitmap(veld_magenta, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READONLY); 8... 9if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN && ev.mouse.button & 1) 10 { 11 proefpixel = al_get_pixel(veld_magenta, ev.mouse.x + cameraX, ev.mouse.y + cameraY); 12 if(memcmp(&magenta, &proefpixel, sizeof(ALLEGRO_COLOR)) != 0) 13 { 14 if(muisinterval < 30) 15 { 16 if(COMANDO) 17 Com.dubbelklik = true; //printf("Dubbelklik %i \n", muisinterval); 18 } 19 else 20 if(COMANDO) 21 Com.dubbelklik = false; //printf("Enkel %i \n", muisinterval); 22 muisinterval = 0; 23 24 if(COMANDO) 25 { 26 Com.doelX = ev.mouse.x + cameraX; 27 Com.doelY = ev.mouse.y + cameraY; 28 ... 29 } 30 } 31 }

Now mr. Com moves to any place no matter where I click. That's the same as not having the condition at all. Setting the memcmp condition to '== 0' makes him not move at all. (I'd expect him to move to magenta areas but he is consistent.)
I checked with ImageMagick's identify tool if magenta really is magenta in the bitmap and not 254,0,254 or so but it's 255,0,255 according to the program.
So what am I doing wrong?

bamccaig
Member #7,536
July 2006
avatar

This could be a good place to abstract the comparison into a separate function (assuming the overhead of another call isn't significant, and usually it wouldn't be). That way you can focus on testing just the comparison in isolation and once you're confident that it works properly you can focus on the rest. That also simplifies this function that is actually doing things with the comparison.

int al_ext_color_equals(
    ALLEGRO_COLOR * lhs,
    ALLEGRO_COLOR * rhs)
{
    int ret = memcmp(lhs, rhs, sizeof(ALLEGRO_COLOR));

    return ret == 0;
}

Note also ML's advice in the referenced thread. Since the color values are floats you may want to approximate the comparison to catch almost equal colors. That's up to you. I'm not sure how likely (or unlikely) it is for color attributes to be approximately different using whatever technique that they're being created from...

When you're trying to debug code it's important to isolate the specific part that's buggy.

Mark Oates
Member #1,146
March 2001
avatar

basically_equal()

I use a threshold of 0.0001 in the header file.

--
Visit CLUBCATT.com for cat shirts, cat mugs, puzzles, art and more <-- coupon code ALLEGRO4LIFE at checkout and get $3 off any order of 3 or more items!

AllegroFlareAllegroFlare DocsAllegroFlare GitHub

SiegeLord
Member #7,827
October 2006
avatar

1 / 256.0 should be enough for any practical purpose.

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

A. van Patmos
Member #15,349
October 2013

Thanks so far people. Should the following:

ALLEGRO_COLOR magenta = al_map_rgb(255,0,255);
printf("%f\n", magenta.r);printf("%f\n", magenta.g);printf("%f\n", magenta.b);

not print this?
1.000000
0.000000
1.000000

Bruce Pascoe
Member #15,931
April 2015
avatar

Mark: C++ supports default parameter values? When did this happen, or was that always supported?

Mark Oates
Member #1,146
March 2001
avatar

Yea, it's always been there (if I understand you correctly).

You have to put the default parameters in the declaration (not the definition), which means they usually go in the header file. It kinda sucks because I like the idea that your default params are controlled by the library and not the header files.

Also, parameters with defaults have to be the last ones in the list (You can't add parameters without defaults after). C++ doesn't support named parameters, unfortunately.

--
Visit CLUBCATT.com for cat shirts, cat mugs, puzzles, art and more <-- coupon code ALLEGRO4LIFE at checkout and get $3 off any order of 3 or more items!

AllegroFlareAllegroFlare DocsAllegroFlare GitHub

Elias
Member #358
May 2000

SiegeLord said:

1 / 256.0 should be enough for any practical purpose.

Well, with texture compression and whatnot, a color component may get shrunk down to less than that, then when you read back from the texture you lose a lot of precision. For example if all that happens is that the texture internally uses 16-bit 565 format, then a color of 255, 255, 255 will end up as 31, 63, 31 and read back as: 248, 252, 248. So the difference is 255/256 - 248/256 = 7 / 256.

So I'd say 7 / 256.0 is a safer bet than 1 / 256.0 if you happen to read colors back from a texture or the screen.

--
"Either help out or stop whining" - Evert

Go to: