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.
def clamp_rgb(r, g, b):
return min(255, int(r)), min(255, int(g)), min(255, int(b))
def redistribute_rgb(r, g, b):
threshold = 255.999
m = max(r, g, b)
if m <= threshold:
return int(r), int(g), int(b)
total = r + g + b
if total >= 3 * threshold:
return int(threshold), int(threshold), int(threshold)
x = (3 * threshold - total) / (3 * m - total)
gray = threshold - x * m
return int(gray + x * r), int(gray + x * g), int(gray + x * b)
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 with redistribute_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 the L
component was modified, and clamping was performed on the resulting RGB values. The results are similar, but require color space conversions for every pixel.
This should work - just linearly scale the red and green values. Assuming your max red/green/blue value is 255
, and n
is in range 0 .. 100
R = (255 * n) / 100
G = (255 * (100 - n)) / 100
B = 0
(Amended for integer maths, tip of the hat to Ferrucio)
Another way to do would be to use a HSV colour model, and cycle the hue from 0 degrees
(red) to 120 degrees
(green) with whatever saturation and value suited you. This should give a more pleasing gradient.
Here's a demonstration of each technique - top gradient uses RGB, bottom uses HSV:
Best Answer
First, please be aware that three numbers don't describe a color, three numbers together with a colorspace do. RGB isn't a colorspace, it's what's called a color model. There are lots of colorspaces with the RGB model. So ((1,0,0), sRGB) is a different color than ((1,0,0), Adobe RGB). Are you aware of how string encodings work, where a bunch of bytes by itself is not a string? It's a lot like that. It's also similar in that you're kind of asking for trouble whenever you want to look at the component values, because it's an opportunity for messing up the colorspace handling.
Sorry, cannot help myself. Anyway, I'll answer the question as if your original color was ((1,0,0), Generic RGB).
and on the other hand,
These fooComponent methods do not work with all colors, only those in two specific colorspaces, see docs. You already know you're good if you created the colors yourself with the methods above. If you have a color of unknown provenance, you can (attempt to) convert it to a colorspace in which you can use those component methods with
-[NSColor colorUsingColorspaceName:]
.