C#: 根据系统颜色创建较浅/较暗的颜色

72
10个回答

118

ControlPaint.Light .Dark .DarkDark等。

Color lightRed = ControlPaint.Light( Color.Red );

1
ControlPaint.Light和.Dark非常完美:D 特别是带有额外百分比浮点参数的东西。 - Svish
2
今天我意识到.Net框架非常庞大。因为我之前不知道ControlPaint类。但是我只使用第三方图像处理库(如AForge.net)。谢谢。 - user94893
1
可以将百分比传递给此函数,但是在 MSDN 中没有提供有关此百分比形式的线索,只知道它是浮点数。 - Steve Smith
1
我相信这仅适用于Windows表单(但OP没有提到)。 - d219
如果它是浮点数,那么它将从0到1。 - Sod Almighty

101

我最近在博客中谈到了这个问题。主要思路是对每个颜色分量应用一个给定的校正系数。以下静态方法使用指定的校正因子修改给定颜色的亮度,并生成较暗或较亮的变体:

/// <summary>
/// Creates color with corrected brightness.
/// </summary>
/// <param name="color">Color to correct.</param>
/// <param name="correctionFactor">The brightness correction factor. Must be between -1 and 1. 
/// Negative values produce darker colors.</param>
/// <returns>
/// Corrected <see cref="Color"/> structure.
/// </returns>
public static Color ChangeColorBrightness(Color color, float correctionFactor)
{
    float red = (float)color.R;
    float green = (float)color.G;
    float blue = (float)color.B;

    if (correctionFactor < 0)
    {
        correctionFactor = 1 + correctionFactor;
        red *= correctionFactor;
        green *= correctionFactor;
        blue *= correctionFactor;
    }
    else
    {
        red = (255 - red) * correctionFactor + red;
        green = (255 - green) * correctionFactor + green;
        blue = (255 - blue) * correctionFactor + blue;
    }

    return Color.FromArgb(color.A, (int)red, (int)green, (int)blue);
}

3
很棒的答案。比ControlPaint.Dark或ControlPaint.Light更好。ControlPaint方法在非常小的百分比上效果不佳,它们有一些内置的最小值。你的代码甚至可以在0.1f下工作。 - TechAurelian
@Pavel 如果我想要同一种颜色的n个浅色调,我该如何使用你的算法? - Geek
1
@Geek,要生成给定颜色的n个浅色阴影,只需在(0,1]范围内执行算法并使用不同的校正系数,例如0.05、0.10、0.15等。 - Pavel Vladov
1
你应该添加完整的公式。此外,也可以通过将所有颜色乘以从0到2的百分比因子来实现。例如:1 = 100% = 无变化。0.8 = 暗20%。1.2 = 亮20%。 - Pedro77
很棒的方法@PavelVladov。这可以很容易地成为一个扩展,使调整亮度变得更加容易。 - hacker
显示剩余2条评论

17

你也可以使用 Lerp 函数来实现这个功能。XNA 中有一个这样的函数,但是你也可以自己编写。

请参见我在类似问题上的回答以获取 C# 实现。

该函数使您能够执行以下操作:

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

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

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

11
大多数这些方法确实会使颜色变暗,但它们对色调的调整过于夸张,所以结果看起来并不好。最好的解决方案是使用Rich Newman's HSLColor类,并调整亮度。
public Color Darken(Color color, double darkenAmount) {
    HSLColor hslColor = new HSLColor(color);
    hslColor.Luminosity *= darkenAmount; // 0 to 1
    return hslColor;
}

HSL颜色空间允许更好的明暗处理和创建彼此看起来“正确”的配色方案组件。RGB空间无法可靠地为这些类型的任务创建高质量的结果。 - Special Sauce
最终我使用了这个代码,并进行了修改,添加了亮度调节并加入了 darkenAmount 参数(我将其命名为 percentage),让它从颜色到黑或白之间工作。变暗:hslColor.Luminosity *= 1 - percentage; 变亮:hslColor.Luminosity /= 1 - percentage;。感谢您提供这个出色的答案。 - ctwheels

6

借鉴@Pavel的答案中的核心方法,我为了更直观(至少对于我来说)的签名准备了以下两个小扩展方法。

public static Color LightenBy(this Color color, int percent)
{
    return ChangeColorBrightness(color, percent/100.0);
}

public static Color DarkenBy(this Color color, int percent)
{
    return ChangeColorBrightness(color, -1 * percent / 100.0); 
}

3

您也可以通过调整RGB百分比来使颜色变浅或变深,以下是如何使颜色比原来暗x%的示例:

//_correctionfactory in percentage, e.g 50 = make it darker 50%
    private Color DarkerColor(Color color, float correctionfactory = 50f)
    {
        const float hundredpercent = 100f;                        
        return Color.FromArgb((int)(((float)color.R / hundredpercent) * correctionfactory),
            (int)(((float)color.G / hundredpercent) * correctionfactory), (int)(((float)color.B / hundredpercent) * correctionfactory));
    }

另外一个方法是我们可以反向操作,使颜色变得更轻。只需要将255-RGB的结果乘以所需百分比即可,例如以下示例:

private Color LighterColor(Color color, float correctionfactory = 50f)
    {
        correctionfactory = correctionfactory / 100f;
        const float rgb255 = 255f;
        return Color.FromArgb((int)((float)color.R + ((rgb255 - (float)color.R) * correctionfactory)), (int)((float)color.G + ((rgb255 - (float)color.G) * correctionfactory)), (int)((float)color.B + ((rgb255 - (float)color.B) * correctionfactory))
            );
    }

希望这能帮到你。

3

以下是我用于调整颜色明暗度的JavaScript代码。您可以将其作为C#函数的基础。

它的工作原理是计算每个RGB组件与纯白之间的距离,然后通过提供的因子调整此距离。新的距离用于计算新的颜色。因子介于0和1之间时会使颜色变暗,大于1时会使颜色变亮。

function Darken( hexColor, factor )
    {   
        if ( factor < 0 ) factor = 0;

        var c = hexColor;
        if ( c.substr(0,1) == "#" )
        {
            c = c.substring(1);
        }

        if ( c.length == 3 || c.length == 6 )
        {
            var i = c.length / 3;

            var f;  // the relative distance from white

            var r = parseInt( c.substr(0, i ), 16 );
            f = ( factor * r / (256-r) );
            r = Math.floor((256 * f) / (f+1));

            r = r.toString(16);
            if ( r.length == 1 ) r = "0" + r;

            var g = parseInt( c.substr(i, i), 16);
            f = ( factor * g / (256-g) );
            g = Math.floor((256 * f) / (f+1));
            g = g.toString(16);
            if ( g.length == 1 ) g = "0" + g;

            var b = parseInt( c.substr( 2*i, i),16 );
            f = ( factor * b / (256-b) );
            b = Math.floor((256 * f) / (f+1));
            b = b.toString(16);
            if ( b.length == 1 ) b = "0" + b;

            c =  r+g+b;
         }   

         return "#" + c;

    }

0

使用 HSI 转换库(搜索谷歌)。然后,调整 I 通道以获得更浅/更深的颜色。


0
我制作了一个网站,可以实现这个功能colorglower.com。你可以查看演示。
以下是我使用的JavaScript代码。
function lighten(color) {

// convert to decimal and change luminosity
var luminosity = 0.01
var computedColors = new Array();
var newColor = "#",
    c, i, n, black = 0,
    white = 255;
for (n = 0; n < 10; n++) {
    for (i = 0; i < 3; i++) {
        c = parseInt(color.substr(i * 2, 2), 16);
        c = Math.round(Math.min(Math.max(black, c + (luminosity * white)), white)).toString(16);
        newColor += ("00" + c).substr(c.length);
    }

    computedColors[n] = newColor;
    var arrayUnique = checkIfArrayIsUnique(computedColors);
    if (arrayUnique == false) {
        computedColors.pop();
        break;
    }

    computedColors[n] = newColor;
    newColor = "#";
    luminosity += calcPercentage();
}

return computedColors;

}

这段代码的作用是接收一个十六进制颜色值,然后输出其10个最浅的颜色版本,并将它们放入数组中。您可以更改亮度以调整阴影百分比。要使颜色变暗,只需更改以下内容:
luminosity -= calcPercentage();

-1

我修改了Pavel Vladov的函数来修改即使是RGB成分,以获得任何R/G/B方向组合的阴影:

Public Function ChangeColorShades(color As Color, correctionFactor As Single, bR As Boolean, bG As Boolean, bB As Boolean) As Color


    Dim red As Single = CSng(color.R)
    Dim green As Single = CSng(color.G)
    Dim blue As Single = CSng(color.B)

    If (correctionFactor < 0) Then

        correctionFactor = 1 + correctionFactor
        If bR Then
            red *= correctionFactor
        End If
        If bG Then
            green *= correctionFactor
        End If
        If bB Then
            blue *= correctionFactor
        End If


    Else
        If bR Then
            red = (255 - red) * correctionFactor + red
        End If
        If bG Then
            green = (255 - green) * correctionFactor + green
        End If
        If bB Then
            blue = (255 - blue) * correctionFactor + blue
        End If

    End If

    Return color.FromArgb(color.A, CInt(red), CInt(green), CInt(blue))
End Function

4
标记为C#的问题 - jasttim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接