RGB values in COLORREF?

I know the macro RGB(r, g, b) creates a COLORREF from r,g,b values. But I need the inverse of the macro. I need to extract the red, green, and blue values from the COLORREF. I am working on texturing and lighting in my 3D engine and I cannot get a good working model using the COLORREFs. But if I use the RGB values I get better results.

Is it something similar to this:
Red = (int)(COLORREF

Comments

  • Two ways of doing it.
    The first one is a union:
    [code]
    typedef union
    {
    COLORREF c;
    struct
    {
    #ifdef LITTLEENDIAN
    unsigned char cBlue;
    unsigned char cGreen;
    unsigned char cRed;
    unsigned char crsvd;
    #else
    unsigned char crsvd;
    unsigned char cRed;
    unsigned char cGreen;
    unsigned char cBlue;
    #endif
    } chars;
    } UPixel;
    [/code]
    The big and little endian thing is ugly, but if you ever change platform (e.g. from X86 to Motorola), you're in trouble, since the locations of the bytes are fscked.

    Now in the code you could do something like this:
    [code]
    UPixel Pixel;
    Pixel.c=SomeColor;
    unsigned char cRedPart=SomeColor.chars.cRed;
    unsigned char cGreenPart=SomeColor.chars.cGreen;
    unsigned char cBluePart=SomeColor.chars.cBlue;
    [/code]

    The other solution is slower, unless your compiler can really optimise:

    [code]
    unsigned char cRedPart=(SomeColor&0x00ff0000)>>16;
    unsigned char cGreenPart=(SomeColor&0x0000ff00)>>8;
    unsigned char cBluePart=SomeColor&0x000000ff;
    [/code]

    Of course, you ought to make some macros for all this.

    HTH

    Regards,

    Rune

  • Forgive my ignorance ! I have been searching my MSDN Library CD.
    I have been looking for a number of days now. Even my books. I guess I just didnt look in the right place. I never came across the fact that COLORREF was a struct. WOW !!! that helps everything !!! thanks


  • : I know the macro RGB(r, g, b) creates a COLORREF from r,g,b values. But I need the inverse of the macro. I need to extract the red, green, and blue values from the COLORREF. I am working on texturing and lighting in my 3D engine and I cannot get a good working model using the COLORREFs. But if I use the RGB values I get better results.
    :
    : Is it something similar to this:
    : Red = (int)(COLORREF << 16);
    : Grn = (int)(COLORREF << 8);
    : Blu = (int)(COLORREF);
    [code=ffffff]
    COLORREF clr = RGB([color=bb0000]10[/color],[color=bb0000]20[/color],[color=bb0000]30[/color]);
    BYTE r = GetRValue(clr);
    BYTE g = GetGValue(clr);
    BYTE b = GetBValue(clr);
    [/code]
    Cheers,
    Eric

  • : I have been looking for a number of days now. Even my books. I guess I just didnt look in the right place. I never came across the fact that COLORREF was a struct. WOW !!! that helps everything !!! thanks

    It's not a struct, it's a DWORD (32 bit unsigned integer). Cyt's code is using a union to pretend the DWORD is a struct. This invokes undefined behavior though, so you should avoid it.

    Cheers,
    Eric

  • : Cyt's code is using a union to pretend the DWORD is a struct.
    : This invokes undefined behavior though, so you should avoid it.

    It's not exactly undefined, in my opinion. However, I admit that it's better to use Microsoft macros on a Microsoft defined type (i.e. COLORREF).

    I'm using similar structs/unions myself in a graphic-engine under development. The reason for not using COLORREF and MS macros is that the entire engine is supposed to be windows independent. Until now, this has not caused any problems. The interesting part would of course be to test the engine under Linux/AmigaOS/whatever.

  • : : Cyt's code is using a union to pretend the DWORD is a struct.
    : : This invokes undefined behavior though, so you should avoid it.
    :
    : It's not exactly undefined, in my opinion.

    It's not a matter of opinion, it's a matter of the language definitition. The only time it's ever defined to to write one member of the union, and read from another, is when two members of a union are POD structs with a common initial sequences. For example:
    [code=ffffff]
    [color=000080]union[/color] {
    [color=000080]struct[/color] {
    [color=000080]int[/color] i;
    [color=000080]float[/color] f;
    } foo;
    [color=000080]struct[/color] {
    [color=000080]int[/color] x, y;
    [color=000080]char[/color]* name;
    } bar;
    };
    [/code]
    It would be OK to write to foo.x and then read from bar.x.

    : Until now, this has not caused any problems.

    Which means nothing, of course, other than it works in your particular compiler, or on your operating system. It doesn't mean that it is standard-defined behavior. Which means you cannot say if it will work on any other compiler, or even in future versions of your compiler.

    Cheers,
    Eric

  • : : It's not exactly undefined, in my opinion.
    : It's not a matter of opinion, it's a matter
    : of the language definitition.

    You are right. And let me try to explain it a bit "better" (which is not a definition, but my opinion :-))
    "Better", because it will show when my struct/union approach break.

    There is a C compiler for Texas Instruments DSPs. Since the CPU works with 16 bit registers/memory accesses, the smallest quantity, one can have (i.e. char) is 16 bit in the C compiler.

    Therefore, sizeof(long) is not 4, but 2.
    And therefore, my code:
    [code]
    typedef union
    {
    long l;
    struct
    {
    unsigned char c1;
    unsigned char c2;
    unsigned char c3;
    unsigned char c4;
    } chars;
    } UPixel;
    [/code]
    will not work as it does on an X86/Motorola 680x0 CPU.

    Example:
    [code]
    UPixel P;
    P.chars.c1=0x12;
    P.chars.c2=0x34;
    P.chars.c3=0x00;
    P.chars.c4=0x00;
    [/code]

    The contents of P.l will now be different on each processor:
    [code]
    TI DSP | Motorola 680x0 | X86
    0x00120034 | 0x12340000 | 0x00003412
    [/code]
    I tried to take into account the Big/Little endian thing by defining UPixel differently for different platforms, but one can never now how many bits will be available for an unsigned char

    One last interesting question for Eric: Is there a minimum guaranteed size of char/short/long?

    Regards
  • : : : It's not exactly undefined, in my opinion.
    : : It's not a matter of opinion, it's a matter
    : : of the language definitition.
    :
    : Therefore, sizeof(long) is not 4, but 2.
    : And therefore, my code:
    : [code]
    : typedef union
    : {
    : long l;
    : struct
    : {
    : unsigned char c1;
    : unsigned char c2;
    : unsigned char c3;
    : unsigned char c4;
    : } chars;
    : } UPixel;
    : [/code]
    : will not work as it does on an X86/Motorola 680x0 CPU.

    Actually, the point is was trying to make is that [italic]even if sizeof long is 4[/italic], using a union this way is undefined. When the language standard says something is "undefined", it typically means that while the code may be syntactically legal (the compiler need not reject it), the standard "omits the description of any explicit definition of behavior". It could do anything. It [italic]could[/italic] work exactly as you expect. Or it could crash, reformat your hard disk, make toast, play "My Sharona" on your PC speaker... whatever.

    : Example:
    : [code]
    : UPixel P;
    : P.chars.c1=0x12;
    : P.chars.c2=0x34;
    : P.chars.c3=0x00;
    : P.chars.c4=0x00;
    : [/code]
    :
    : The contents of P.l will now be different on each processor:

    Or your machine could melt into a puddle of radioactive slag. You have no way of knowing [italic]what[/italic] will happen once you invoke undefined behavior.

    : One last interesting question for Eric: Is there a minimum guaranteed size of char/short/long?

    'char' must have at least 8 bits. By definition, (sizeof char) == 1.

    'short' must have enough value bits to hold the value 32767

    'long' must have enough value bits to hold the value 2147483647

    Note: it is possible that (sizeof char) == (sizeof short) == (sizeof long), as long as the minimum requirements described above are met.

    Cheers,
    Eric

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories