小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

HSL顏色處理

 我的菜譜123 2013-07-12

 

顏色的規(guī)律,個(gè)人理解 純屬扯淡 見諒。有些網(wǎng)上抄的 炒剩飯。

知識(shí)的海洋很深?yuàn)W 就像一個(gè)神奇的盒子 貌似理解了 可能有些東西再過(guò)幾年都沒(méi)能理解

顏色模式

色彩是由物體所反射光的波長(zhǎng)來(lái)決定的

RGB加色模式

 

RGB為三個(gè)能量值 能量值的強(qiáng)弱直觀的反映了明與暗 能量值越強(qiáng)越亮

 

而CMY減色模式是跟RGB互逆的一種方式

介質(zhì)是白的 然后要把顏料涂上去 展現(xiàn)各種色彩。

物體是什么 物體可以反射光 但同時(shí)也要吸收一定的能量值,

所以從本質(zhì)上看把顏料涂上去是一個(gè)變暗的過(guò)程。CMY正符合了這種原理。

你看RGB三原色交叉部分不正是CMY嗎 自然界是多么的神奇。

 

HSB(HSL) 色調(diào)飽和度亮度模式

以另外一種不同的理念進(jìn)行色彩的調(diào)配

H色調(diào) 0~360 圓環(huán)形式 以角度表示

S 飽和度 0~1 之間的小數(shù)

L 亮度 0~1 之間的小數(shù)

 

什么是純色

先來(lái)看一下windows的拾色器

 

最上頭黑色框里面那些顏色 最最最頂端的部分。

是不是感覺(jué)他們最鮮艷 最惹眼,嗯 因?yàn)樗麄僐GB之間的差異化最大

RGB產(chǎn)生顏色的原理就是RGB三個(gè)能量值產(chǎn)生差異化 組合。

所以我們才能看到這些花花綠綠的顏色。

純色一個(gè)特點(diǎn)那就是最大值跟最小值的差是255 ,差異達(dá)到最大。

也就是說(shuō)RGB一定有一個(gè)顏色是0 一個(gè)是255,否則不能稱之為純色

純亮度表示就是只能量值沒(méi)有差異 也指灰度圖

 

在液晶屏上以仰視的角度看上面的那幅圖  你會(huì)看到底部飽和度比較低的部分。TFT屏幕都是這樣 可視角度比較差

就像這樣的效果:

 

這就是為什么確定RGB為三基色,其實(shí)我也不懂 但是看了上圖估計(jì)也不需要過(guò)多的技術(shù)解釋了吧。

 

純色的計(jì)算

通過(guò)觀察windows畫圖板拾色器 就是上面中間那個(gè)破圖。我們知道 如果飽和度固定為1 亮度固定為0.5 ,那么色調(diào)即純色 純色即色調(diào)。純色的定義參見上面。

從RGB值的變化規(guī)律可以看出色調(diào)的變化是連續(xù)平緩 首尾相接的 可以看成是一個(gè)360度的圓 紅色是0度。他的變化規(guī)律是:

 

又是看圖

這鬼的規(guī)律啊 哪有什么規(guī)律 花花綠綠好看吧 有點(diǎn)像披薩,說(shuō)錯(cuò)了 有點(diǎn)像燒餅。

三個(gè)規(guī)律

1至始至終都有一個(gè)值是0 一個(gè)值是255。

2整個(gè)過(guò)程中同一時(shí)間總是只有一個(gè)值在變

3三個(gè)數(shù)的全排列 那么總共有6種組合

形象點(diǎn)來(lái)說(shuō)

有一個(gè)值在增加 增滿過(guò)后另一個(gè)值再增加 本值再減小 就像這樣從左往右 以長(zhǎng)江后浪推前浪 前仆后繼的方式達(dá)到原點(diǎn)  有點(diǎn)像合金彈頭游戲里面那種循環(huán)的無(wú)縫銜接背景 哥們兒你聽懂我在說(shuō)什么了嗎。其實(shí)我也沒(méi)搞懂自己在說(shuō)什么。

 

通過(guò)以上我們寫段代碼枚舉一些個(gè)純色

但是首先有一點(diǎn)要明確: 就是那塊披薩 就是60度 值是255

我們把色調(diào)分成1~360的表現(xiàn)形式,但是RGB是以(255,255,255)的表現(xiàn)形式 那么他們之間怎么對(duì)應(yīng)呢?那就是60度=255

每前進(jìn)一度scale =(255*6)*(1/360)

RGB可以表達(dá)255*255*255=16581375種顏色 但是他可以表達(dá)的純色只有255*6=1530種

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
public void getHue()
{
    Graphics gph = Graphics.FromHwnd(this.Handle);
    int indx = 0;
  
    //狀態(tài)是Up 顏色是綠色 這已經(jīng)很明顯了吧,這正是0度時(shí)候推進(jìn)的趨勢(shì)
    bool high = true;//Up
    int scale = 1;//0紅色 1綠色 2藍(lán)色
    int[] cor = { 255, 0, 0 };//0度角 紅色
  
    Color[] cors = new Color[36];
    Color result = Color.FromArgb(cor[0], cor[1], cor[2]);
    int curScale = 0;
    //推進(jìn)以便 生成所有色調(diào)的顏色表
    //這里的30指前進(jìn)30步 與其他并無(wú)關(guān)系
    //具體前進(jìn)的范圍為: 步數(shù)*(255D * 6 * (每步的大小 / 360D))
    //注意每步大小的值不能超過(guò)60 因?yàn)?0=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);
    }
}

 

 

 

增加他們之間的密度 越密過(guò)度越平滑

最平滑的狀況是 scale =1

 

越稀 則越粗糙 他的極限是 scale =(255*6)*(60/360)

即 scale =255 超過(guò)255是無(wú)意義的 因?yàn)閟cale的取值是0~255

 

別看幾句破代碼 調(diào)試的時(shí)候可是費(fèi)了我好大勁兒。

 

我們已經(jīng)能枚舉所有色調(diào),實(shí)際上他是一個(gè)從0度(255,0,0)偏移的過(guò)程。但是更改色調(diào)有沒(méi)有一種快速的方式計(jì)算呢。難道每確定一個(gè)顏色都進(jìn)行255*6=1530次循環(huán)?不會(huì)吧。

自然不會(huì) 但是最多進(jìn)行6次循環(huán)是必須的 因?yàn)榫W(wǎng)上的公式也要進(jìn)行6個(gè)switch 囧 說(shuō)明磚家該研究的早就研究過(guò)了 咱不可能超過(guò)磚家 對(duì)吧。

快速計(jì)算的方式就是~~~ 加速每次偏轉(zhuǎn)的值 更改偏轉(zhuǎn)的次數(shù) 嗯 條件是不少于6次。怎么樣換湯不換藥吧~~~ 囧

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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 他們之間到底有什么奧秘

我們來(lái)做個(gè)windows畫圖板那樣的拾色器順便 測(cè)試下上面函數(shù)的正確性

 

色調(diào)有了 然后就是處理飽和度

這個(gè)規(guī)律比色調(diào)那個(gè)簡(jiǎn)單多了

還是通過(guò)觀察拾色器

R2為處理后的值 R1為處理前的值 :R2=R1 (127-R1)*S

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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個(gè)等級(jí)的飽和度
    {
        for (int j = 0; j < cors.Length; j )//顏色數(shù)
        {
            //計(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
}

 


 

 

但是有一點(diǎn)要說(shuō)明下 如果一幅圖像的色調(diào)降得很低了接近灰度了 說(shuō)明他的顏色信息已經(jīng)損失了 再去還原他的色調(diào)是有困難的

 

上圖雖然已經(jīng)達(dá)到我們要的目的了,但是我們就是愛(ài)折騰 就是要讓他不一樣 ~~

把for循環(huán)里面的顏色計(jì)算代碼改成這樣:

1
2
3
4
5
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));

 


 

 

這反映了一個(gè)現(xiàn)象 雖然某些顏色看上去不是紅色

但是他三基色的組成里紅色成分越多被侵蝕就越嚴(yán)重 紅色成分越少越抗侵蝕,看 多么的完美 這與photoshop里的調(diào)色常識(shí)不謀而合。

 

說(shuō)道他們的奧秘嘛 ,咳咳咳 。其實(shí)也沒(méi)什么奧秘

總結(jié)下:

飽和度度/彩度 指顏色信息 降低容易 降低到一定程度 還原可就難了。

色調(diào)其實(shí)是指飽和度為1 亮度為0.5的 這種特例情況 也指純色。純色定義見前面

亮度、飽和度的調(diào)整 都是以純色為初始的 所以找出純色很關(guān)鍵。

從純色算法以及能量值差異原理可以知道 色調(diào)主要跟RGB里的最大值最小值相關(guān) 他們之間的差異反映了色調(diào) 他們跟另外一個(gè)值進(jìn)行調(diào)配 反映了飽和度。最大值的強(qiáng)弱反映了可見度 即亮度。

何以見得呢。

調(diào)用.net自帶的函數(shù)得到飽和度

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

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

輸出結(jié)果是0.8196079

你可以試驗(yàn)一下把210改到(23,232)范圍內(nèi)的任意值 最后輸出的結(jié)果都是一樣的。

 

 

網(wǎng)上寫的那些公式

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
public Color getRGBfromHSV(double _h, double _s, double _v)//色相 飽和度 亮度
{
    int h1 = (int)(_h / 60 % 6);//確定色調(diào)在色帶中的位置 其實(shí)就是確定色調(diào)
    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;
//按色調(diào)對(duì)這些值進(jìn)行分配
    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;
}

 


 

我照著公式的原理寫了段代碼 神了 確實(shí)可以用 但是說(shuō)實(shí)話我真沒(méi)搞太懂。看問(wèn)題要研究他的本質(zhì) 不能老抄別人的。

 

 另一段改自C 的轉(zhuǎn)換代碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
public Color GetRGBColorFromHSV(double _h, double _s, double _v)//色相 飽和度 亮度
{
    double r, g, b;
    if (_s == 0)//如果飽和度為0則是灰度圖 rgb三個(gè)值都將等于亮度
    {
        r = _v;
        g = _v;
        b = _v;
    }
    else
    {
        double[] dp = new double[3];
        double xh = _h * 6;//色相x6 ?
        if (xh == 6) xh = 0;//色環(huán)是一個(gè)360度的圓環(huán) 如果超過(guò)最大值則變?yōu)?
        //int i = (int)(Math.Floor(xh) 0.1);//色相x6取整數(shù) 0.1 ?
        int i = (int)xh;
        dp[0] = 1; dp[2] = 0; xh -= i;
        if (i % 2 != 0)// (i&1) //如果i是奇數(shù)
            dp[1] = 1 - xh;
        else
            dp[1] = xh;
        //處理色調(diào)
        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);
        }
        //三個(gè)元素的全排列 ?
        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;
}

 調(diào)用上面的函數(shù)來(lái)整點(diǎn)花哨的效果 一個(gè)圓環(huán)形的色帶:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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);

 

 

亮度部分我暫時(shí)不想寫了 累了 下次補(bǔ)上。

亮度0.5是個(gè)分水嶺 高于0.5的時(shí)候RGB三個(gè)值都是增的趨勢(shì) 低于0.5時(shí)是減的趨勢(shì)

 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多