요약
아래 코드 단편은 RGB (빨강, 녹색, 파랑)와 HLS/HBS (색조, 밝기, 채도/색조, 밝기, 채도) 간에 색을 변환 합니다.
추가 정보
RGBtoHLS () 는 DWORD RGB 값을 가져와 HLS로 변환 하 고, 결과를 전역 vars h, l 및 s에 저장 하 고, 현재 값에 h, l 및 i를 가져와 해당 값을 RGB DWORD에 반환 합니다. Vars H, L 및 S는 다음에 의해서만 기록 됩니다.
-
RGBtoHLS (초기화)
-
스크롤 막대 처리기
알고리즘에 대 한 참조 지점은 Foley 및 Van Dam "대화형 컴퓨터 그래픽의 기본 사항" 페이지 618-19입니다. 해당 알고리즘이 부동 소수점에 있습니다. CHART는 덜 일반적인 (hardwired 범위) 정수 계열 알고리즘을 구현 합니다. 이 샘플 전체에 걸쳐 반올림 오류가 발생할 수 있습니다. (((0.5 + x)/y)가 부동 소수점 없이 phrased ((x + (y/2))/y ((()), 매우 작은 반올림 오류를 생성 합니다. 이렇게 하면 다음의 여러 부서가 이상 하 게 보입니다.
*/ #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; } } /* utility routine for HLStoRGB */ WORD HueToRGB(n1,n2,hue) WORD n1; WORD n2; WORD 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 ); } DWORD HLStoRGB(hue,lum,sat) WORD hue; WORD lum; WORD sat; { WORD R,G,B; /* RGB component values */ WORD 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)); }