Finding "Equivalent" Color with Opacity

Finding equivalent color with opacity

Color blending is just a linear interpolation per channel, right? So the math is pretty simple. If you have RGBA1 over RGB2, the effective visual result RGB3 will be:

r3 = r2 + (r1-r2)*a1
g3 = g2 + (g1-g2)*a1
b3 = b2 + (b1-b2)*a1

…where the alpha channel is from 0.0 to 1.0.

Sanity check: if the alpha is 0, is RGB3 the same as RGB2? Yes. If the alpha is 1, is RGB3 the same as RGB1? Yes.

If you locked down only the background color and final color, there are a large number of RGBA colors (infinite, in floating-point space) that could satisfy the requirements. So you have to pick either the color of the bar or the opacity level you want, and find out the value of the other.

Picking the Color Based on Alpha

If you know RGB3 (the final desired color), RGB2 (the background color), and A1 (how much opacity you want), and you are just looking for RGB1, then we can re-arrange the equations thusly:

r1 = (r3 - r2 + r2*a1)/a1
g1 = (g3 - g2 + g2*a1)/a1
b1 = (b3 - b2 + b2*a1)/a1

There are some color combinations which are theoretically possible, but impossible given the standard RGBA range. For example, if the background is pure black, the desired perceived color is pure white, and the desired alpha is 1%, then you would need:

r1 = g1 = b1 = 255/0.01 = 25500

…a super-bright white 100× brighter than any available.

Picking the Alpha Based on Colors

If you know RGB3 (the final desired color), RGB2 (the background color), and RGB1 (the color you have that you want to vary the opacity of), and you are just looking for A1, then we can re-arrange the equations thusly:

a1 = (r3-r2) / (r1-r2)
a1 = (g3-g2) / (g1-g2)
a1 = (b3-b2) / (b1-b2)

If these give different values, then you can't make it match exactly, but you can average the alphas to get as close as possible. For example, there's no opacity in the world that will let you put green over red to get blue.

Calculate a color with opacity based on it's values over other colors?

Yes you can, by solving a system of linear equations. Let's look at the red channel as an example:

Variables:

c - color (unknown)

f - opacity (unknown)

Equations:

c * f + (1 − f) * 255 = 160. (blending with white)

c * f + (1 − f) * 0 = 73. (blending with black)

Rearrange to get:

c * f − 255 f = −95.

c * f = 73.

255 f = 168.

Therefore:

f = 168/255 ≈ 65.9%.

c = 6205/56 ≈ 110.8.

Computing the other channels, your final color is (111,167,220) and opacity is 66%.

Transparent equivalent of given color

Have you had a look at ?rgb?

Usage:

rgb(red, green, blue, alpha, names = NULL, maxColorValue = 1)

An alpha transparency value can also be specified (as an opacity,
so ‘0’ means fully transparent and ‘max’ means opaque). If
alpha’ is not specified, an opaque colour is generated.

The alpha parameter is for specifying transparency. col2rgb splits R colors specified in other ways into RGB so you can feed them to rgb.

Change Colour Opacity When Dont know RGB values only Alpha

Problem

Using the opacity property on the button itself would affect the text of the button; not ideal.

Solution

Apply the background color to a pseudo-element instead and layer it underneath the text with negative z-index. When needed, use the opacity property on the pseudo-element to create your transparent background.

Example

Note: Pseudo-elements cannot be applied to the <input> element as it cannot have children. This will only work with elements that can have children, such as <button> and <a>.

button {

position: relative;

background: none;

border: solid 1px #EEE;

padding: 10px;

border-radius: 5px;

overflow: hidden;

}

button:before {

content: '';

position: absolute;

top: -1px;

right: -1px;

bottom: -1px;

left: -1px;

background: red;

z-index: -1;

opacity: .5;

}

button:hover:before {

opacity: .8;

}

button:active:before {

background: orange;

}
<button>Button</button>

computing RGBA to match an RGB color

You mean you want the RGBA color with maximum transparency which, when drawn on top of a white background, gives the original RGB color?

Let R0, G0 and B0 be the components of the original color, each ranging from 0.0 to 1.0, and let R, G, B and A be the components of the new RGBA color (with A = 1 denoting 100% opacity). We know that the colors must satisfy:

R0 = A·R + (1 − A)

G0 = A·G + (1 − A)

B0 = A·B + (1 − A)

which, if we knew A, we could easily solve for R, G and B:

R = (R0 − 1 + A) / A = 1 − (1 − R0) / A
G = (G0 − 1 + A) / A = 1 − (1 − G0) / A
B = (B0 − 1 + A) / A = 1 − (1 − B0) / A

Since we require that R ≥ 0, G ≥ 0 and B ≥ 0, it follows that 1 − R0 ≥ A, 1 − G0 ≥ A and 1 − B0 ≥ A, and therefore the smallest possible value for A is:

A = max( 1 − R0, 1 − G0, 1 − B0 ) = 1 − min( R0, G0, B0 )

Thus, the color we want is:

A = 1 − min( R0, G0, B0 )

R = 1 − (1 − R0) / A
G = 1 − (1 − G0) / A
B = 1 − (1 − B0) / A


Ps. For a black background, the same formulas would be even simpler:

A = max( R0, G0, B0 )

R = R0 / A
G = G0 / A
B = B0 / A


Pps. Just to clarify, all the formulas above are for non-premultiplied RGBA colors. For premultiplied alpha, just multiply R, G and B as calculated above by A, giving:

R = A · ( 1 − (1 − R0) / A ) = R0 − (1 − A)

G = A · ( 1 − (1 − G0) / A ) = G0 − (1 − A)

B = A · ( 1 − (1 − B0) / A ) = B0 − (1 − A)

(or, for a black background, simply R = R0, G = G0 and B = B0.)

Color calculations: increase alpha but maintain the same color appearance over a white background

So I know this question is now almost a year old, but I had the same problem and found the solution so I thought I'd share it. The term for this is "alpha compositing" and wikipedia has a great article on it.

http://en.wikipedia.org/wiki/Alpha_compositing

In your case you are compositing your color with a fully opaque white rgba(255,255,255,1).

I made an excel calculator to do this. I couldn't figure out how to put the cell values themselves into StackOverflow, so here's a screenshot of the forumulas. Orange cells are for your input.

Excel Formulas

You can then change A10-A13 to define your initial color and D10 to specify your desired alpha.

Combined known colors           
Color 1 Color 2 Combined
A 0.15 1 =$B$3+$C$3*(1-$B$3)
R 255 255 =(1/($D$3))*(B4*$B$3+C4*$C$3*(1-$B$3))
G 0 255 =(1/($D$3))*(B5*$B$3+C5*$C$3*(1-$B$3))
B 0 255 =(1/($D$3))*(B6*$B$3+C6*$C$3*(1-$B$3))

1 Known Color, Known result Alpha
Color 1 Color 2 Combined
A 0.15 =(D10-B10)/(1-B10) 0.85
R 255 255 =(1/($D$10))*(B11*$B$10+C11*$C$10*(1-$B$10))
G 255 255 =(1/($D$10))*(B12*$B$10+C12*$C$10*(1-$B$10))
B 0 255 =(1/($D$10))*(B13*$B$10+C13*$C$10*(1-$B$10))

In Swift calculate color without transparency obtained by overlaying a color with an transparant color

The alpha of the overlay color (a2) tells you the percentage that color contributes to the total, and (1 - a2) tells you the percentage the original color contributes. From that, it is a straightforward calculation:

func calculateColor(orgColor: UIColor, overlayColor: UIColor) -> UIColor {
// Helper function to clamp values to range (0.0 ... 1.0)
func clampValue(_ v: CGFloat) -> CGFloat {
guard v > 0 else { return 0 }
guard v < 1 else { return 1 }
return v
}

var (r1, g1, b1, a1) = (CGFloat(0), CGFloat(0), CGFloat(0), CGFloat(0))
var (r2, g2, b2, a2) = (CGFloat(0), CGFloat(0), CGFloat(0), CGFloat(0))

orgColor.getRed(&r1, green: &g1, blue: &b1, alpha: &a1)
overlayColor.getRed(&r2, green: &g2, blue: &b2, alpha: &a2)

// Make sure the input colors are well behaved
// Components should be in the range (0.0 ... 1.0)
r1 = clampValue(r1)
g1 = clampValue(g1)
b1 = clampValue(b1)

r2 = clampValue(r2)
g2 = clampValue(g2)
b2 = clampValue(b2)
a2 = clampValue(a2)

let color = UIColor( red: r1 * (1 - a2) + r2 * a2,
green: g1 * (1 - a2) + g2 * a2,
blue: b1 * (1 - a2) + b2 * a2,
alpha: 1)

return color
}

Intuitively this checks out. If the overlay color is fully opaque (a2 == 1) then the result will be the overlay color. If the overlay color is fully transparent (a2 == 0), the result will be the original color. If the overlay color's alpha is 0.5, you will get a blend that is exactly halfway between the two colors.


Testing it in a Playground:

// Make these colors anything you want
let c1 = UIColor(red: 27/255, green: 155/255, blue: 199/255, alpha: 1.0)
let c2 = UIColor(red: 188/255, green: 13/255, blue: 51/255, alpha: 0.37)

let c3 = calculateColor(orgColor: c1, overlayColor: c2)

let view1 = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
let view2 = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))

view1.backgroundColor = c1
view2.backgroundColor = c2

// Overlay view2 onto view1
view1.addSubview(view2)

// view3 has the calculated color
let view3 = UIView(frame: CGRect(x: 100, y: 0, width: 100, height: 100))
view3.backgroundColor = c3

// display the views side by side in view4
let view4 = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 100))
view4.addSubview(view1)
view4.addSubview(view3)

// display this view and see that the two halves match
view4

Playground output:

Playground output



Related Topics



Leave a reply



Submit