71

Duplicate

How do I adjust the brightness of a color?
How do I determine darker or lighter color variant of a given color?
Programmatically Lighten a Color


Say I have

var c = Color.Red;

Now I want to create a new Color that is lighter or darker than that color. How can I do that without too much hassle?

Community
  • 1
  • 1
Svish
  • 152,914
  • 173
  • 462
  • 620

10 Answers10

117

ControlPaint.Light .Dark .DarkDark, etc.

Color lightRed = ControlPaint.Light( Color.Red );
schnaader
  • 49,103
  • 10
  • 104
  • 136
Paul Alexander
  • 31,970
  • 14
  • 96
  • 151
  • 1
    ControlPaint.Light and .Dark are perfect :D Especially with the extra percentage float parameter thingy. – Svish Apr 29 '09 at 08:51
  • 2
    Today, I realize that .Net framework is very huge size. Because I don't know about ControlPaint class before. But I use only 3-party image processing(like AForge.net). Thanks. –  Apr 29 '09 at 17:21
  • 1
    it is possible to pass a percentage to this function, though no clue is given in MSDN as to what form this pecentage takes, only that it's a float. – Steve Smith Jul 25 '17 at 15:37
  • 1
    I believe this only works for Windows forms though (which the OP makes no reference to) – d219 Apr 21 '20 at 21:47
  • If it's a float, then it'll be from 0 to 1. – Sod Almighty Jul 31 '21 at 16:18
100

I recently blogged about this. The main idea is to apply a given correction factor to each of the color components. The following static method modifies the brightness of a given color with a specified correction factor and produces a darker or a lighter variant of that color:

/// <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);
}
Pavel Vladov
  • 4,707
  • 3
  • 35
  • 39
  • 3
    Great answer. Better than ControlPaint.Dark or ControlPaint.Light. The ControlPaint methods do not work well with very small percentages, they have some built-in minimum. Your code works even with 0.1f. – TechAurelian Nov 15 '12 at 15:30
  • @Pavel if I want to have `n` lighter shades of the same color , how would I use your algorithm? – Geek Sep 10 '13 at 18:03
  • 1
    @Geek, to produce n lighter shades of a given color simply execute the algorithm with different correction factors in the range (0, 1], for example 0.05, 0.10, 0.15, etc. – Pavel Vladov Jan 02 '14 at 13:50
  • Nice. I can use negative numbers for darks and positive for lights – Sith2021 Jun 09 '14 at 02:59
  • @harveyt, to get a darker color it's best to use a slightly modified formula. **[The full article on my blog](http://www.pvladov.com/2012/09/make-color-lighter-or-darker.html)** gives a detailed explanation and code examples. – Pavel Vladov Jun 13 '14 at 06:09
  • 1
    You should add the full formula. Also, alternatively, ones can just multiply all the colors by a percent factor from 0 to 2. eg: 1 = 100% = no change. 0.8 = 20% darker. 1.2 = 20% lighter. – Pedro77 Aug 03 '14 at 19:57
  • Great method @PavelVladov. This is easily made into an extension to make modifying brightness even easier. – hacker Dec 22 '15 at 15:39
17

You can also do this using a Lerp function. There's one in XNA, but it's easy to write yourself.

See my answer to this similar question for a C# implementation.

The function lets you do this:

// 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 );
Community
  • 1
  • 1
Keith
  • 150,284
  • 78
  • 298
  • 434
11

Most of these methods do darken the color but they adjust the hue way to much so the result doesn't look very good. The best answer is to use Rich Newman's HSLColor class and adjust the luminosity.

public Color Darken(Color color, double darkenAmount) {
    HSLColor hslColor = new HSLColor(color);
    hslColor.Luminosity *= darkenAmount; // 0 to 1
    return hslColor;
}
TugboatCaptain
  • 4,150
  • 3
  • 47
  • 79
  • The HSL color space allows for much better lightening and darkening routines, as well as creating color scheme components that all look "right" together. The RGB space simply cannot reliably create quality results for these types of tasks. – Special Sauce Apr 20 '17 at 02:34
  • I ended up using this and tweaking it to add lighten and to have the `darkenAmount` parameter (which I named `percentage`) work from `color` to black or white. Darken: `hslColor.Luminosity *= 1 - percentage;` and Lighten: `hslColor.Luminosity /= 1 - percentage;`. Thank you for the great answer. – ctwheels Mar 26 '20 at 12:52
6

Taking the core method of @Pavel's answer I prepared the following two little extension methods for a more intuitive (at least for me) signature.

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); 
}
Community
  • 1
  • 1
Zoltán Tamási
  • 12,249
  • 8
  • 65
  • 93
3

Here's some javascript code I use for lightening/darkening a given colour. You could use it as a base for an equivalent C# function

It works by calculating a distance from pure white of each of the RGB components and then adjusts this distance by the provided factor. The new distance is used to calculate the new colour. A factor of between 0 and 1 darkens, a factor higher than 1 lightens

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;

    }
Tom Carter
  • 2,938
  • 1
  • 27
  • 42
2

You can also simply work on the RGB percentage to get it lighter or darker as you want, Here is an example for how to make a color darker x% than it is:

//_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));
    }

One more thing we can also reverse the process to be lighter instead, Only we getting the result of 255 - RGB and then multiply it by the percentage we want like the following example:

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))
            );
    }

Hope that helps.

Omar Negm
  • 21
  • 3
0

I made a site that does this colorglower.com You can check it out to see a demo.

Here's the javascript code i used.

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;

}

What this code does is it receives a hex color and then it outputs 10 lightest color versions of it and puts in in the array. You can change the luminosity to whatever you like to adjust the shade percentage. To darken the colors you just need to change:

luminosity -= calcPercentage();
shinra tensei
  • 693
  • 5
  • 20
  • 39
0

Using HSI converter library(search google). And then, adjust I channel for lighter/darker color.

user229044
  • 232,980
  • 40
  • 330
  • 338
-1

I changed Pavel Vladov function to modify even RGB component, to get shades on any combination of R/G/B directions:

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
Tratak
  • 138
  • 1
  • 9