Icon Colors






2.45/5 (12 votes)
Apr 13, 2005
1 min read

44537

611
An article on what you can do with color.
Introduction
While browsing the MSDN Library DVD (Oct. 2001), I found the above image in "Creating Windows XP Icons", and wrote this demonstration to show what can be done with colors.
Background
First, I would like to apologize to people with low resolution screens, the dialog is 800 pixels wide. I wanted to display the colors as a rainbow; sorting by their RGB value doesn't do the trick, so I used HLS instead. The dialog allows either sort.
Using the code
The library shows a function:
VOID ColorRGBToHLS( COLORREF clrRGB, WORD *pwHue, WORD *pwLuminance, WORD *pwSaturation );
defined in Shlwapi.h but I couldn't find it where they said it was. I did find it in MSDN Online Help on article ID: 29240, to convert RGB to HLS.
#define HLSMAX RANGE /* H,L, and S vary over 0-HLSMAX */ #define RGBMAX 255 /* R,G, and B vary over 0-RGBMAX */ /* HLSMAX BEST IF DIVISIBLE BY 6 */ /* RGBMAX, HLSMAX must each fit in a byte. */ /* Hue is undefined if Saturation is 0 (grey-scale) */ /* This value determines where the Hue scrollbar is */ /* initially set for achromatic colors */ #define UNDEFINED (HLSMAX*2/3) void RGBtoHLS(lRGBColor) DWORD lRGBColor; { WORD R,G,B; /* input RGB values */ BYTE cMax,cMin; /* max and min RGB values */ WORD Rdelta,Gdelta,Bdelta; /* intermediate value: % of spread from max */ /* get R, G, and B out of DWORD */ R = GetRValue(lRGBColor); G = GetGValue(lRGBColor); B = GetBValue(lRGBColor); /* calculate lightness */ cMax = max( max(R,G), B); cMin = min( min(R,G), B); L = ( ((cMax+cMin)*HLSMAX) + RGBMAX )/(2*RGBMAX); if (cMax == cMin) { /* r=g=b --> achromatic case */ S = 0; /* saturation */ H = UNDEFINED; /* hue */ } else { /* chromatic case */ /* saturation */ if (L <= (HLSMAX/2)) S = ( ((cMax-cMin)*HLSMAX) + ((cMax+cMin)/2) ) / (cMax+cMin); else S = ( ((cMax-cMin)*HLSMAX) + ((2*RGBMAX-cMax-cMin)/2) ) / (2*RGBMAX-cMax-cMin); /* hue */ Rdelta = ( ((cMax-R)*(HLSMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin); Gdelta = ( ((cMax-G)*(HLSMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin); Bdelta = ( ((cMax-B)*(HLSMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin); if (R == cMax) H = Bdelta - Gdelta; else if (G == cMax) H = (HLSMAX/3) + Rdelta - Bdelta; else /* B == cMax */ H = ((2*HLSMAX)/3) + Gdelta - Rdelta; if (H < 0) H += HLSMAX; if (H > HLSMAX) H -= HLSMAX; } }
As you can see, this code is the old UNIX C (1978) vintage, but it is easy to bring it up to date. See IconColorsDlg.cpp for details.
Here is the sort routine code:
void CIconColorsDlg::SortColors() { COLORREF clTemp; DWORD dwColor1, dwColor2; for (int j = 0; j < 32; j++) { for (int i = 0; i < 31; i++) { if (!bRGB) { RGBtoHLS(m_nColor[i + 1]); dwColor1 = wHue; dwColor1 = dwColor1 << 8; dwColor1 += wLum; dwColor1 = dwColor1 << 8; dwColor1 += wSat; dwColor1 = dwColor1 & 0x00FFFFFF; RGBtoHLS(m_nColor[i]); dwColor2 = wHue; dwColor2 = dwColor2 << 8; dwColor2 += wLum; dwColor2 = dwColor2 << 8; dwColor2 += wSat; dwColor2 = dwColor2 & 0x00FFFFFF; if (dwColor1 < dwColor2) { clTemp = m_nColor[i]; m_nColor[i] = m_nColor[i + 1]; m_nColor[i + 1] = clTemp; } } else if (m_nColor[i + 1] < m_nColor[i]) { clTemp = m_nColor[i]; m_nColor[i] = m_nColor[i + 1]; m_nColor[i + 1] = clTemp; } } } }
Then to see the details of each color, I use a left-shift-end-around function:
void CIconColorsDlg::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default COLORREF clTemp; clTemp = m_nColor[0]; for(int i = 1; i < 32; i++) { m_nColor[i-1] = m_nColor[i]; } m_nColor[31] = clTemp; DrawColors(); CDialog::OnTimer(nIDEvent); }
Points of Interest
The RGB
macro uses COLORREF
variable to save the value in. It is saved as 0x00bbggrr where bb is the blue byte, gg is the green byte, and rr is the red byte. Sorting this does group the colors, but not how I wanted. The pink color RGB(255, 204, 255)
you will notice is out of place because as the variables in RGBtoHLS()
is seen, wHue
= 65520 (-16), Bdelta
= 0, and Gdelta
= 16. Maybe I'll fix this sometime.
History
April 11, 2005 - Version 1.0.