HSV/HSB/HSL 色相、饱和度、亮度的色彩模型

什么是HSV/HSB/HSL

首先理解 HSV/HSB/HSL 都是什么

我理解:

  • HSV : Hue, Saturation, Value
  • HSB : Hue, Saturation, Brightness
  • HSL : Hue, Saturation, Lightness(或是Luminance)

Hue : 色相
Saturation: 饱和度
其中的Value、Brightness、Lightness都是用于控制亮度用的

三者同一个意思,就是叫法不一
下面使用HSV的方式来介绍

看一张图:
HSV/HSB/HSL 色相、饱和度、亮度的色彩模型_第1张图片

下面是我看到这张图,然后对HSV的理解

Hue 色相

从上图可以看出: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
}

Saturation饱和度

从上图可以看出来,就是颜色鲜艳度,就是对应白色到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就是控制亮度的,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);

使用C# WinForm写了个Demo

主要以:Graphics类、与Bitmap来实现, Graphics.DrawImage(Image image);
圈圈、线条都是直接Graphics.DrawLine, Graphics.DrawEllipse
HSV/HSB/HSL 色相、饱和度、亮度的色彩模型_第2张图片

主要核心代码:

        // 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);
        }

Project

Test_HSV_HSB_HSL_色相_饱和度_亮度.zip

References

  • Unity Shader-后处理:简单的颜色调整(亮度,饱和度,对比度)
  • 彩色图像和颜色空间

你可能感兴趣的:(C#,理论,图形)