Programmatically Lighten a Color

2020-01-24 03:26发布

Motivation

I'd like to find a way to take an arbitrary color and lighten it a few shades, so that I can programatically create a nice gradient from the one color to a lighter version. The gradient will be used as a background in a UI.

Possibility 1

Obviously I can just split out the RGB values and increase them individually by a certain amount. Is this actually what I want?

Possibility 2

My second thought was to convert the RGB to HSV/HSB/HSL (Hue, Saturation, Value/Brightness/Lightness), increase the brightness a bit, decrease the saturation a bit, and then convert it back to RGB. Will this have the desired effect in general?

20条回答
家丑人穷心不美
2楼-- · 2020-01-24 04:06

In order to get a lighter or a darker version of a given color you should modify its brightness. You can do this easily even without converting your color to HSL or HSB color. For example to make a color lighter you can use the following code:

float correctionFactor = 0.5f;
float red = (255 - color.R) * correctionFactor + color.R;
float green = (255 - color.G) * correctionFactor + color.G;
float blue = (255 - color.B) * correctionFactor + color.B;
Color lighterColor = Color.FromArgb(color.A, (int)red, (int)green, (int)blue);

If you need more details, read the full story on my blog.

查看更多
冷血范
3楼-- · 2020-01-24 04:10

In C#:

public static Color Lighten(Color inColor, double inAmount)
{
  return Color.FromArgb(
    inColor.A,
    (int) Math.Min(255, inColor.R + 255 * inAmount),
    (int) Math.Min(255, inColor.G + 255 * inAmount),
    (int) Math.Min(255, inColor.B + 255 * inAmount) );
}

I've used this all over the place.

查看更多
We Are One
4楼-- · 2020-01-24 04:10

Convert it to RGB and linearly interpolate between the original color and the target color (often white). So, if you want 16 shades between two colors, you do:


for(i = 0; i < 16; i++)
{
  colors[i].R = start.R + (i * (end.R - start.R)) / 15;
  colors[i].G = start.G + (i * (end.G - start.G)) / 15;
  colors[i].B = start.B + (i * (end.B - start.B)) / 15;
}
查看更多
淡お忘
5楼-- · 2020-01-24 04:10

I've done this both ways -- you get much better results with Possibility 2.

Any simple algorithm you construct for Possibility 1 will probably work well only for a limited range of starting saturations.

You would want to look into Poss 1 if (1) you can restrict the colors and brightnesses used, and (2) you are performing the calculation a lot in a rendering.

Generating the background for a UI won't need very many shading calculations, so I suggest Poss 2.

-Al.

查看更多
手持菜刀,她持情操
6楼-- · 2020-01-24 04:10

A bit late to the party, but if you use javascript or nodejs, you can use tinycolor library, and manipulate the color the way you want:

tinycolor("red").lighten().desaturate().toHexString() // "#f53d3d" 
查看更多
狗以群分
7楼-- · 2020-01-24 04:11

I didn't find this question until after it became a related question to my original question.

However, using insight from these great answers. I pieced together a nice two-liner function for this:

Programmatically Lighten or Darken a hex color (or rgb, and blend colors)

Its a version of method 1. But with over saturation taken into account. Like Keith said in his answer above; use Lerp to seemly solve the same problem Mark mentioned, but without redistribution. The results of shadeColor2 should be much closer to doing it the right way with HSL, but without the overhead.

查看更多
登录 后发表回答