# color space conversions and alpha compositing

• From: Cameron McCormack <cam@mcc.id.au>
• Date: Fri, 18 Feb 2011 16:24:08 +1300
• Message-ID: <20110218032408.GB26871@wok.mcc.id.au>
```I am reviewing my test painting-render-02-b.svg for correctness.  The
test involves alpha compositing when color-interpolation="linearRGB".

I will run through a worked example here, and hopefully someone can tell
me if I am doing it right.

Let’s perform alpha compositing where the background pixel is (0,0,0,1),
opaque black, and the foreground pixel to be composited into the
background is (1,1,1,0.5), half opaque white.  (I’m using component
values in the range [0, 1].)

For the sRGB ↔ linearRGB conversions I’m using the formulae on
http://en.wikipedia.org/wiki/SRGB#Specification_of_the_transformation:

R_s = R_linear ≤ 0.0031308 ? 12.92 * R_linear
: min(1.055 * pow(R_linear, 1 / 2.4), 1)
G_s = G_linear ≤ 0.0031308 ? 12.92 * G_linear
: min(1.055 * pow(G_linear, 1 / 2.4), 1)
B_s = B_linear ≤ 0.0031308 ? 12.92 * B_linear
: min(1.055 * pow(B_linear, 1 / 2.4), 1)
A_s = A_linear

and

R_linear = R_s ≤ 0.04045 ? R_s / 12.92
: pow((R_s + 0.055) / 1.055, 2.4)
G_linear = G_s ≤ 0.04045 ? R_s / 12.92
: pow((G_s + 0.055) / 1.055, 2.4)
B_linear = B_s ≤ 0.04045 ? B_s / 12.92
: pow((B_s + 0.055) / 1.055, 2.4)
A_linear = A_s

and for the compositing itself the formulae at

R_result = min((1 - A_fg) * R_bg + R_fg, 1)
G_result = min((1 - A_fg) * G_bg + G_fg, 1)
B_result = min((1 - A_fg) * B_bg + B_fg, 1)
A_result = 1 - (1 - A_fg) * (1 - A_bg)

For the unpremultiplied ↔ premultiplied alpha conversions I’m doing

R_pre = R * A
G_pre = G * A
B_pre = B * A
A_pre = A

and

R = R_pre / A
G = R_pre / A
B = R_pre / A
A = A_pre

bg = (0, 0, 0, 1)
fg = (1, 1, 1, 0.5)

Convert them to linearRGB space:

bg_linear = (0, 0, 0, 1)
fg_linear = (1, 1, 1, 0.5)    i.e., the same values

Since the alpha compositing is done with premultiplied colours, we
multiply the alpha in:

bg_linear_pre = (0, 0, 0, 1)
fg_linear_pre = (0.5, 0.5, 0.5, 0.5)

Do the alpha blending:

result_linear_pre = (0.5, 0.5, 0.5, 1)

Unpremultiply:

result_linear = (0.5, 0.5, 0.5, 1)

Convert to sRGB:

result = (0.790357, 0.790357, 0.790357, 1)

I think in this particular example, the order of the colour space
conversion and the alpha multiplication/division doesn’t matter, since
you get the same result.  Is that true in general, though?

Is my method above correct?

--
Cameron McCormack ≝ http://mcc.id.au/
```

Received on Friday, 18 February 2011 03:24:49 UTC