天天看點

RGB和HSL顔色轉換

  1. //   
  2. // 下面的代碼完成顔色轉換:RGB<--->HSL。注意它們的分量的取值範圍。   
  3. // cheungmine 收集整理   
  4. //   
  5. #include "stdafx.h"   
  6. #define min3v(v1, v2, v3)   ((v1)>(v2)? ((v2)>(v3)?(v3):(v2)):((v1)>(v3)?(v3):(v2)))   
  7. #define max3v(v1, v2, v3)   ((v1)<(v2)? ((v2)<(v3)?(v3):(v2)):((v1)<(v3)?(v3):(v1)))  
  8. typedef struct   
  9. {  
  10.     BYTE  red;              // [0,255]   
  11.     BYTE  green;            // [0,255]   
  12.     BYTE  blue;             // [0,255]   
  13. }COLOR_RGB;  
  14. typedef struct   
  15. {  
  16.     float  hue;               // [0,360]   
  17.     float  saturation;        // [0,100]   
  18.     float  luminance;         // [0,100]   
  19. }COLOR_HSL;  
  20. // Converts RGB to HSL   
  21. static   void  RGBtoHSL( const  COLOR_RGB *rgb,  COLOR_HSL *hsl)  
  22. {  
  23.     float  h=0, s=0, l=0;  
  24.     // normalizes red-green-blue values   
  25.     float  r = rgb->red/255.f;  
  26.     float  g = rgb->green/255.f;  
  27.     float  b = rgb->blue/255.f;  
  28.     float  maxVal = max3v(r, g, b);  
  29.     float  minVal = min3v(r, g, b);  
  30.     // hue   
  31.     if (maxVal == minVal)  
  32.     {  
  33.         h = 0; // undefined   
  34.     }  
  35.     else   if (maxVal==r && g>=b)  
  36.     {  
  37.         h = 60.0f*(g-b)/(maxVal-minVal);  
  38.     }  
  39.     else   if (maxVal==r && g<b)  
  40.     {  
  41.         h = 60.0f*(g-b)/(maxVal-minVal) + 360.0f;  
  42.     }  
  43.     else   if (maxVal==g)  
  44.     {  
  45.         h = 60.0f*(b-r)/(maxVal-minVal) + 120.0f;  
  46.     }  
  47.     else   if (maxVal==b)  
  48.     {  
  49.         h = 60.0f*(r-g)/(maxVal-minVal) + 240.0f;  
  50.     }  
  51.     // luminance   
  52.     l = (maxVal+minVal)/2.0f;  
  53.     // saturation   
  54.     if (l == 0 || maxVal == minVal)  
  55.     {  
  56.         s = 0;  
  57.     }  
  58.     else   if (0<l && l<=0.5f)  
  59.     {  
  60.         s = (maxVal-minVal)/(maxVal+minVal);  
  61.     }  
  62.     else   if (l>0.5f)  
  63.     {  
  64.         s = (maxVal-minVal)/(2 - (maxVal+minVal)); //(maxVal-minVal > 0)?   
  65.     }  
  66.     hsl->hue = (h>360)? 360 : ((h<0)?0:h);   
  67.     hsl->saturation = ((s>1)? 1 : ((s<0)?0:s))*100;  
  68.     hsl->luminance = ((l>1)? 1 : ((l<0)?0:l))*100;  
  69. }   
  70. // Converts HSL to RGB   
  71. static   void  HSLtoRGB( const  COLOR_HSL *hsl, COLOR_RGB *rgb)   
  72. {  
  73.     float  h = hsl->hue;                   // h must be [0, 360]   
  74.     float  s = hsl->saturation/100.f;  // s must be [0, 1]   
  75.     float  l = hsl->luminance/100.f;       // l must be [0, 1]   
  76.     float  R, G, B;  
  77.     if (hsl->saturation == 0)  
  78.     {  
  79.         // achromatic color (gray scale)   
  80.         R = G = B = l*255.f;  
  81.     }  
  82.     else   
  83.     {  
  84.         float  q = (l<0.5f)?(l * (1.0f+s)):(l+s - (l*s));  
  85.         float  p = (2.0f * l) - q;  
  86.         float  Hk = h/360.0f;  
  87.         float  T[3];  
  88.         T[0] = Hk + 0.3333333f; // Tr   0.3333333f=1.0/3.0   
  89.         T[1] = Hk;              // Tb   
  90.         T[2] = Hk - 0.3333333f; // Tg   
  91.         for ( int  i=0; i<3; i++)  
  92.         {  
  93.             if (T[i] < 0) T[i] += 1.0f;  
  94.             if (T[i] > 1) T[i] -= 1.0f;  
  95.             if ((T[i]*6) < 1)  
  96.             {  
  97.                 T[i] = p + ((q-p)*6.0f*T[i]);  
  98.             }  
  99.             else   if ((T[i]*2.0f) < 1)  //(1.0/6.0)<=T[i] && T[i]<0.5   
  100.             {  
  101.                 T[i] = q;  
  102.             }  
  103.             else   if ((T[i]*3.0f) < 2)  // 0.5<=T[i] && T[i]<(2.0/3.0)   
  104.             {  
  105.                 T[i] = p + (q-p) * ((2.0f/3.0f) - T[i]) * 6.0f;  
  106.             }  
  107.             else  T[i] = p;  
  108.         }  
  109.         R = T[0]*255.0f;  
  110.         G = T[1]*255.0f;  
  111.         B = T[2]*255.0f;  
  112.     }  
  113.     rgb->red = (BYTE)((R>255)? 255 : ((R<0)?0 : R));  
  114.     rgb->green = (BYTE)((G>255)? 255 : ((G<0)?0 : G));  
  115.     rgb->blue = (BYTE)((B>255)? 255 : ((B<0)?0 : B));  
  116. }  
  117. int  _tmain( int  argc, _TCHAR* argv[])  
  118. {  
  119.     COLOR_RGB  rgb={254, 216, 166};  
  120.     COLOR_HSL  hsl;  
  121.     RGBtoHSL(&rgb, &hsl);  
  122.     printf("H=%.0f; S=%.0f; L=%.0f/n" , hsl.hue, hsl.saturation, hsl.luminance);  
  123.     HSLtoRGB(&hsl, &rgb);  
  124.     RGBtoHSL(&rgb, &hsl);  
  125.     printf("H=%.0f; S=%.0f; L=%.0f/n" , hsl.hue, hsl.saturation, hsl.luminance);  
  126.     getchar();  
  127.     return  0;  
  128. }  
  129. // 在Windows系統下,HSL分量的範圍是[0,240]。參考“畫筆”程式,可以看到RGB(紅|綠|藍)   
  130. // 和HSL(色調|飽和度|亮度)的聯系。   
  131. // 下面的代碼,把COLOR_HSL的分量值變為Windows的HSL分量,取值在[0,240]之間,需要:   
  132. COLOR_HSL  hsl={300, 50, 82};  
  133. // 下面為COLOR_HSL到Windows的HSL的轉換:   
  134. win_H = 240 * hsl.hue / 360.f;  
  135. win_S = 240 * hsl.saturation / 100.f;  
  136. win_L = 240 * hsl.luminance / 100.f;