Allegro.cc - Online Community

Allegro.cc Forums » Allegro Development » al_map_rgba vs. al_map_rgba_f

This thread is locked; no one can reply to it. rss feed Print
al_map_rgba vs. al_map_rgba_f
Felix-The-Ghost
Member #9,729
April 2008
avatar

I was testing al_clear_to_color to draw a colored bitmap on top of the back buffer, which was colored, and alpha in the al_map_rgba version doesn't behave like I'd think.

For example if the back buffer was red and the bitmap to draw was green (0 alpha) it would draw yellow as if it was combining them. I just add "_f" to "al_map_rgba" without changing arguments and it behaves as you'd think, with 0 alpha. :-/

==========================
<--- The ghost with the most!
---------------------------
[Website] [Youtube]

Edgar Reynaldo
Member #8,592
May 2007
avatar

J-Gamer
Member #12,491
January 2011
avatar

This code is from allegro 5.1:
al_map_rgba is defined like this:

ALLEGRO_COLOR al_map_rgba(
   unsigned char r, unsigned char g, unsigned char b, unsigned char a)
{
   ALLEGRO_COLOR color;
   _AL_MAP_RGBA(color, r, g, b, a);
   return color;
}

With _AL_MAP_RGBA expanding to:

#define _AL_MAP_RGBA(_color, _r, _g, _b, _a)                                  \
   do {                                                                       \ 
      (_color).r = _al_u8_to_float[_r];                                       \ 
      (_color).g = _al_u8_to_float[_g];                                       \ 
      (_color).b = _al_u8_to_float[_b];                                       \ 
      (_color).a = _al_u8_to_float[_a];                                       \ 
   } while (0) 

_al_u8_to_float is an array of 256 floats and is filled in _al_init_pixels like this:

   int i;
   for (i = 0; i < 256; i++)
      _al_u8_to_float[i] = i / 255.0;
}

The first entry in it should be 0. So it will put 0.0f as the .a component of the color struct, unless something fishy is going on.
al_map_rgba_f is way simpler, it just sets the values:

ALLEGRO_COLOR al_map_rgba_f(float r, float g, float b, float a)
{
   ALLEGRO_COLOR color;
   color.r = r;
   color.g = g;
   color.b = b;
   color.a = a;
   return color;
}

So unless there's some weird memory corruption, those two calls should have the same effect.

" There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo
"If your body was a business, thought would be like micro-management and emotions would be like macro-management. If you primarily live your life with emotions, then you are prone to error on the details. If you over-think things all the time you tend to lose scope of priorities." - Mark Oates

SiegeLord
Member #7,827
October 2006
avatar

J-Gamer said:

So unless there's some weird memory corruption, those two calls should have the same effect.

Or you didn't initialize Allegro.

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

J-Gamer
Member #12,491
January 2011
avatar

draw a colored bitmap on top of the back buffer

I don't think you can have a backbuffer if you don't initialize allegro. You will indeed run into the problem if you call al_map_rgba before initializing though.

" There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo
"If your body was a business, thought would be like micro-management and emotions would be like macro-management. If you primarily live your life with emotions, then you are prone to error on the details. If you over-think things all the time you tend to lose scope of priorities." - Mark Oates

Edgar Reynaldo
Member #8,592
May 2007
avatar

I just add "_f" to "al_map_rgba" without changing arguments and it behaves as you'd think, with 0 alpha.

Something important to note is that al_map_rgba_f takes values from 0.0 to 1.0, and al_map_rgba takes values from 0-255.

J-Gamer
Member #12,491
January 2011
avatar

If the argument given is 0, that makes no difference.

" There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo
"If your body was a business, thought would be like micro-management and emotions would be like macro-management. If you primarily live your life with emotions, then you are prone to error on the details. If you over-think things all the time you tend to lose scope of priorities." - Mark Oates

Edgar Reynaldo
Member #8,592
May 2007
avatar

Yes, I know that, thanks. I was pointing out that they take different parameters because it sounded like he was not aware of that.

Allegro uses pre multiplied alpha blending by default, for various reasons.

Quote:

// pre multiplied alpha blender, this is the default
al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA)

ALLEGRO_ADD

r = dr * dst + sr * src
g = dg * dst + sg * src
b = db * dst + sb * src
a = da * dst + sa * src

With src of (0,255,0,0) and dst of (1,0,0,?)

r = dr*(1-sa) + sr*1.0
g = dg*(1-sa) + sg*1.0
b = db*(1-sa) + sb*1.0

r = 1.0*(1-0) + 0*1 = 1
g = 0*(1-0) + 1*1 = 1
b = 0*(1-0) + 0*1 = 0

Which is yellow, and is exactly what you were getting.

Quote:

If you are using non-pre-multiplied alpha, you could use

al_set_blender(ALLEGRO_ADD, ALLEGRO_ALPHA, ALLEGRO_INVERSE_ALPHA)

Also, why are you trying to draw a fully transparent bitmap anyway? What's the point?

Arthur Kalliokoski
Second in Command
February 2005
avatar

Also, why are you trying to draw a fully transparent bitmap anyway? What's the point?

I bet he was trying to find out why partial transparency didn't work right either, like taking extreme cases. I do stuff like that all the time.

“Throughout history, poverty is the normal condition of man. Advances which permit this norm to be exceeded — here and there, now and then — are the work of an extremely small minority, frequently despised, often condemned, and almost always opposed by all right-thinking people. Whenever this tiny minority is kept from creating, or (as sometimes happens) is driven out of a society, the people then slip back into abject poverty. This is known as "bad luck.”

― Robert A. Heinlein

Felix-The-Ghost
Member #9,729
April 2008
avatar

I should have checked in earlier, I've since removed the code.
What I was doing exactly was testing al_clear_to_color with al_set_clipping_rectangle to see if I could "hide" parts of a fully opaque bitmap.

When I first read the manual entry for al_map_rgba_f I thought it meant that the alpha is 0-1 and the others were still 0-255 :/ Either way it was the al_map_rgba version that was using the alpha strangely (the color values themselves seemed to affect the alpha -- 0, 0, 0, 0 was not visibly the same as 255, 0, 0, 0)

Edit: Add this code to any program after rendering Buffer before copying it to the back buffer:

al_set_clipping_rectangle(5, 5, 20, 20); // target should be your buffer and rectangle can be anything in its bounds
al_clear_to_color(al_map_rgba(255, 0, 0, 0));
al_set_clipping_rectangle(0, 0, al_get_bitmap_width(Buffer), al_get_bitmap_height(Buffer));

That shows up as red to me, but if I change the al_map_rgba to al_map_rgba_f it works as I'd think it'd work, with 0 alpha meaning 0 alpha (aside from the fact that the color of a translucent alpha would be incorrect due to 255 not being between 0-1, but my point is alpha is working)

==========================
<--- The ghost with the most!
---------------------------
[Website] [Youtube]

Edgar Reynaldo
Member #8,592
May 2007
avatar

(the color values themselves seemed to affect the alpha -- 0, 0, 0, 0 was not visibly the same as 255, 0, 0, 0)

That's because the default blending mode use pre-multiplied alpha which means the dst in the blending formula will always be 1 - source alpha. If sa is 0, the dest is added at full intensity. If sa is 1, the destination is ignored. Since you're using ALLEGRO_ADD in the default blender, and ALLEGRO_ONE for src, the source will always be added to the resulting color, even with a source alpha of 0.

Quote:

ALLEGRO_ADD

r = dr * dst + sr * src
g = dg * dst + sg * src
b = db * dst + sb * src
a = da * dst + sa * src

where dst is (1-sa) and src is 1.

To use the default blender with a bitmap that you clear to a certain color, the color needs to be mulitiplied by the alpha first :

al_clear_to_color(al_map_rgba((r*a)/255) , (g*a)/255 , (b*a)/255 , a));

Then you could draw that bitmap normally with the default blender.

Edit

Quote:

That shows up as red to me, but if I change the al_map_rgba to al_map_rgba_f it works as I'd think it'd work, with 0 alpha meaning 0 alpha (aside from the fact that the color of a translucent alpha would be incorrect due to 255 not being between 0-1, but my point is alpha is working)

That's probably just a quirk of the fact that 255.0f is not between 0.0 and 1.0.

Felix-The-Ghost
Member #9,729
April 2008
avatar

Thanks for the info :)

==========================
<--- The ghost with the most!
---------------------------
[Website] [Youtube]

Go to: