RGB(Red、Green、Blue)色彩模式是一种面向硬件的色彩模型,显示系统都采用RGB颜色模型来进行图像显示。RGB色彩模型属于加法混色原理,每种原色的数值越高,色彩就越亮,RGB都是0时是黑色,都是255时是白色。
RGB色彩模型表示直接,但是RGB数值和色彩的三属性没有直接的联系,不能揭示色彩之间的关系。
HSV色彩模式应用最广泛的是一个倒圆锥模型,是一种面向用户感官的色彩模型,侧重与色彩表示。这是根据人的视觉系统对亮度的敏感度要强于色彩值这个生理特性而提出的颜色模型。
HSV(Hue、Saturation、Value)分别对应色相、饱和度、明度。
HSV模型在计算机图形应用中,常使用HSV色轮,其中色相表示为圆环,用一个独立的三角形来表示饱和度(S)和明度(V)。这个三角形的垂直轴表示饱和度,水平轴表示明度。在这种方式下,选择颜色可以首先在圆环中选择色相,在三角形中选择需要的饱和度和明度。
HSV模型还可以通过圆柱体来表示。色相沿着圆柱体的外圆周变化,饱和度沿着横截面的圆心的距离变化,明度沿着横截面底面到顶面的距离变化。
HSV与RGB互转
由于HSV是面向用户的色彩模型,而显示系统都采用面向硬件的RGB色彩模型,所以在控制硬件的时候,需要进行HSV与RGB的转换。
设 (r, g, b) 分别是一个颜色的红、绿和蓝坐标,它们的值是在 0 到 1 之间的实数。设 max 等价于 r, g 和 b中的最大者。设 min 等于这些值中的最小者。要找到在 HSV 空间中的 (h, s, v) 值,这里的 h ∈ [0, 360)是角度的色相角,而 s, v ∈ [0,1] 是饱和度和明度。
由于HSV与RGB在计算中都涉及到小数运算,转换会有精度损失。
HSV范围采用:H:0~360;S : 0~1000; V : 1000;
RGB的范围采用:R : 0~1000;G : 0~1000; B : 1000;
HSV2RGB
/**
* @brief: HSV change to RGB
* @param {IN USHORT_T h -> range 0~360 }
* @param {IN USHORT_T s -> range 0~1000}
* @param {IN USHORT_T v -> range 0~1000}
* @param {OUT USHORT_T *r -> R result,rang from 0~1000}
* @param {OUT USHORT_T *g -> G result,rang from 0~1000}
* @param {OUT USHORT_T *b -> B result,rang from 0~1000}
* @retval: none
*/
VOID vLightToolHSV2RGB(IN USHORT_T h, IN USHORT_T s, IN USHORT_T v, OUT USHORT_T *r, OUT USHORT_T *g, OUT USHORT_T *b)
{
INT_T i;
FLOAT_T RGB_min, RGB_max;
FLOAT_T RGB_Adj;
INT_T difs;
if(h >= 360) {
h = 0;
}
RGB_max = v * 1.0f;
RGB_min = RGB_max*(1000 - s) / 1000.0f;
i = h / 60;
difs = h % 60; /* factorial part of h */
/* RGB adjustment amount by hue */
RGB_Adj = (RGB_max - RGB_min)*difs / 60.0f;
switch (i) {
case 0:
*r = (USHORT_T)RGB_max;
*g = (USHORT_T)(RGB_min + RGB_Adj);
*b = (USHORT_T)RGB_min;
break;
case 1:
*r = (USHORT_T)(RGB_max - RGB_Adj);
*g = (USHORT_T)RGB_max;
*b = (USHORT_T)RGB_min;
break;
case 2:
*r = (USHORT_T)RGB_min;
*g = (USHORT_T)RGB_max;
*b = (USHORT_T)(RGB_min + RGB_Adj);
break;
case 3:
*r = (USHORT_T)RGB_min;
*g = (USHORT_T)(RGB_max - RGB_Adj);
*b = (USHORT_T)RGB_max;
break;
case 4:
*r = (USHORT_T)(RGB_min + RGB_Adj);
*g = (USHORT_T)RGB_min;
*b = (USHORT_T)RGB_max;
break;
default: // case 5:
*r = (USHORT_T)RGB_max;
*g = (USHORT_T)RGB_min;
*b = (USHORT_T)(RGB_max - RGB_Adj);
break;
}
if(*r > 1000) {
*r = 1000;
}
if(*g > 1000) {
*g = 1000;
}
if(*b > 1000) {
*b = 1000;
}
}
RGB2HSV
/**
* @brief: RGB change to HSV
* @param {IN USHORT_T R -> R,rang from 0~1000}
* @param {IN USHORT_T G -> G,rang from 0~1000}
* @param {IN USHORT_T B -> B,rang from 0~1000}
* @param {OUT USHORT_T H -> result, range 0~360}
* @param {OUT USHORT_T S -> result, range 0~1000}
* @param {OUT USHORT_T V -> result, range 0~1000}
* @retval: none
*/
VOID vLightToolRGB2HSV(IN USHORT_T R, IN USHORT_T G, IN USHORT_T B, OUT USHORT_T *H, OUT USHORT_T *S, OUT USHORT_T *V)
{
FLOAT_T r,g,b;
FLOAT_T minRGB,maxRGB,deltaRGB;
FLOAT_T h = 0,s = 0,v = 0;
r = R / 1000.0f;
g = G / 1000.0f;
b = B / 1000.0f;
minRGB = fLightToolGetMIN(r,fLightToolGetMIN(g,b));
maxRGB = fLightToolGetMAX(r,fLightToolGetMAX(g,b));
deltaRGB = maxRGB - minRGB;
v = maxRGB;
if(maxRGB != 0.0) {
s = deltaRGB / maxRGB;
} else {
s = 0.0;
}
if(s <= 0.0) {
h = -1.0f;
} else {
if(r == maxRGB) {
h = (g-b) / deltaRGB;
} else if (g == maxRGB) {
h = 2.0 + (b-r) / deltaRGB;
} else if (b == maxRGB) {
h = 4.0 + (r-g) / deltaRGB;
}
}
h = h * 60.0;
if(h < 0.0) {
h += 360;
}
*H = (USHORT_T)h;
*S = (USHORT_T)(s * 1000);
*V = (USHORT_T)(v * 1000);
}