tags:

views:

2260

answers:

5

I'm looking for an algorithm to do additive color mixing for RGB values.

Is it as simple as adding the RGB values together to a max of 256?

(r1, g1, b1) + (r2, g2, b2) =
    (min(r1+r2, 256), min(g1+g2, 256), min(b1+b2, 256))
+2  A: 

Yes, it is as simple as that. Another option is to find the average (for creating gradients).

It really just depends on the effect you want to achieve.

However, when Alpha gets added, it gets complicated. There are a number of different methods to blend using an alpha.

An example of simple alpha blending: http://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending

John Gietzen
+7  A: 

It depends on what you want, and it can help to see what the results are of different methods.

If you want

Red + Black        = Red
Red + Green        = Yellow
Red + Green + Blue = White
Red + White        = White 
Black + White      = White

then adding with a max works (e.g. min(r1 + r2, 255)) This is more like the light model you've referred to.

If you want

Red + Black        = Dark Red
Red + Green        = Dark Yellow
Red + Green + Blue = Dark Gray
Red + White        = Pink
Black + White      = Gray

then you'll need to average the values (e.g. (r1 + r2) / 2) This works better for lightening/darkening colors and creating gradients.

Daniel LeCheminant
Sounds more like I want the 2nd option, thanks
Gaidin
+1  A: 

More "natural" would be:

  ((r1+r2)/2, (g1+g2)/2, (b1+b2)/2)

Or more generally, x of color1 and 1-x of color2 (eg. ¾ of first color, ¼ of second):

  (r1*x+r2*(1-x), g1*x+g2*(1-x), b1*x+b2*(1-x))
vartec
If both colors are within (0,255), there is no need for max(*, 256)
MizardX
of course, got influenced by the question ;-)
vartec
max(x,255) where x is less than 255 will always be 255? Am I going crazy?
fuzzy-waffle
No, I wrote the wrong one, and many people followed suit assuming that I would know the difference between min and max!
Gaidin
+2  A: 

Few points:

  • I think you want to use min instead of max
  • I think you want to use 255 instead of 256

This will give:

(r1, g1, b1) + (r2, g2, b2) = (min(r1+r2, 255), min(g1+g2, 255), min(b1+b2, 255))

However, The "natural" way of mixing colors is to use the average, and then you don't need the min:

(r1, g1, b1) + (r2, g2, b2) = ((r1+r2)/2, (g1+g2)/2, (b1+b2)/2)

Dani van der Meer
You are absolutely right... I will change my answer
Dani van der Meer
Sorry. I am halucingating. min(a,b) will give the least value of a and b. min(a,constant) will constrain a below the constant.
MizardX
+3  A: 

To blend using alpha channels, you can use these formulas:

ax = 1 - (1 - a) * (1 - A)
rx = r * a / ax + R * A * (1 - a) / ax
gx = g * a / ax + G * A * (1 - a) / ax
bx = b * a / ax + B * A * (1 - a) / ax

(r,g,b,a) is the paint color. (R,G,B,A) is the background. (rx,gx,bx,ax) is the resulting color.

NOTE: All variables used here are in the range [0.0, 1.0]. You have to divide or multiply by 255 if you want to use values in the range [0, 255].

For example, 50% red on top of 50% green:

(R, G, B, A) = (0.00, 1.00, 0.00, 0.50)  # background, 50% green
(r, g, b, a) = (1.00, 0.00, 0.00, 0.50)  # paint, 50% red
ax = 1 - (1 - a) * (1 - A) = 0.75
rx = r * a / ax + R * A * (1 - a) / ax = 0.67
gx = g * a / ax + G * A * (1 - a) / ax = 0.33
bx = b * a / ax + B * A * (1 - a) / ax = 0.00

Resulting color is: (0.67, 0.33, 0.00, 0.75), or 75% brown (or dark orange).

MizardX