memcmp for comparing colors
A. van Patmos

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

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

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

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

basically_equal()

I use a threshold of 0.0001 in the header file.

SiegeLord

1 / 256.0 should be enough for any practical purpose.

A. van Patmos

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

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

Mark Oates

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.

Elias
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.

Thread #616050. Printed from Allegro.cc