- From: Alex Danilo <alex@abbra.com>
- Date: Fri, 18 Feb 2011 16:23:56 +1100
- To: Cameron McCormack <cam@mcc.id.au>
- Cc: public-svg-wg@w3.org

Hi Cam, I think you got the equations for linearRGB->sRGB wrong by the look of things (good ol' Wikipedia...) --Original Message--: >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 These terms should have a '- 0.055' for the larger value case. >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 >http://www.w3.org/TR/SVG/masking.html#SimpleAlphaBlending: > > 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 > > >So we start with: > > 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: You never unpremultiply. See: http://www.soe.ucsc.edu/classes/cmps160/Spring05/blinn_theory.pdf as a nice reference. Basically the intermediate bit plane always holds premultiplied colours. So, if you had 'enable-background="new"' on a group element, the intermediate backing store after all compositing would consist of premultiplied values and per-pixel alpha. > result_linear = (0.5, 0.5, 0.5, 1) > >Convert to sRGB: > > result = (0.790357, 0.790357, 0.790357, 1) The result with the corrected equation is 0.73535... which also handily multiplies by 255 to give 187 or 0xBB just like the viewers that support linearRGB compositing get. >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? No, not in general. sRGB is non-linear. So you will get a different result. See also: http://www.harrybardak.co.uk/sRGB.htm for some nice pictures of composited images. >Is my method above correct? Almost, just need to correct the equations. Cheers, Alex >-- >Cameron McCormack ≝ http://mcc.id.au/ > > >

Received on Friday, 18 February 2011 05:24:44 UTC