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?
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.
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.
Pretend that you alpha blended to white:
where
amount
is from 0 to 1, with 0 returning the original color and 1 returning white.You might want to blend with whatever the background color is if you are lightening to display something disabled:
where
(dest_r, dest_g, dest_b)
is the color being blended to andamount
is from 0 to 1, with zero returning(r, g, b)
and 1 returning(dest.r, dest.g, dest.b)
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).
Here are two functions in Python. The first implements the naive approach which just clamps the RGB values to 255 if they go over. The second redistributes the excess values to keep the hue intact.
I created a gradient starting with the RGB value (224,128,0) and multiplying it by 1.0, 1.1, 1.2, etc. up to 2.0. The upper half is the result using
clamp_rgb
and the bottom half is the result withredistribute_rgb
. I think it's easy to see that redistributing the overflows gives a much better result, without having to leave the RGB color space.For comparison, here's the same gradient in the HLS and HSV color spaces, as implemented by Python's
colorsys
module. Only theL
component was modified, and clamping was performed on the resulting RGB values. The results are similar, but require color space conversions for every pixel.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).
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.