I have COLORREF color . How to change a single attribute: R , G or B ?

  • If you are given an exhaustive answer, mark it as correct (click on the check mark next to the selected answer). - ߊߚߤߘ

2 answers 2

To install a separate component, you must first clear the corresponding byte (the first for R, the second for G, the third for B) via bitwise AND, then write the new value via bitwise OR. For convenience, you can create macros:

 #define SetRValue(c, r) ((COLORREF)((c & 0x00FFFF00) | ((BYTE)(r)))) #define SetGValue(c, g) ((COLORREF)((c & 0x00FF00FF) | ((BYTE)(g) << 8))) #define SetBValue(c, b) ((COLORREF)((c & 0x0000FFFF) | ((BYTE)(b) << 16))) 

Using:

 COLORREF color = RGB(0x11, 0x22, 0x33); printf("0x%08x\n", color); // 0x00332211 color = SetRValue(color, 0xaa); printf("0x%08x\n", color); // 0x003322aa color = SetGValue(color, 0xbb); printf("0x%08x\n", color); // 0x0033bbaa color = SetBValue(color, 0xcc); printf("0x%08x\n", color); // 0x00ccbbaa 

    To modify a single component, you first need to split the original color into components using Get*Value() , then assemble it back using RGB() , making the necessary modifications as you build:

     COLORREF changeRedColor(COLORREF oldColor, unsigned char newRed) { return RGB(newRed, GetGValue(oldColor), GetBValue(oldColor)); } COLORREF changeGreenColor(COLORREF oldColor, unsigned char newGreen) { return RGB(GetRValue(oldColor), newGreen, GetBValue(oldColor)); } COLORREF changeBlueColor(COLORREF oldColor, unsigned char newBlue) { return RGB(GetRValue(oldColor), GetGValue(oldColor), newBlue); } 

    It is worth noting that this technique is perfectly optimized by compilers, turning into a bitwise AND, OR and (if necessary) shift:

     ; gcc -O2 -m32 -S changeRedColor(unsigned int, unsigned char): movzx eax, BYTE PTR [esp+8] mov edx, DWORD PTR [esp+4] and edx, 16776960 or eax, edx ret changeGreenColor(unsigned int, unsigned char): movzx eax, BYTE PTR [esp+8] mov edx, DWORD PTR [esp+4] movzx ecx, dl and edx, 16711680 sal eax, 8 or eax, ecx or eax, edx ret changeBlueColor(unsigned int, unsigned char): movzx eax, BYTE PTR [esp+8] movzx edx, WORD PTR [esp+4] sal eax, 16 or eax, edx ret