[Pixman] [cairo] LCD Alpha Blending Formulas [Repost from AGG]

Andrea Canciani ranma42 at gmail.com
Mon Feb 7 05:32:01 PST 2011

On Mon, Feb 7, 2011 at 1:30 PM, Petr Kobalíček <kobalicek.petr at gmail.com> wrote:
> Hi devs,
> [Repost from the AGG mailing list]
> this post is not strictly related to agg. I'm playing with one problem
> related to image compositing and I only need to confirm whether my
> solution is correct.
> I abstracted image compositing into following two functions:
>  CompositeC(Dca, Da, Sca, Sa) - Function that produces color component
> (premultiplied).
>  CompositeA(Dca, Da, Sca, Sa) - Function that produces alpha component.
> Where:
>  Dca = destination color * destination alpha (RGB*A)
>  Da = destination alpha (A)
>  Sca = source color * source alpha (RGB*A)
>  Sa = source alpha (A)
> Can be written as (svg):
>  Dca' = CompositeC(Dca, Da, Sca, Sa)
>  Da'  = CompositeA(Dca, Da, Sca, Sa)
> Where:
>  Dca' - new destination color component value
>  Da' - new destination alpha value
> Now when mask (Ma) is used the formula can be simply extended to (LERP):
>  Dca' = CompositeC(Dca, Da, Sca, Sa).Ma + Dca.(1 - Ma)
>  Da'  = CompositeA(Dca, Da, Sca, Sa).Ma + Dca.(1 - Ma)

This is not always true for cairo operators, but is correct for all of them
except the "unbounded" operators.
See http://www.cairographics.org/operators/ for some documentation
on cairo operators (the "unbounded" operators are also called "XRender"
operators here).

Cairo defines CLEAR and SOURCE as:
Dca' = Composite (Dca, Da, Sca, Sa).Ma + Dca.(1 - Ma)
Da'  = Composite (Dca, Da, Sca, Sa).Ma + Dca.(1 - Ma)

and all the other operators can be defined as:
Dca' = Composite (Dca, Da, Sca * Ma, Sa * Ma)
Da' = Composite (Da, Da, Sa * Ma, Sa * Ma)

> My problem is with ARGB mask, usually used for LCD-subpixel alpha blending.
> So my question is, can I use the following formula?:
>  Dca' = CompositeC(Dca, Da, Sca, Sa).Mc + Dca.(1 - Mc)
>  Da'  = CompositeA(Dca, Da, Sca, Sa).Ma + Dca.(1 - Ma)

Except for operators which behave differently in cairo and pixman (CLEAR
and SOURCE), you probably want to use pixman as reference.
See http://cgit.freedesktop.org/pixman/tree/test/composite.c#n434

Dca' = Composite (Dca, Da, Sca * Mca, Sa * Mca)
Da' = Composite (Da, Da, Sa * Ma, Sa * Ma)

I believe that SOURCE and CLEAR would instead be computed as:
Dca' = Composite (Dca, Da, Sca, Sa).Mca + Dca.(1 - Mca)
Da'  = Composite (Da, Da, Sa, Sa).Ma + Da.(1 - Ma)

Please notice that the two formulas should be equivalent for most

> Where:
>  Ma - Alpha component from the ARGB mask, this should be equal to max(R, G, B).
Neither cairo nor pixman seems to use or guarantee the assumption
Ma == max(Mr,Mg,Mb)

>  Mc - Color component from the ARGB mask (individual component for R, G, B).
Pixman and cairo always composite premultiplied color components. This
is the reason why I used Mca in the formulas above.

> It seems that cairo graphics library is using this formula, but skia not.
> BTW 1: Here is link to skia code, I don't understand why they used
> saturated addition:
>  http://code.google.com/p/skia/source/browse/trunk/src/core/SkBlitter_ARGB32_Subpixel.cpp

Cairo/pixman use saturated addition as well. The reason in pixman is
the definition of the operators in the RENDER specification.

I'm not sure about what operator is implemented in the file you
linked to. The alpha seems to be computed as in the ADD operator,
but the color components as in the SOURCE operator.
This is probably the reason why you get different results from skia
and cairo.


More information about the Pixman mailing list