首先理解 HSV/HSB/HSL 都是什么
我理解:
Hue : 色相
Saturation: 饱和度
其中的Value、Brightness、Lightness都是用于控制亮度用的
三者同一个意思,就是叫法不一
下面使用HSV的方式来介绍
下面是我看到这张图,然后对HSV的理解
从上图可以看出:Hue就是颜色的周期
逆时针一圈可以看出过渡规律:
R~RG~G~GB~B~RB~R
后面~R可以可以省略,因为可以倒回开头的R
如下:
R~RG~G~GB~B~RB~R
⇒
R~RG~G~GB~B~RB
(红~黄~绿~浅蓝~蓝~粉紫(倒回~红))
而这些过渡,对应的是:Hue的0~360的6个区间,如下伪代码,对应的是:Hue 与 RGB 的映射
// jave.lin 2019.09.03
// Hue to RGB
oneRegion = 360f/6; // 或是1f/6
region1 = onRegion;
region2 = onRegion * 2;
region3 = onRegion * 3;
region4 = onRegion * 4;
region5 = onRegion * 5;
region6 = onRegion * 6;
if (position >= region1 && position < region2) {
// R~RG
} else if (position >= region2 && position < region3) {
// RG~G
} else if (position >= region3 && position < region4) {
// G~GB
} else if (position >= region4 && position < region5) {
// GB~B
} else if (position >= region5 && position < region6) {
// B~RB
}
从上图可以看出来,就是颜色鲜艳度,就是对应白色到Hue色之间的过渡关系,Saturation越大越偏向于Hue色,否则偏向于白色
也可以理解为颜色的鲜艳度,饱和度高,越鲜艳,饱和度底,越灰白
对应伪代码就是:
// jave.lin 2019.09.03
// Saturation理解
float t = 0f~1f; // 或是0~100,用于控制饱和度强度
Color whiteColor = Color.white;
Color hueColor = ...; // 就是先从上面的hue中确定色相
Color FinalColor = Lerp(whiteColor, hueColor, t); // Lerp(a,b,t) => a*(1-t)+b*t,下面用到的Lerp都是一样的
从上图可以看出,Value就是控制亮度的,Value值越小,越偏向黑色,否则偏向Hue色相应用Saturation后的颜色
伪代码:
// jave.lin 2019.09.03
// Value 理解
float t = 0f~1f; // 或是0~100,用于控制亮度强度
Color saturateColor = Lerp(whiteColor, hueColor, saturateT); // 上面Saturate的值
Color blackColor = Color.black;
Color FinalColor = Lerp(blackColor, saturateColor, t);
主要以:Graphics类、与Bitmap来实现, Graphics.DrawImage(Image image);
圈圈、线条都是直接Graphics.DrawLine, Graphics.DrawEllipse
主要核心代码:
// t : [0~1]对应:0~360
// 返回的颜色
private void GetH(float t, out byte r, out byte g, out byte b)
{
r = 0; g = 0; b = 0;
const float t1 = 1f / 6;
const float t2 = 1f / 6 * 2;
const float t3 = 1f / 6 * 3;
const float t4 = 1f / 6 * 4;
const float t5 = 1f / 6 * 5;
const float t6 = 1f / 6 * 6;
const float invOne = 6f;
t = t < 0 ? 0 : t;
t = t > 1 ? 1 : t;
if (t >= 0 && t < t1)
{
// R ~ RG
r = 255;
g = (byte)(t * invOne * 255);
b = 0;
}
else if (t >= t1 && t < t2)
{
// RG ~ G
r = (byte)((1 - (t - t1) * invOne) * 255);
g = 255;
b = 0;
}
else if (t >= t2 && t < t3)
{
// G ~ GB
r = 0;
g = 255;
b = (byte)((t - t2) * invOne * 255);
}
else if (t >= t3 && t < t4)
{
// GB ~ B
r = 0;
g = (byte)((1 - (t - t3) * invOne) * 255);
b = 255;
}
else if (t >= t4 && t < t5)
{
// B ~ RB
r = (byte)((t - t4) * invOne * 255);
g = 0;
b = 255;
}
else if (t >= t5 && t <= t6)
{
// RB ~ R
r = 255;
g = 0;
b = (byte)((1 - (t - t5) * invOne) * 255);
}
}
private void GetSV(
// tr,tg,tb 目标颜色
byte tr, byte tg, byte tb,
// st 饱和度插值系数
// vt 亮度插值系数
float st, float vt,
// 输出的 rgb 颜色
out byte r, out byte g, out byte b)
{
float stt = 1 - st;
float vtt = 1 - vt;
// 饱和度
tb = Lerp(255, tb, st, stt);
tg = Lerp(255, tg, st, stt);
tr = Lerp(255, tr, st, stt);
// 亮度
b = Lerp(tb, 0, vt, vtt);
g = Lerp(tg, 0, vt, vtt);
r = Lerp(tr, 0, vt, vtt);
}
Test_HSV_HSB_HSL_色相_饱和度_亮度.zip