Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » convert pixel formats

Credits go to Arthur Kalliokoski and Matthew Leverton for helping out!
This thread is locked; no one can reply to it. rss feed Print
convert pixel formats
Mark Oates
Member #1,146
March 2001
avatar

basically, I'm trying to figure out how to finish (do it correctly) this function :

inline uint32_t make_argb_8888(ALLEGRO_COLOR &col)
{
  unsigned char r = (int)(255 * col.r);
  unsigned char g = (int)(255 * col.g);
  unsigned char b = (int)(255 * col.b);
  unsigned char a = (int)(255 * col.a);

  // uh....
}

Something makes me think I should do
return (0x00ff0000 * r) + (0x0000ff00 * g) + (0x000000ff * b) + (0xff000000 * a);
and that's my best guess, but I don't know why.

Matthew Leverton
Supreme Loser
January 1999
avatar

(a << 24) | (r << 16) | (g << 8) | b

Arthur Kalliokoski
Second in Command
February 2005
avatar

If you had these four chars as a struct in a union with an int, you could skip the addition and multiplication in the return value by using the address offsets as a "multiplication" substitute.. IIRC that's the way A4 did it.

You might look into SSE if you don't care about portability.

“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

Mark Oates
Member #1,146
March 2001
avatar

Fantastic! Thanks Matthew.

My result:

unsigned char r, g, b, a;

inline uint32_t make_argb_8888(ALLEGRO_COLOR &col)
{
  al_unmap_rgba(col, &r, &g, &b, &a);
  return (a << 24) | (r << 16) | (g << 8) | b;
}

Would I get any real benefits using a union? It seems like it would just involve more shuffling and processor time.

Arthur Kalliokoski
Second in Command
February 2005
avatar

I tried timing them with clock(), but they seemed to run about equal. I didn't check that the logic is correct, but as long as I don't overrun arrays the times should be about what the "right" way would take.

click paperclip to get the test proglet.

[EDIT]

I had a brain fart blowing out the cache, naturally they'd be the same, but no matter what I do they run about equal (or at least bounce around as to which is faster). See t_v2.c in paperclip.

In short, Matthew's version would be better for conciseness.

“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

Dustin Dettmer
Member #3,935
October 2003
avatar

You should declare r, g, b, and a inside the function.

Arthur Kalliokoski
Second in Command
February 2005
avatar

I thought I did ??? Unless you mean the global arrays of floats and ints, simulating buffers in memory.

“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

Mark Oates
Member #1,146
March 2001
avatar

Quote:

I thought I did ???

He's talkin to me.

Wouldn't that slow down the function?

Arthur Kalliokoski
Second in Command
February 2005
avatar

The idea of locals on the stack being faster is due to the cache line already being loaded due to saving the return address. I'm not sure how an inlined function would work though, maybe I should check.

“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

Dustin Dettmer
Member #3,935
October 2003
avatar

It should speed it up.

Stuff inside a function goes into the cache, which is faster to play with than regular memory.

Also a smart compiler could turn them into registers -- which would be even faster.

Mark Oates
Member #1,146
March 2001
avatar

Go to: