HSL颜色处理

 

颜色之原理,个人掌握 纯属扯淡 见谅。有些网上抄的 炒剩饭。

知的大洋非常深奥 就像一个神奇的盒子 貌似理解了
可能小东西再过几年还没有能明了

水彩模式

情调是由物体所反射光的波长来控制的

RGB加色模式

 

图片 1

RGB也老三只能值 能量值的强弱直观的体现了明和暗 能量值更强越亮

 

苟CMY减色模式是跟RGB互逆的同等种植办法

介质是白之 然后如把颜料涂上失去 展现各种色彩。

体是呀 物体可以反射光 但同时也只要收得的会量值,

用由精神上看把颜料涂上是一个变暗的进程。CMY正顺应了这种规律。

您看RGB三原色交叉部分不亏CMY吗 自然界是多的神奇。

 

HSB(HSL) 色调饱和度亮度模式

因另外一栽不同的看法进行色彩的调配

H色调 0~360 圆环形式 以角度表示

S 饱和度 0~1 之间的小数

L 亮度 0~1 之间的小数

 

哎是纯色

优先来拘禁一下windows的拾色器

 

图片 2

顶上面黑色框里面那些颜色 最极端极端上方的一对。

凡是免是感到他们极鲜艳 最惹眼,嗯 因为他俩RGB之间的差异化最充分

RGB有颜色之法则就是是RGB三单能值产生差异化 组合。

因而我们才能够顾这些多彩的水彩。

纯色一个特征那就是极其充分价值与最小值的不比是255 ,差异及最可怜。

也就是说RGB一定生一个颜料是0 一个是255,否则不可知称之为纯色

纯亮度表示虽是不得不量值没有差异 也指灰度图

 

当液晶屏上以仰视的角度看上面的那么幅图 
你会见到底饱和度比较小的一部分。TFT屏幕还是这么 可视角度比较差

即使像这样的效果:

 

图片 3

旋即便是为何确定RGB为老三本色,其实自己哉无清楚
但是关押了直达图估计也未待了多的技艺解释了咔嚓。

 

纯色的盘算

通过观察windows画图板拾色器 就是方中间深破图。我们懂得
如果饱和度固定为1 亮度固定为0.5 ,那么色调即纯色
纯色即色调。纯色的概念参见上面。

起RGB值的变化规律可以看来色调的扭转是接连平缓 首尾相接的
可以当是一个360渡过的圆 红色是0度。他的变化规律是:

 

图片 4

又是圈图

立不好的法则啊 哪有什么规律 花花绿绿好看吧 有点像披萨,说错了 有硌像烧饼。

其三只规律

1暨始至终都有一个值是0 一个价值是255。

2合过程中同一时间总是独自发一个值当转移

3叔独数之全排列 那么总共有6种组成

形象点来说

有一个值当加 增满过后任何一个价值更多 本值再减多少 就如这么从左往右
以长江后浪推前浪 前仆后继的法及原点 
有点像合金弹头游戏之中那种循环的无缝对接背景
哥们公你听明白我于说啊了邪。其实自己吧从没弄明白自己以说啊。

 

由此以上我们描绘段子代码枚举一些只纯色

唯独首先有一些假设强烈: 就是那块披萨 就是60度过 值是255

俺们把色调分成1~360底表现形式,但是RGB是为(255,255,255)的表现形式
那么她们中间怎么对应为?那就是是60度=255

每前进一度scale+=(255*6)*(1/360)

RGB可以表达255*255*255=16581375种颜色
但是他得以发挥的纯色只生255*6=1530种

 

public void getHue()

{

    Graphics gph = Graphics.FromHwnd(this.Handle);

    int indx = 0;



    //状态是Up 颜色是绿色 这已经很明显了吧,这正是0度时候推进的趋势

    bool high = true;//Up

    int scale = 1;//0红色 1绿色 2蓝色

    int[] cor = { 255, 0, 0 };//0度角 红色



    Color[] cors = new Color[36];

    Color result = Color.FromArgb(cor[0], cor[1], cor[2]);

    int curScale = 0;

    //推进以便 生成所有色调的颜色表

    //这里的30指前进30步 与其他并无关系

    //具体前进的范围为: 步数*(255D * 6 * (每步的大小 / 360D))

    //注意每步大小的值不能超过60 因为60=255 scale的值域是[0,255]

    while (indx < 30)

    {

        if (high == true)

        {

            curScale = scale % 3;

            cor[curScale] += (int)(255D * 6 * (10 / 360D));

        }

        else if (high == false)

        {

            curScale = (scale - 1) % 3;//< 0 ? 0 : (scale - 1) % 3;

            cor[curScale] -= (int)(255D * 6 * (10 / 360D));

        }



        gph.DrawString(indx.ToString(), new Font(new FontFamily("宋体"), 9), new SolidBrush(Color.Black), 15 * (indx - 1), 50);



        if (cor[curScale] < 0)

        {

            cor[curScale] = 0;

            scale++;

            high = !high;

            gph.DrawString("▓", new Font(new FontFamily("宋体"), 9), new SolidBrush(Color.Black), 15 * (indx - 1), 90);

            continue;

        }

        else if (cor[curScale] > 255)

        {

            cor[curScale] = 255;

            //scale++;

            high = !high;

            gph.DrawString("▇ ", new Font(new FontFamily("宋体"), 9), new SolidBrush(Color.Black), 15 * (indx - 1), 90);

            continue;

        }



        cors[indx] = Color.FromArgb(cor[0], cor[1], cor[2]);

        gph.FillRectangle(new SolidBrush(Color.FromArgb(cor[0], cor[1], cor[2])), 15 * indx++, 0, 15, 20);

        gph.DrawString(curScale.ToString(), new Font(new FontFamily("宋体"), 9), new SolidBrush(Color.Black), 15 * (indx - 1), 30);



        gph.DrawString(scale.ToString(), new Font(new FontFamily("宋体"), 9), new SolidBrush(Color.Black), 15 * (indx - 1), 70);

    }

}

 

 

图片 5

 

增加她们中的密度 越密过于越平

极致坦荡的景象是 scale+=1

 

图片 6

愈来愈稀 则更聊糙 他的顶峰是 scale+=(255*6)*(60/360)

尽管 scale+=255 超过255凡是纸上谈兵的 因为scale的取值是0~255

 

图片 7

变更看几句子破代码 调试之时光可是费了自家吓大劲儿。

 

俺们早已会枚举所有色调,实际上他是一个打0度(255,0,0)偏移的过程。但是又改色调来无发一样种植高效的艺术计算呢。难道每确定一个颜色都开展255*6=1530次循环?不会吧。

自不见面 但是极多开展6糟巡回是要的 因为网上的公式为使进行6个switch 囧
说明砖家该钻之已经研究过了 咱不容许跨越砖家 对吧。

快快计算的方尽管是~ 加速每次偏转的值 更改偏转的次数 嗯
条件是免少于6蹩脚。怎么样换汤不换药吧
~ 囧

 

public Color getHue(int theta)//角度0~360

{

    int times = theta / 60, Mod = theta % 60;

    bool high = true;

    int scale = 1, indx = 0;

    int[] cor = { 255, 0, 0 };

    int curScale = 0;

    while (indx <times )

    {



        if (high == true)

        {

            curScale = scale % 3;

            cor[curScale] += 255 ;

        }

        else if (high == false)

        {

            curScale = (scale - 1) % 3;

            cor[curScale] -= 255 ;

        }



        if (cor[curScale] <= 0)

        {

            cor[curScale] = 0;

            scale++;

            high = !high;

        }

        else if (cor[curScale] >= 255)

        {

            cor[curScale] = 255;

            high = !high;

        }

        indx++;

    }



    if (high == true)

        cor[scale % 3] += (int)(255D * 6 * (Mod / 360D)) > 255 ? 255 : (int)(255D * 6 * (Mod / 360D));

    else if (high == false)

        cor[(scale - 1) % 3] -= (int)(255D * 6 * (Mod / 360D)) < 0 ? 0 : (int)(255D * 6 * (Mod / 360D));



    return Color.FromArgb(cor[0], cor[1], cor[2]);

}

 

 

 

纯色 饱和度 HSL RGB 他俩之间到底发生啊奥秘

俺们来开只windows画图板那样的拾色器顺便 测试下端函数的不易

 

色有矣 然后哪怕处理饱和度

本条规律比色调那个简单多矣

还是通过观察拾色器

R2也处理后底值 R1吧拍卖前的值 :R2=R1+(127-R1)*S

public void drawPalette()

{

    Graphics gph = Graphics.FromHwnd(this.Handle);

    //生成颜色表

    Color[] cors = new Color[(int)(360D / 11)];

    for (int i = 0; i < 360 - 11; i += 11)

        cors[(i / 11)] = getHue(i);



    //饱和度处理

    float s = 0;//饱和度

    for (int i = 0; i < 20; i++)//10行 10个等级的饱和度

    {

        for (int j = 0; j < cors.Length; j++)//颜色数

        {

            //计算方式 r'=r+(127-r)s

            Color corTmp = Color.FromArgb((int)(cors[j].R + (127 - cors[j].R) * s),

                (int)(cors[j].G + (127 - cors[j].G) * s),

                (int)(cors[j].B + (127 - cors[j].B) * s));



            gph.FillRectangle(new SolidBrush(corTmp), 15 * j, 15 * i, 15, 15);

        }

        s += (1f / 20);

    }



    //this.BackColor = getHue(59);//10 * i++

}

 

 

图片 8

 

然来某些只要说明下 如果一致幅图像的色泽降得不可开交没有了看似灰度了
说明外的水彩信息就损失了 再去恢复他的色是产生紧的

 

上图则曾经上我们而的目的了,但是咱尽管是容易折腾 就是设吃他未等同 ~~

将for循环里面的颜色计算代码改成为这样:

Color corTmp = Color.FromArgb((int)(cors[j].R + (255 - cors[j].R) * s),

                (int)(cors[j].G + (0 - cors[j].G) * s),

                (int)(cors[j].B + (0 - cors[j].B) * s));

 

 

 

图片 9

立马反映了一个景 虽然某些颜色看起来不是辛亥革命

但是他三本色的结缘里红色成分越多为祸害就越发严重 红色成分越少越抗侵蚀,看
多么的一应俱全 这与photoshop里的调色常识不谋而合。

 

商讨他们的深邃嘛 ,咳咳咳 。其实呢没有什么奥秘

总结下:

饱满度度/彩度 指颜色信息 降低容易 降低至早晚水平 还原可即不便了。

色彩其实是借助饱和度为1 亮度为0.5之 这种特例情况 也靠纯色。纯色定义见前面

亮度、饱和度的调动 都是因纯色为初始的 所以找来纯色很要紧。

起纯色算法和能值差距原理可以知晓 色调主要及RGB里之极致充分价值最小价相关
他们之间的差距反映了颜色 他们跟另外一个价值进行调配
反映了饱和度。最深价值的强弱反映了可见度 即亮度。

何以见得呢。

调用.net自带的函数得到饱和度

Color c = Color.FromArgb(210, 23, 232);

MessageBox.Show(c.GetSaturation().ToString());

出口结果是0.8196079

君得测验瞬间将210改成到(23,232)范围外的随机值
最后输出的结果尚且是一致的。

 

 

网上写的那些公式

 

图片 10

图片 11

 

public Color getRGBfromHSV(double _h, double _s, double _v)//色相 饱和度 亮度

{

    int h1 = (int)(_h / 60 % 6);//确定色调在色带中的位置 其实就是确定色调

    double f = _h / 60 - h1;

//确定最大值最小值 亮度

    double p = (_v * (1 - _s));

    double q = (_v * (1 - f * _s));

    double t = (_v * (1 - (1 - f) * _s));



Color cor;

//按色调对这些值进行分配

    switch (h1)

    {

        case 0:

            cor = Color.FromArgb((int)(_v * 255), (int)(t * 255), (int)(p * 255));

            break;

        case 1:

            cor = Color.FromArgb((int)(q * 255), (int)(_v * 255), (int)(p * 255));

            break;

        case 2:

            cor = Color.FromArgb((int)(p * 255), (int)(_v * 255), (int)(t * 255));

            break;

        case 3:

            cor = Color.FromArgb((int)(p * 255), (int)(q * 255), (int)(_v * 255));

            break;

        case 4:

            cor = Color.FromArgb((int)(t * 255), (int)(p * 255), (int)(_v * 255));

            break;

        default:

            cor = Color.FromArgb((int)(_v * 255), (int)(p * 255), (int)(q * 255));

            break;

    }

    return cor;

}

 

 

自随在公式的法则写了段代码 神了 确实可以用
但是说实话我真没有做太明白。看题目而钻他的原形 不可知老抄别人的。

 

 另一样段改自C++的变换代码:

public Color GetRGBColorFromHSV(double _h, double _s, double _v)//色相 饱和度 亮度
{
    double r, g, b;

    if (_s == 0)//如果饱和度为0则是灰度图 rgb三个值都将等于亮度
    {
        r = _v;
        g = _v;
        b = _v;
    }
    else
    {
        double[] dp = new double[3];
        double xh = _h * 6;//色相x6 ?
        if (xh == 6) xh = 0;//色环是一个360度的圆环 如果超过最大值则变为0
        //int i = (int)(Math.Floor(xh) + 0.1);//色相x6取整数+0.1 ?
        int i = (int)xh;
        dp[0] = 1; dp[2] = 0; xh -= i;
        if (i % 2 != 0)// (i&1) //如果i是奇数
            dp[1] = 1 - xh;
        else
            dp[1] = xh;

        //处理色调
        for (int n = 0; n < 3; ++n)
        {
            dp[n] = (((dp[n]) - 0.5) * (_s) + 0.5);
            //SATFORMAT(dp[n], _s);
        }


        //处理亮度
        if (_v == 0.5) { }
        else if (_v < 0.5)
        {
            if (_v < 0) _v = 0;
            for (int n = 0; n < 3; ++n)
                dp[n] = ((dp[n]) * (_v) * 2);
            //BLACKFORMAT(dp[n], _v)
        }
        else
        {
            if (_v > 1) _v = 1;
            for (int n = 0; n < 3; ++n)
                dp[n] = (1 - (1 - (dp[n])) * (1 - (_v)) * 2);
            //WHITEFORMAT(dp[n], _v);
        }


        //三个元素的全排列 ?

        switch (i)
        {
            case 0:
                r = dp[0]; g = dp[1]; b = dp[2];
                break;
            case 1:
                r = dp[1]; g = dp[0]; b = dp[2];
                break;
            case 2:
                r = dp[2]; g = dp[0]; b = dp[1];
                break;
            case 3:
                r = dp[2]; g = dp[1]; b = dp[0];
                break;
            case 4:
                r = dp[1]; g = dp[2]; b = dp[0];
                break;
            default:
                r = dp[0]; g = dp[2]; b = dp[1];
                break;
        }


    }

    //return ((int)(b * 255 + .5) << 16) + ((int)(g * 255 + .5) << 8) + (int)(r * 255 + .5);
    Color cor = Color.FromArgb((int)(r * 255 + 0.5), ((int)(g * 255 + 0.5)), ((int)(b * 255 + 0.5)));
    return cor;
}

 调用者的函数来整点花哨的意义 一个圆环形的色带:

Class1 c2 = new Class1();
Graphics gph = Graphics.FromHwnd(this.Handle);

Color[] cors = new Color[360];

gph.TranslateTransform(200, 200);

System.Drawing.Drawing2D.GraphicsPath ph = new System.Drawing.Drawing2D.GraphicsPath();
ph.AddEllipse(-100, -100, 200, 200);
ph.AddEllipse(-80, -80, 160, 160);

gph.SetClip(ph, System.Drawing.Drawing2D.CombineMode.Intersect);
for (int k = 0; k < 360; k++)
{
    cors[k] = c2.GetRGBColorFromHSV(1D/360 * k, 1D, 0.5D);

    gph.RotateTransform(1);
    gph.DrawLine(new Pen(new SolidBrush(cors[k]), 2), 0, 0, 100, 0);

}

gph.FillEllipse(new SolidBrush(Color.Transparent), -80, -80, 160, 160);

 

图片 12

 

亮度部分自临时未思量写了 累了 下涂鸦上及。

亮度0.5是单分水岭 高于0.5的时光RGB三只价都是长的趋向 低于0.5常是减的倾向