views:

3414

answers:

16

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?

+16  A: 

I would go for the second option. Generally speaking the RGB space is not really good for doing color manipulation (creating transition from one color to an other, lightening / darkening a color, etc). Below are two sites I've found with a quick search to convert from/to RGB to/from HSL:

Cd-MaN
A: 

I would have tried number #1 first, but #2 sounds pretty good. Try doing it yourself and see if you're satisfied with the results, it sounds like it'll take you maybe 10 minutes to whip up a test.

davr
+1  A: 

A very similar question, with useful answers, was asked previously: http://stackoverflow.com/questions/97646/how-do-i-determine-darker-or-lighter-color-variant-of-a-given-color

Short answer: multiply the RGB values by a constant if you just need "good enough", translate to HSV if you require accuracy.

Wedge
Upvoted for the reference to the similar question, but I disagree with the RGB advice - go HSV.
Blair Conrad
+3  A: 

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.

Nick
Very handy, and simple. Using it in a VB.NET app now.
Kezzer
See http://stackoverflow.com/questions/801406/c-create-a-lighter-darker-color-based-on-a-system-color
Martín Marconcini
+1  A: 

Converting to HS(LVB), increasing the brightness and then converting back to RGB is the only way to reliably lighten the colour without effecting the hue and saturation values (ie to only lighten the colour without changing it in any other way).

David Arno
+2  A: 

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;
}
Adam Rosenfield
In most cases only the start and end color are needed since the graphics library of choice probably has built in gradient capabilities.
Max Schmeling
+2  A: 

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.

A: 

Technically, I don't think either is correct, but I believe you want a variant of option #2. The problem being that taken RGB 990000 and "lightening" it would really just add onto the Red channel (Value, Brightness, Lightness) until you got to FF. After that (solid red), it would be taking down the saturation to go all the way to solid white.

The conversions get annoying, especially since you can't go direct to and from RGB and Lab, but I think you really want to separate the chrominance and luminence values, and just modify the luminence to really achieve what you want.

Pseudo Masochist
A: 

As Wedge said, you want to multiply to make things brighter, but that only works until one of the colors becomes saturated (i.e. hits 255 or greater). At that point, you can just clamp the values to 255, but you'll be subtly changing the hue as you get lighter. To keep the hue, you want to maintain the ratio of (middle-lowest)/(highest-lowest).

I'll edit this with an exact formula if I find a few more minutes later.

Mark Ransom
A: 

You'll find code to convert between color spaces in the color-tools ruby library

Thibaut Barrère
A: 

This is a dupe. I'll sacrifice the rep I'll lose posting this in order to clean it up - please close!

http://stackoverflow.com/questions/97646/how-do-i-determine-darker-or-lighter-color-variant-of-a-given-color

Bobby Jack
I disagree, that question is specific to C#, while this is language agnostic.
Keith
+3  A: 

ControlPaint class in System.Windows.Forms namespace has static methods Light and Dark:

public static Color Dark(Color baseColor, float percOfDarkDark);

These methods use private implementation of HLSColor. I wish this struct was public and in System.Drawing.

Alternatively, you can use GetHue, GetSaturation, GetBrightness on Color struct to get HSB components. Unfortunately, I didn't find the reverse conversion.

Ilya Ryzhenkov
A: 

IF you want to produce a gradient fade-out, I would suggest the following optimization: Rather than doing RGB->HSB->RGB for each individual color you should only calculate the target color. Once you know the target RGB, you can simply calculate the intermediate values in RGB space without having to convert back and forth. Whether you calculate a linear transition of use some sort of curve is up to you.

VoidPointer
A: 

I have a blog post that shows how to do this in Delphi. Its pretty simple because the functions ColorRGBToHSL and ColorHLSToRGB are part of the standard library.

Lawrence Barsanti
+1  A: 

Method 1: Convert RGB to HSL, adjust HSL, convert back to RGB.

Method 2: Lerp the RGB colour values - http://en.wikipedia.org/wiki/Lerp_(computing)

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

Keith
A: 

Try ColorJizz

Mikee
You should really state that you are the author.
Blair McMillan