色相(H)饱和度(S)明度(L)与RGB的转换以及在android上的试验

来源:互联网 发布:echo gumi动作数据 编辑:程序博客网 时间:2024/05/20 18:46

最近突然想在android的SurfaceView上实现一个类似windows上画图颜色选择面板那种颜色和彩虹差不多排列的效果,以下是尝试。



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.找出RGB中的最大值。
3.计算L(明度):L=(max(R,G,B) + min(R,G,B))/2
4.如果最大和最小的颜色值相同,即表示灰色,那么S(饱和度)定义为0,而H(色调)未定义并在程序中通常写成0。
5.否则L(明度)计算S(饱和度)
If L<0.5, S=(max(R,G,B) -min(R,G,B))/(max(R,G,B)  + min(R,G,B))
If L>=0.5, S=(max(R,G,B) -min(R,G,B))/(2.0-maxcolor-min(R,G,B))
6.计算H(色调)
If R=max(R,G,B)
 H=(G-B)/(max(R,G,B)-min(R,G,B))
If G=max(R,G,B),
H=2.0+(B-R)/(max(R,G,B)-min(R,G,B))
If B=max(R,G,B),
H=4.0+(R-G)/(max(R,G,B)-min(R,G,B))
H=H*60.0
if(H<0) 
H+=360
说明:1,由步骤3的式子可以看出L(明度)仅与图像的最多颜色成分和最少的颜色成分的总量有关。L(明度)越小,图像越趋于黑色。L(明度)越高图像越趋于明亮的白色。
  2,由步骤5的式子可以看出S(饱和度)与图像的最多颜色成分和最少的颜色成分的差量有关。S(饱和度)越小,图像越趋于灰度图像。S(饱和度)越大,图像越鲜艳,给人的感觉是彩色的,而不是黑白灰的图像。
  3,H(色调)决定了人对图像的不同的颜色感受。
  4,从第6步的计算看,H(色调)分成0~6区域。RGB颜色空间是一个立方体而HSL颜色空间是两个六角形锥体,其中的H(色调)是RGB立方体的主对角线。因此,RGB立方体的顶点:红、黄、绿、青、蓝和品红就成为HSL六角形的顶点,而数值0~6就告诉我们H(色调)在哪个部分。
以上整理自百度百科

b) HSL→RGB
private void HSL2RGB(double H, double S, double L){//此处HSL均转化到(0, 1)
double var1, var2;
if(S == 0){
R = (int)(L * 255.0);
G = (int)(L * 255.0);
B = (int)(L * 255.0);
}else{
if(L < 0.5)
var2 = L * (1 + S);
else
var2 = (L + S) - (S * L);
var1 = 2.0 * L - var2;

R = (int)(255.0 * Hue2RGB(var1, var2, H + (1.0/3.0)));
G = (int)(255.0 * Hue2RGB(var1, var2, H));
B = (int)(255.0 * Hue2RGB(var1, var2, H - (1.0/3.0)));
}
}

private double Hue2RGB(double v1, double v2, double vH){
if (vH < 0) 
vH += 1;
   if (vH > 1) 
    vH -= 1;
   if (6.0 * vH < 1) 
    return v1 + (v2 - v1) * 6.0 * vH;
   if (2.0 * vH < 1) 
    return v2;
   if (3.0 * vH < 2) 
    return v1 + (v2 - v1) * ((2.0 / 3.0) - vH) * 6.0;
   return (v1);
}
最后实现效果如下(其中L固定为0.5):





0 0
原创粉丝点击