模型原理
H: Hue 色相
S:Saturation 飽和度
L :Lightness 亮度
HSL色彩模式使用HSL模型為圖像中每一個
像素的HSL分量分配一個0~255範圍內的強度值。HSL圖像只使用三種通道,就可以使它們按照不同的比例混合,在螢幕上重現16777216種顏色。
在 HSL 模式下,每種 HSL 成分都可使用從 0到 255的值。(其中L是從黑(0)到白(255)漸變)
Windows自帶畫圖程式中選單欄->顏色->編輯顏色->規定自定義顏色 中可以通過修改E(H)SL的值(0~240)以得到對應RGU(B)的值。
模型解釋
HSL的H(hue)分量,代表的是人眼所能感知的顏色範圍,這些顏色分布在一個平面的色相環上,取值範圍是0°到360°的圓心角,每個角度可以代表一種顏色。色相值的意義在於,我們可以在不改變光感的情況下,通過旋轉色相環來改變顏色。在實際套用中,我們需要記住色相環上的六大主色,用作基本參照:360°/0°紅、60°黃、120°綠、180°青、240°藍、300°洋紅,它們在色相環上按照60°圓心角的間隔排列。
HSL的S(saturation)分量,指的是色彩的飽和度,它用0%至100%的值描述了相同色相、亮度下色彩純度的變化。數值越大,顏色中的灰色越少,顏色越鮮艷,呈現一種從理性(灰度)到感性(純色)的變化。
HSL的L(lightness)分量,指的是色彩的亮度,作用是控制色彩的亮暗變化。它同樣使用了0%至100%的取值範圍。數值越小,色彩越暗,越接近於黑色;數值越大,色彩越亮,越接近於白色。
模型轉換
a) RGB→HSL的算法描述。
步驟1:把RGB值轉成區間[0,1]內的數值。
步驟2:找出R,G和B中的最大值。
步驟3:計算亮度:L=(maxcolor + mincolor)/2
步驟4:如果最大和最小的顏色值相同,即表示灰色,那么S定義為0,而H未定義並在程式中通常寫成0。
步驟5:否則,根據亮度L計算飽和度S:
If L<0.5, S=(maxcolor-mincolor)/(maxcolor + mincolor)
If L>=0.5, S=(maxcolor-mincolor)/(2.0-maxcolor-mincolor)
步驟6:計算色調H:
If R=maxcolor, H=(G-B)/(maxcolor-mincolor)
If G=maxcolor, H=2.0+(B-R)/(maxcolor-mincolor)
If B=maxcolor, H=4.0+(R-G)/(maxcolor-mincolor)
H=H*60.0,如果H為負值,則加360。
說明:1,由步驟3的式子可以看出亮度僅與圖像的最多顏色成分和最少的顏色成分的總量有關。亮度越小,圖像越趨於黑色。亮度越高圖像越趨於明亮的白色。
2,由步驟5的式子可以看出飽和度與圖像的最多顏色成分和最少的顏色成分的差量有關。飽和度越小,圖像越趨於灰度圖像。飽和度越大,圖像越鮮艷,給人的感覺是彩色的,而不是黑白灰的圖像。
3,色調決定了人對圖像的不同的顏色感受。
4,從第6步的計算看,H分成0~6區域。RGB顏,色空間是一個立方體而HSL顏色空間是兩個六角形錐體,其中的L是RGB立方體的主對角線。因此,RGB立方體的頂點:紅、黃、綠、青、藍和
品紅就成為HSL六角形的頂點,而數值0~6就告訴我們H在哪個部分。
b) HSL→RGB的算法描述。
步驟1:If S=0,表示灰色,定義R,G和B都為L.
步驟2:否則,測試L:
If L<0.5,temp2=L*(1.0+S)
If L>=0.5,temp2=L+S-L*S
步驟3:temp1=2.0*L-temp2
步驟4:把H轉換到0~1。
步驟5:對於R,G,B,計算另外的臨時值temp3。方法如下:
for R, temp3=H+1.0/3.0
for G, temp3=H
for B, temp3=H-1.0/3.0
if temp3<0, temp3=temp3+1.0
if temp3>1, temp3=temp3-1.0
步驟6:對於R,G,B做如下測試:
If 6.0*temp3<1,color=temp1+(temp2-temp1)*6.0*temp3
Else if 2.0*temp3<1,color=temp2
Else if 3.0*temp3<2,
color=temp1+(temp2-temp1)*((2.0/3.0)-temp3)*6.0
Else color=temp1
HSL→RGB的C語言算法:
float H = 0.5, S = 0.5, L = 0.5; // HSL取值範圍(0, 1) float R, G, B; float q, p; float T[3]; if (S == 0) { R = G = B = L; } else { if (L < 0.5)q = L*(1.0 + S); if (L >= 0.5)q = L + S - L*S; p = 2.0*L - q; T[0] = H + 0.3333333f; T[1] = H; T[2] = H - 0.3333333f; for (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) { T[i] = q; } else if ((T[i] * 3.0f) < 2) { T[i] = p + (q - p) * ((2.0f / 3.0f) - T[i]) * 6.0f; } else T[i] = p; } R = T[0]; G = T[1]; B = T[2]; } R = ((R > 1) ? 1 : ((R < 0) ? 0 : R));//取值範圍(0,1) G = ((G > 1) ? 1 : ((G < 0) ? 0 : G));//取值範圍(0,1) B = ((B > 1) ? 1 : ((B < 0) ? 0 : B));//取值範圍(0,1)//為了使代碼更具通用性,此處不寫成一個方法(有些語言聲明方法的形式不一致)。//此段代碼也不需要任何頭檔案。//各操作平台對RGB和HSL的取值範圍也不同,這裡統一為0到1。