Yana D. Nugraha
Yana D. Nugraha

Reputation: 5309

How can I convert from DWORD RGBA to ints?

I have to convert a DWORD (unsigned long) RGBA to four int vars (R, G, B, and A) So far, I have this function to convert the 4 ints to a DWORD:

unsigned long RGBA2DWORD(int iR, int iG, int iB, int iA)
{
    return ((iA << 24) | (iR << 16) | (iG << 8) | iB);
}

How can I convert it back?

Something like

struct RGBA
{
    int R, G, B, A;
};

RGBA DWORD2RGBA(unsigned long dwColor)
{
    static RGBA tmp;
    //.......conversion process
    return tmp;
}

Any kind of help would be appreciated! :)

Thanks

Upvotes: 5

Views: 9932

Answers (4)

Izzy
Izzy

Reputation: 412

Actually the RGBA part of unsigned long should be:

int iR = (value) & 0xff;
int iG = (value >> 8) & 0xff;
int iB = (value >> 16) & 0xff;
int iA = (value >> 24) & 0xff;

and the whole question is about BGRA (according to question's example) rather than RGBA.

Upvotes: 1

AnT stands with Russia
AnT stands with Russia

Reputation: 320501

If I were you, I'd stick with multiplicative-additive operations in the packing/unpacking functions. Something like this

unsigned long RGBA2DWORD(int iR, int iG, int iB, int iA)
{        
  return ((iA * 256 + iR) * 256 + iG) * 256 + iB;
}

with a symmetrical unpacking function

RGBA DWORD2RGBA(unsigned long dwColor)
{        
  RGBA tmp; /* why did you declare it static??? */

  tmp.B = dwColor % 256; dwColor /= 256;
  tmp.G = dwColor % 256; dwColor /= 256;
  tmp.R = dwColor % 256; dwColor /= 256;
  tmp.A = dwColor % 256; /* dwColor /= 256; */

  return tmp;
}

Note that there's only one "magic constant" in the whole code.

Of course, if you have an external specification that is written in terms of bit patterns in the packed data, a version based on bit and shift opertions might be preferrable. Still

unsigned long RGBA2DWORD(int iR, int iG, int iB, int iA)
{        
  return (((((iA << 8) + iR) << 8) + iG) << 8) + iB;
}

RGBA DWORD2RGBA(unsigned long dwColor)
{        
  RGBA tmp; /* why did you declare it static??? */

  tmp.B = dwColor & 0xFF; dwColor >>= 8;
  tmp.G = dwColor & 0xFF; dwColor >>= 8;
  tmp.R = dwColor & 0xFF; dwColor >>= 8;
  tmp.A = dwColor & 0xFF; /* dwColor >>= 8; */

  return tmp;
}

has much less "magic constants".

Now you can wrap the repetivie actions/subexpressions in macros or, better, inline functions and arrive at very compact and readable packer/unpacker.

Upvotes: 10

Jason Williams
Jason Williams

Reputation: 57902

If you don't mind using byte-size integers for RGBA, you can use a union. [edit This is a commonly used approach and you are unlikely to find a compiler that doesn't suport it, but strictly speaking (so I'm told) it's an illegal hack. The better approach in most circumstances is to do a mathematical or binary conversion, but I'll leave this half of my answer in place because it may help the reader to understand what people are doing when they see this type of code out in the real world]

union RGBA
{
    DWORD dword;
    unsigned char RGBA[4];
    struct RGBAstruct
    {
        unsigned char b;
        unsigned char g;
        unsigned char r;
        unsigned char a;
    }
};

Then you can access the green component as:

RGBA colour;
int green = (int) colour.RGBA[2];

or

int green = (int) colour.RGBAstruct.g;

and access the DWORD value as

DWORD value = colour.dword;

If you need the RGBA values to be int values, or wish to use a conversion approach, then you need to use bitwise operators.

You are encoding them almost correctly, but you need to use bitwise OR operator |, not logical OR || operator:

DWORD value = (iA << 24) | (iR << 16) | (iG << 8) | iB;

To go in the reverse direction:

int iA = (value >> 24) & 0xff;
int iR = (value >> 16) & 0xff;
int iG = (value >> 8) & 0xff;
int iB = (value) & 0xff;

Upvotes: 4

Alex
Alex

Reputation: 2047

You can go the other way around like:

iA = rgb >> 24; iR = (0x00FF0000 & rgb) >> 16; iG = (0x0000FF00 & rgb) >> 8; iB = (0x000000FF & rgb);

Upvotes: 2

Related Questions