代码之家  ›  专栏  ›  技术社区  ›  VolkerK

如何确定给定颜色的深色或浅色变体?

  •  41
  • VolkerK  · 技术社区  · 17 年前

    给定系统或用户的任何色调的源颜色,我想要一个简单的算法,我可以使用它来计算出所选颜色的较浅或较深的变体。类似于在Windows Live Messenger上用于设置用户界面样式的效果。

    语言是C和.NET 3.5。

    回复评论: 颜色格式为(alpha)RGB。值为字节或浮点数。

    标记答案: 对于我使用的上下文(一些简单的UI效果),我标记为已接受的答案实际上对于这个上下文来说是最简单的。然而,我也放弃了对更复杂和准确的答案的投票。任何人做更先进的色彩操作,并在未来找到这个线程,一定要看看这些。谢谢。:)

    13 回复  |  直到 17 年前
        1
  •  28
  •   clahey    17 年前

    只需将RGB值乘以要修改级别的量。如果其中一种颜色已经达到最大值,则无法使其更亮(无论如何都使用HSV数学)。

    这与切换到hsv然后修改v的数学结果完全相同。这与切换到hsl然后修改l的结果相同,只要您不想开始失去饱和度。

        2
  •  46
  •   Keith    16 年前

    XNA there is the Color.Lerp static method 这就是两种颜色的区别。

    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 );
    
        3
  •  20
  •   KPexEA    17 年前

    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;
    }
    
        4
  •  14
  •   Travis Illig    17 年前

    富纽曼 discusses HSL color 关于他的博客上的.NET System.Drawing.Color,甚至 provides an HSLColor class 这一切都是为了你。将system.drawing.color转换为hslcolor,根据亮度添加/减去值,然后转换回system.drawing.color以在应用程序中使用。

        5
  •  10
  •   Nils Pipenbrinck    17 年前

    您可以将颜色转换为HSL颜色空间,在那里进行操作,然后转换回您选择的颜色空间(很可能是RGB)。

    较浅的颜色具有较高的L值,较深的颜色具有较低的L值。

    以下是相关的资料和所有的方程式:

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

    另一种方法是简单地用白色或黑色插入颜色。这也会降低颜色的饱和度,但计算起来更便宜。

        6
  •  9
  •   GregUzelac    17 年前

    我在system.windows.forms中使用了controlpaint.dark()和.light()。

        7
  •  4
  •   Arthur    14 年前

    我猜你用的是带字节值(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-这是所有的零,使数学更容易。

    我遗漏了一些细节,比如将结果转换回字节,这可能是您想要做的。

        8
  •  3
  •   sachaa    17 年前

    如果您使用的是RGB颜色,我会将此颜色参数转换为 HSL (色调、饱和度、亮度),修改亮度参数,然后转换回RGB。通过谷歌搜索,你会发现很多关于如何进行这些颜色表示转换(从RGB到HSL和Viceversa)的代码示例。

    这就是我很快发现的: http://bytes.com/forum/thread250450.html

        9
  •  0
  •   Dima    17 年前

    假设您得到的颜色是RGB,首先将其转换为hsv(色调,饱和度,值)颜色空间。然后增加/减少该值以产生颜色的较亮/较暗阴影。然后转换回RGB。

        10
  •  0
  •   alastairs    17 年前

    如果您的颜色是RGB格式(或者可能是CMYK格式),您可以使用相当粗糙的方法来增加颜色的每个组件的值。例如,在HTML中,颜色表示为三个两位数的十六进制数字。#ff0000将为您提供一个亮红色,然后可以通过将g和b分量的值增加相同的量(例如ff5555)使其褪色(使红色变浅)。大概对于色调、饱和度和明度(hsl)的颜色,你可以提高l分量,但我不能确定;我对这个颜色空间不太熟悉。

    不过,正如我所说,这种方法相当粗糙。从我的生活信使的记忆中,听起来好像你正在尝试做渐变,它可以在Windows演示基金会(WPF,部分.NET 3)中很容易地被应用。WPF支持许多不同类型的渐变画笔,包括线性和径向渐变。

    我强烈推荐亚当·内森的书 Windows Presentation Foundation Unleashed 作为WPF的一个很好和彻底的介绍。

    高温高压

        11
  •  0
  •   who    17 年前

    在HSL/HSV中,颜色的任何变化都是最好的。

    一个好的测试是在RGB空间和HSL空间中插入两个等效值。HSL空间的斜坡看起来像是一个自然的过程。在RGB空间中,它通常看起来很不自然。HSL映射到我们的视觉色彩空间感知比RGB好得多。

        12
  •  0
  •   DarenW    17 年前

    转换为hsv或其他颜色空间的想法似乎很好,可能对于精确的颜色工作是必要的,但对于普通目的而言,在RGB中工作的错误可能并不重要。此外,处理边界情况也很困难:RGB是一个立方体形状的空间,而HSV则不是。如果使用字节值,则可以在空间之间有多对一和一对多的映射。这可能是问题,也可能不是问题,具体取决于应用程序。牛传染性胃肠炎病毒

        13
  •  0
  •   TK.    17 年前

    这个 website 注意,您可以在bcl c system.windows.forms命名空间中使用controlPaint类。