Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Algorithm for Additive Color Mixing for RGB Values

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))   
like image 412
Gaidin Avatar asked Apr 07 '09 16:04

Gaidin


People also ask

What is the RGB The additive color mixing model?

The RGB color model is an additive color model in which the red, green, and blue primary colors of light are added together in various ways to reproduce a broad array of colors. The name of the model comes from the initials of the three additive primary colors, red, green, and blue.

How do you mix colors with RGB?

The Main Idea. To start mixing in RGB, think of each channel as a bucket of red, green, or blue paint. With 8 bits per channel, you have 256 levels of granularity for how much of that color you want to mix in; 255 is the whole bucket, 192 = three quarters, 128 = half bucket, 64 = quarter bucket, and so on.

How are RGB values calculated?

The function R*0.2126+ G*0.7152+ B*0.0722 is said to calculate the perceived brightness (or equivalent grayscale color) for a given an RGB color. Assuming we use the interval [0,1] for all RGB values, we can calculate the following: yellow = RGB(1,1,0) => brightness=0.9278.

How many color combinations are possible with RGB?

RGB color is best suited for on-screen applications, such as graphic design. Each color channel is expressed from 0 (least saturated) to 255 (most saturated). This means that 16,777,216 different colors can be represented in the RGB color space.


1 Answers

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

r = new Color(); r.A = 1 - (1 - fg.A) * (1 - bg.A); if (r.A < 1.0e-6) return r; // Fully transparent -- R,G,B not important r.R = fg.R * fg.A / r.A + bg.R * bg.A * (1 - fg.A) / r.A; r.G = fg.G * fg.A / r.A + bg.G * bg.A * (1 - fg.A) / r.A; r.B = fg.B * fg.A / r.A + bg.B * bg.A * (1 - fg.A) / r.A; 

fg is the paint color. bg is the background. r is the resulting color. 1.0e-6 is just a really small number, to compensate for rounding errors.

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:

// background, 50% green var bg = new Color { R = 0.00, G = 1.00, B = 0.00, A = 0.50 }; // paint, 50% red var fg = new Color { R = 1.00, G = 0.00, B = 0.00, A = 0.50 }; // The result var r = new Color(); r.A = 1 - (1 - fg.A) * (1 - bg.A); // 0.75 r.R = fg.R * fg.A / r.A + bg.R * bg.A * (1 - fg.A) / r.A; // 0.67 r.G = fg.G * fg.A / r.A + bg.G * bg.A * (1 - fg.A) / r.A; // 0.33 r.B = fg.B * fg.A / r.A + bg.B * bg.A * (1 - fg.A) / r.A; // 0.00 

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


You could also reverse these formulas:

var bg = new Color(); if (1 - fg.A <= 1.0e-6) return null; // No result -- 'fg' is fully opaque if (r.A - fg.A < -1.0e-6) return null; // No result -- 'fg' can't make the result more transparent if (r.A - fg.A < 1.0e-6) return bg; // Fully transparent -- R,G,B not important bg.A = 1 - (1 - r.A) / (1 - fg.A); bg.R = (r.R * r.A - fg.R * fg.A) / (bg.A * (1 - fg.A)); bg.G = (r.G * r.A - fg.G * fg.A) / (bg.A * (1 - fg.A)); bg.B = (r.B * r.A - fg.B * fg.A) / (bg.A * (1 - fg.A)); 

or

var fg = new Color(); if (1 - bg.A <= 1.0e-6) return null; // No result -- 'bg' is fully opaque if (r.A - bg.A < -1.0e-6) return null; // No result -- 'bg' can't make the result more transparent if (r.A - bg.A < 1.0e-6) return bg; // Fully transparent -- R,G,B not important fg.A = 1 - (1 - r.A) / (1 - bg.A); fg.R = (r.R * r.A - bg.R * bg.A * (1 - fg.A)) / fg.A; fg.G = (r.G * r.A - bg.G * bg.A * (1 - fg.A)) / fg.A; fg.B = (r.B * r.A - bg.B * bg.A * (1 - fg.A)) / fg.A; 

The formulas will calculate that background or paint color would have to be to produce the given resulting color.


If your background is opaque, the result would also be opaque. The foreground color could then take a range of values with different alpha values. For each channel (red, green and blue), you have to check which range of alphas results in valid values (0 - 1).

like image 104
Markus Jarderot Avatar answered Sep 24 '22 19:09

Markus Jarderot