[Pixman] Op. when compositing

Søren Sandmann soren.sandmann at gmail.com
Thu Jun 12 08:01:19 PDT 2014

Eric Nicolas <erik.nicolas at gmail.com> writes:

> Hello, Thanks for your answer.
> Below is a small test program (works on little endian machines).
> As is the result is already strange to me :
>      in: r=20 g=20 b=80 a=FF
>      out: r=90 g=90 b=C0 a=FF
> Where as I expected the fill color #FFFFFFFF x the mask 0x80 = #FFFFFF80
> and so an output of #9090FFFF.
> However, if I set the fill color to #FFFFFF80, the result seems really
> wrong :
> in: r=20 g=20 b=80 a=FF
> out: r=98 g=98 b=E0 a=FF
> I would expect fill x mask => #FFFFFF40 and thus out: #606060C0FF.
> I especially do not understand how a lower alpha input color can end up in
> a lighter output on the target image.
> What I am doing wrong here ?

The thing you are missing is that Pixman works with premultiplied
alpha. That is, if the rgb values are R, G, and B, and the alpha value
is A, then pixman will assume that pixels are stored as

   R * A, G * A, B * A, A

and it will also generate pixels in this format. The reason for doing
this is that it avoids divisions when compositing.

When you set the fill value to 0xffffff80 pixman will interprete it as 

     (1.0 / 0.5), (1.0 / 0.5), (1.0 / 0.5), 0.5

   = (2, 2, 2, 0.5)

ie., you get out-of-range color values, which is why the result will be
lighter. Normally, the alpha value in premultiplied pixels should not be
bigger than the color values, though it can occasionally be useful.

Premultiplied alpha also means that when applying an alpha mask, it must
be applied to all four channels, so in this case you get

   0xffffff80 x 0x80 = 0x80808040

when applying the mask.


More information about the Pixman mailing list