簡體   English   中英

如何確定給定顏色的更深或更淺的顏色變體?

[英]How do I determine darker or lighter color variant of a given color?

給定系統或用戶的任何色調的源顏色,我想要一個簡單的算法,我可以使用它來計算出所選顏色的更淺或更深的變體。 類似於在 Windows Live Messenger 上用於設置用戶界面樣式的效果。

語言是帶有 .net 3.5 的 C#。

回應評論:顏色格式為(Alpha)RGB。 將值作為字節或浮點數。

標記答案:對於我使用的上下文(一些簡單的 UI 效果),我標記為已接受的答案實際上是此上下文中最簡單的。 但是,我也放棄了對更復雜和准確的答案的投票。 任何進行更高級顏色操作並在將來找到此線程的人都應該檢查一下。 謝謝。 :)

XNA 中有Color.Lerp靜態方法,它可以作為兩種顏色之間的差異來執行此操作。

Lerp是兩個浮點數之間的數學運算,它通過它們之間差值的比率改變第一個浮點數的值。

這是一個對float執行此操作的擴展方法:

public static float Lerp( this float start, float end, float amount)
{
    float difference = end - start;
    float adjusted = difference * amount;
    return start + adjusted;
}

那么使用 RGB 的兩種顏色之間的簡單 lerp 操作將是:

public static Color Lerp(this Color colour, Color to, float amount)
{
    // start colours as lerp-able floats
    float sr = colour.R, sg = colour.G, sb = colour.B;

    // end colours as lerp-able floats
    float er = to.R, eg = to.G, eb = to.B;

    // lerp the colours to get the difference
    byte r = (byte) sr.Lerp(er, amount),
         g = (byte) sg.Lerp(eg, amount),
         b = (byte) sb.Lerp(eb, amount);

    // return the new colour
    return Color.FromArgb(r, g, b);
}

應用它的一個例子是這樣的:

// make red 50% lighter:
Color.Red.Lerp( Color.White, 0.5f );

// make red 75% darker:
Color.Red.Lerp( Color.Black, 0.75f );

// make white 10% bluer:
Color.White.Lerp( Color.Blue, 0.1f );

只需將 RGB 值乘以您想要修改級別的數量。 如果其中一種顏色已經達到最大值,那么你就不能讓它更亮(無論如何都要使用 HSV 數學。)

這給出了與切換到 HSV 然后修改 V 完全相同的結果,但數學運算要少得多。 只要您不想開始失去飽和度,這與切換到 HSL 然后修改 L 的結果相同。

HSV(色相/飽和度/值)也稱為HSL(色相/飽和度/亮度)只是一種不同的顏色表示。

使用這種表示可以更容易地調整亮度。 因此,從 RGB 轉換為 HSV,使“V”變亮,然后再轉換回 RGB。

下面是一些要轉換的C代碼

void RGBToHSV(unsigned char cr, unsigned char cg, unsigned char cb,double *ph,double *ps,double *pv)
{
double r,g,b;
double max, min, delta;

/* convert RGB to [0,1] */

r = (double)cr/255.0f;
g = (double)cg/255.0f;
b = (double)cb/255.0f;

max = MAXx(r,(MAXx(g,b)));
min = MINx(r,(MINx(g,b)));

pv[0] = max;

/* Calculate saturation */

if (max != 0.0)
    ps[0] = (max-min)/max;
else
    ps[0] = 0.0; 

if (ps[0] == 0.0)
{
    ph[0] = 0.0f;   //UNDEFINED;
    return;
}
/* chromatic case: Saturation is not 0, so determine hue */
delta = max-min;

if (r==max)
{
    ph[0] = (g-b)/delta;
}
else if (g==max)
{
    ph[0] = 2.0 + (b-r)/delta;
}
else if (b==max)
{
    ph[0] = 4.0 + (r-g)/delta;
}
ph[0] = ph[0] * 60.0;
if (ph[0] < 0.0)
    ph[0] += 360.0;
}

void HSVToRGB(double h,double s,double v,unsigned char *pr,unsigned char *pg,unsigned char *pb)
{
int i;
double f, p, q, t;
double r,g,b;

if( s == 0 )
{
    // achromatic (grey)
    r = g = b = v;
}
else
{
    h /= 60;            // sector 0 to 5
    i = (int)floor( h );
    f = h - i;          // factorial part of h
    p = v * ( 1 - s );
    q = v * ( 1 - s * f );
    t = v * ( 1 - s * ( 1 - f ) );
    switch( i )
    {
    case 0:
        r = v;
        g = t;
        b = p;
    break;
    case 1:
        r = q;
        g = v;
        b = p;
    break;
    case 2:
        r = p;
        g = v;
        b = t;
    break;
    case 3:
        r = p;
        g = q;
        b = v;
    break;
    case 4:
        r = t;
        g = p;
        b = v;
    break;
    default:        // case 5:
        r = v;
        g = p;
        b = q;
    break;
    }
}
r*=255;
g*=255;
b*=255;

pr[0]=(unsigned char)r;
pg[0]=(unsigned char)g;
pb[0]=(unsigned char)b;
}

Rich Newman 在他的博客上討論了關於 .NET System.Drawing.Color 的HSL 顏色,甚至提供了一個 HSLColor 類來為您完成所有工作。 將您的 System.Drawing.Color 轉換為 HSLColor,根據亮度添加/減去值,然后轉換回 System.Drawing.Color 以在您的應用程序中使用。

您可以將您的顏色轉換為 HSL 顏色空間,在那里對其進行操作並轉換回您選擇的顏色空間(很可能是 RGB)

顏色越淺,L 值越高,顏色越深,L 值越低。

這是相關的東西和所有的方程式:

http://en.wikipedia.org/wiki/HSL_color_space

另一種方法是簡單地用白色或黑色插入顏色。 這也會稍微降低顏色的飽和度,但計算起來更便宜。

我在System.Windows.Forms使用了ControlPaint.Dark().Light()

我猜你正在使用帶有字節值(0 到 255)的 RGB,因為這在任何地方都很常見。

為了更亮,用白色的 RGB 平均 RGB 值。 或者,為了控制增亮的程度,按一定比例混合它們。 f從 0.0 變化到 1.0,然后:

Rnew = (1-f)*R + f*255
Gnew = (1-f)*G + f*255
Bnew = (1-f)*B + f*255

對於更暗的顏色,請使用黑色的 RGB - 它全為零,使數學更容易。

我省略了一些細節,例如將結果轉換回字節,這可能是您想要做的。

如果您使用的是 RGB 顏色,我會將這些顏色參數轉換為HSL (色調、飽和度、亮度),修改亮度參數,然后再轉換回 RGB。 谷歌一下,你會發現很多關於如何進行這些顏色表示轉換(RGB 到 HSL,反之亦然)的代碼示例。

這是我很快發現的: http : //bytes.com/forum/thread250450.html

網站指出,您可以在 BCL C# System.Windows.Forms 命名空間中使用 ControlPaint 類。

假設您將顏色設為 RGB,首先將其轉換為 HSV(色調、飽和度、值)顏色空間。 然后增加/減少該值以產生更淺/更深的顏色陰影。 然后轉換回RGB。

如果您的顏色是 RGB 格式(或者,大概是 CMYK),您可以使用相當粗略的方法來增加顏色的每個分量的值。 例如,在 HTML 中,顏色表示為三個兩位的十六進制數字。 #ff0000 會給你一個亮紅色,然后可以通過將 G 和 B 組件的值增加相同的數量來淡化,例如#ff5555(給出更淺的紅色)。 大概對於色相、飽和度和亮度 (HSL) 顏色,您可以只提高 L 分量,但我不能肯定; 我對這個色彩空間不太熟悉。

不過,正如我所說,這種方法非常粗糙。 根據我對 Live Messenger 的記憶,聽起來您正在嘗試進行漸變,這在 Windows Presentation Foundation(WPF,.NET 3.0 的一部分)中可以非常輕松地應用。 WPF 支持許多不同類型的漸變畫筆,包括線性漸變和徑向漸變。

我強烈推薦 Adam Nathan 的書Windows Presentation Foundation Unleashed作為對 WPF 的一個很好的全面介紹。

HTH

在 HSL/HSV 中可以更好地完成顏色的任何變化。

一個很好的測試是在 RGB 空間和 HSL 空間中的兩個等效值之間進行插值。 HSL 空間的斜坡看起來是一個自然的過程。 在 RGB 空間中,它通常看起來很不自然。 HSL 映射到我們的視覺色彩空間感知比 RGB 好得多。

轉換為 HSV 或其他一些顏色空間的想法似乎不錯,並且對於精確的顏色工作可能是必要的,但對於普通目的,在 RGB 中工作的錯誤可能還不夠重要。 此外,處理邊界情況可能會很痛苦:RGB 是一個立方體形狀的空間,而 HSV 不是。 如果使用字節值,則可以在空間之間進行多對一和一對多映射。 這可能是也可能不是問題,具體取決於應用程序。 青年會

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM