RGB和HSL色彩轉換
cheungmine
//// 下面的程式碼完成色彩轉換:RGB<--->HSL。注意它們的分量的取值範圍。// cheungmine 收集整理//#include "stdafx.h"#define min3v(v1, v2, v3)((v1)>(v2)? ((v2)>(v3)?(v3):(v2)):((v1)>(v3)?(v3):(v2)))#define max3v(v1, v2, v3)((v1)<(v2)? ((v2)<(v3)?(v3):(v2)):((v1)<(v3)?(v3):(v1)))typedef struct{BYTE red;// [0,255]BYTE green;// [0,255]BYTE blue;// [0,255]}COLOR_RGB;typedef struct{float hue;// [0,360]float saturation;// [0,100]float luminance;// [0,100]}COLOR_HSL;// Converts RGB to HSLstatic void RGBtoHSL(/*[in]*/const COLOR_RGB *rgb, /*[out]*/COLOR_HSL *hsl){float h=0, s=0, l=0;// normalizes red-green-blue valuesfloat r = rgb->red/255.f;float g = rgb->green/255.f;float b = rgb->blue/255.f;float maxVal = max3v(r, g, b);float minVal = min3v(r, g, b);// hueif(maxVal == minVal){h = 0; // undefined}else if(maxVal==r && g>=b){h = 60.0f*(g-b)/(maxVal-minVal);}else if(maxVal==r && g<b){h = 60.0f*(g-b)/(maxVal-minVal) + 360.0f;}else if(maxVal==g){h = 60.0f*(b-r)/(maxVal-minVal) + 120.0f;}else if(maxVal==b){h = 60.0f*(r-g)/(maxVal-minVal) + 240.0f;}// luminancel = (maxVal+minVal)/2.0f;// saturationif(l == 0 || maxVal == minVal){s = 0;}else if(0<l && l<=0.5f){s = (maxVal-minVal)/(maxVal+minVal);}else if(l>0.5f){s = (maxVal-minVal)/(2 - (maxVal+minVal)); //(maxVal-minVal > 0)?}hsl->hue = (h>360)? 360 : ((h<0)?0:h); hsl->saturation = ((s>1)? 1 : ((s<0)?0:s))*100;hsl->luminance = ((l>1)? 1 : ((l<0)?0:l))*100;} // Converts HSL to RGBstatic void HSLtoRGB(const COLOR_HSL *hsl, COLOR_RGB *rgb) {float h = hsl->hue;// h must be [0, 360]float s = hsl->saturation/100.f;// s must be [0, 1]float l = hsl->luminance/100.f;// l must be [0, 1]float R, G, B;if(hsl->saturation == 0){// achromatic color (gray scale)R = G = B = l*255.f;}else{float q = (l<0.5f)?(l * (1.0f+s)):(l+s - (l*s));float p = (2.0f * l) - q;float Hk = h/360.0f;float T[3];T[0] = Hk + 0.3333333f;// Tr0.3333333f=1.0/3.0T[1] = Hk;// TbT[2] = Hk - 0.3333333f;// Tgfor(int i=0; i<3; i++){if(T[i] < 0) T[i] += 1.0f;if(T[i] > 1) T[i] -= 1.0f;if((T[i]*6) < 1){T[i] = p + ((q-p)*6.0f*T[i]);}else if((T[i]*2.0f) < 1) //(1.0/6.0)<=T[i] && T[i]<0.5{T[i] = q;}else if((T[i]*3.0f) < 2) // 0.5<=T[i] && T[i]<(2.0/3.0){T[i] = p + (q-p) * ((2.0f/3.0f) - T[i]) * 6.0f;}else T[i] = p;}R = T[0]*255.0f;G = T[1]*255.0f;B = T[2]*255.0f;}rgb->red = (BYTE)((R>255)? 255 : ((R<0)?0 : R));rgb->green = (BYTE)((G>255)? 255 : ((G<0)?0 : G));rgb->blue = (BYTE)((B>255)? 255 : ((B<0)?0 : B));}int _tmain(int argc, _TCHAR* argv[]){COLOR_RGB rgb={254, 216, 166};COLOR_HSL hsl;RGBtoHSL(&rgb, &hsl);printf("H=%.0f; S=%.0f; L=%.0f/n", hsl.hue, hsl.saturation, hsl.luminance);HSLtoRGB(&hsl, &rgb);RGBtoHSL(&rgb, &hsl);printf("H=%.0f; S=%.0f; L=%.0f/n", hsl.hue, hsl.saturation, hsl.luminance);getchar();return 0;}// 在Windows系統下,HSL分量的範圍是[0,240]。參考“畫筆”程式,可以看到RGB(紅|綠|藍)// 和HSL(色調|飽和度|亮度)的聯絡。// 下面的代碼,把COLOR_HSL的分量值變為Windows的HSL分量,取值在[0,240]之間,需要:COLOR_HSL hsl={300, 50, 82};// 下面為COLOR_HSL到Windows的HSL的轉換:win_H = 240 * hsl.hue / 360.f;win_S = 240 * hsl.saturation / 100.f;win_L = 240 * hsl.luminance / 100.f;
參考文檔:
http://www.codeproject.com/KB/recipes/colorspace1.aspx#rgb2