[cairo] Applying to a surface the alpha of other

Bill Spitzak spitzak at gmail.com
Mon Oct 22 03:48:51 PDT 2012


He does not want to un-premultiply.

The desired operation is to change (r,g,b,a) to (r,g,b,1). Note that the output r == input r.

I agree this is an obvious operation and should be supported somehow.

I'm not sure but it is possible that setting the operator to ADD and compositing (0,0,0,1) would work?

On Oct 16, 2012, at 3:48 PM, Krzysztof Kosiński wrote:

> 2012/10/16 Carlos López González <genetita at gmail.com>:
>> Hi,
>> unfortunately the proposed solution doesn't work. When a ARGB32 color
>> is painted in a RGB24 surface, the colors are multiplied by the alpha.
>> Say I have a ARGB color:
>> ARGB(0.8, 1.0, 0.5, 0.5)
>> once painted to a RGB24 surface it becomes:
>> RGB(0.8, 0.4, 0.4)
>> 
>> Later if I mask back this color thru a 0.6 alpha mask, then it keeps
>> the RGB values and keeps the alpha but the colors are washed out:
>> 
>> ARGB(0.6, 0.8, 0.4, 0.4)
>> 
>> When my desired result is
>> ARGB(0.6, 1.0, 0.5, 0.5) that is keep the colors of one surface and
>> apply the alpha of other.
>> 
>> Any other idea?
> 
> For an image surface, you can manipulate the pixels directly with code
> like this:
> 
> cairo_surface_flush(s);
> int w = cairo_image_surface_get_width(s);
> int h = cairo_image_surface_get_height(s);
> int stride = cairo_image_surface_get_stride(s);
> char *data = cairo_image_surface_get_data(s);
> 
> for (int y = 0; y < h; ++y) {
>  unsigned *row = data + y * stride;
>  for (int x = 0; x < w; ++x) {
>    unsigned px = row[x];
>    unsigned a = (px & 0xff000000) >> 24;
>    unsigned r = (px & 0x00ff0000) >> 16;
>    unsigned g = (px & 0x0000ff00) >> 8;
>    unsigned b = (px & 0x000000ff);
> 
>    // un-premultiply color values
>    if (a != 0) {
>      r = (255 * r + a/2) / a;
>      g = (255 * g + a/2) / a;
>      b = (255 * g + a/2) / a;
>    }
> 
>    // assemble the resulting pixel from components
>    row[x] = 0xff000000 | (r << 16) | (g << 8) | b;
>  }
> }
> 
> cairo_surface_mark_dirty(s);
> 
> Note that since Cairo uses premultiplied alpha compositing, you will
> lose a lot of precision precision for low alpha values, which may look
> very ugly. This could be solved with a floating point surface format,
> but Cairo doesn't have one right now.
> 
> Regards, Krzysztof
> -- 
> cairo mailing list
> cairo at cairographics.org
> http://lists.cairographics.org/mailman/listinfo/cairo



More information about the cairo mailing list