#pragma once #include <shlwapi.h> #pragma comment(lib, "shlwapi.lib") class CColor_RGB_HLS { #define HLSMAX 240 /* 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) /* utility routine for HLStoRGB */ INT HueToRGB(INT n1,INT n2,INT hue) { /* range check: note values passed add/subtract thirds of range */ if (hue < 0) hue += HLSMAX; if (hue > HLSMAX) hue -= HLSMAX; /* return r,g, or b value from this tridrant */ if (hue < (HLSMAX/6)) return ( n1 + (((n2-n1)*hue+(HLSMAX/12))/(HLSMAX/6)) ); if (hue < (HLSMAX/2)) return ( n2 ); if (hue < ((HLSMAX*2)/3)) return ( n1 + (((n2-n1)*(((HLSMAX*2)/3)-hue)+(HLSMAX/12))/(HLSMAX/6)) ); else return ( n1 ); } public: WORD GetHLSMax() { return HLSMAX; } typedef struct _COLOR_HLS { WORD H; union { WORD L; WORD B; }; WORD S; }COLOR_HLS, COLOR_HBS; #if _MSC_VER > 1400 COLOR_HLS ColorRGBToHLS(const COLORREF lRGBColor) { WORD H, L, S; ::ColorRGBToHLS(lRGBColor, &H, &L, &S); COLOR_HLS mHLS={H, L, S}; return mHLS; } COLORREF ColorHLSToRGB(COLOR_HLS mHLS) { return ::ColorHLSToRGB(mHLS.H, mHLS.L, mHLS.S); } #endif virtual COLOR_HLS _ColorRGBToHLS(BYTE R, BYTE G, BYTE B) //* input RGB values */ { BYTE cMax,cMin; /* max and min RGB values */ WORD Rdelta,Gdelta,Bdelta; /* intermediate value: % of spread from max*/ INT H,L,S; /* 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; } COLOR_HLS mHLS={H, L, S}; return mHLS; } virtual COLOR_HLS _ColorRGBToHLS(COLORREF lRGBColor) // { return _ColorRGBToHLS(GetRValue(lRGBColor), GetGValue(lRGBColor), GetBValue(lRGBColor)); } virtual COLORREF _ColorHLSToRGB(WORD hue, WORD lum, WORD sat) { WORD R,G,B; /* RGB component values */ INT Magic1,Magic2; /* calculated magic numbers (really!) */ if (sat == 0) /* achromatic case */ { R=G=B=(lum*RGBMAX)/HLSMAX; if (hue != UNDEFINED) { /* ERROR */ } } else /* chromatic case */ { /* set up magic numbers */ if (lum <= (HLSMAX/2)) Magic2 = (lum*(HLSMAX + sat) + (HLSMAX/2))/HLSMAX; else Magic2 = lum + sat - ((lum*sat) + (HLSMAX/2))/HLSMAX; Magic1 = 2*lum-Magic2; /* get RGB, change units from HLSMAX to RGBMAX */ R = (HueToRGB(Magic1,Magic2,hue+(HLSMAX/3))*RGBMAX + (HLSMAX/2))/HLSMAX; G = (HueToRGB(Magic1,Magic2,hue)*RGBMAX + (HLSMAX/2)) / HLSMAX; B = (HueToRGB(Magic1,Magic2,hue-(HLSMAX/3))*RGBMAX + (HLSMAX/2))/HLSMAX; } return(RGB(R,G,B)); } virtual COLORREF _ColorHLSToRGB(const COLOR_HLS mHLS) { return _ColorHLSToRGB( mHLS.H, mHLS.L, mHLS.S); } }; //测试代码 CColor_RGB_HLS mConv; COLORREF mRGB = RGB(200, 0, 0); CColor_RGB_HLS::_COLOR_HLS mHLS = mConv._ColorRGBToHLS(mRGB); mHLS.L = min(mConv.GetHLSMax(), mHLS.L + 30); mRGB = mConv._ColorHLSToRGB(mHLS);