[cairo] X11 image data rendering problems (Xrender ?)
Bertram Felgenhauer
bertram.felgenhauer at googlemail.com
Sun Mar 23 15:06:54 PDT 2008
Julien Danjou wrote:
> Hi people,
>
> Well, I've been using cairo for some time and had no problem. Until now.
>
> I used to render PNG data onto Xlib Drawable using the
> cairo_image_surface_create_from_png().
> Some others pictures were rendered using
> cairo_image_surface_create_for_data().
>
> Everything was fine.
>
> Now, I dropped the usage of cairo_image_surface_create_from_png() since
> I heard that is was not the Good Way To Go anyway, and use only
> cairo_image_surface_create_for_data() for all types of data file I
> get. FWIW, I use Imlib2 to get image data in ARGB32 format.
Imlib2's ARGB32 format is, however, incompatible with cairo's, because
cairo expects pre-multiplied alpha images. (This is mentioned in passing
at
http://cairographics.org/manual/cairo-Image-Surfaces.html#cairo-format-t
but I don't know whether the docs explain this in detail.)
You can use imlib2 to do the pre-multiplication:
/* in: image = source imlib image with alpha */
imlib_context_set_image(image);
int w = imlib_image_get_width();
int h = imlib_image_get_height();
/* create temporary image */
Imlib_Image premul = imlib_create_image(w, h);
/* FIXME: add error handling */
/* fill with opaque black */
imlib_context_set_image(premul);
imlib_context_set_color(0, 0, 0, 255);
imlib_image_fill_rectangle(0, 0, w, h);
/* blend source image on top - in effect this multiplies the
* rgb values by alpha */
imlib_blend_image_onto_image(image, 0, 0, 0, w, h, 0, 0, w, h);
/* and use the alpha channel of the source image */
imlib_image_copy_alpha_to_image(image, 0, 0);
/* now pass the result to cairo */
cairo_surface_t *result = cairo_image_surface_create_for_data(
(void *) imlib_image_get_data_for_reading_only(),
CAIRO_FORMAT_ARGB32, w, h, sizeof(DATA32) * w);
/* out: result = cairo surface */
You can use something like
static void free_imlib_image(void *img)
{
Imlib_Image save = imlib_context_get_image();
imlib_context_set_image(img);
imlib_free_image();
imlib_context_set_image(save);
}
[...]
static cairo_user_data_key_t free_premul_image_key;
cairo_surface_set_user_data(
result, &free_premul_image_key, (void *) prepare, free_imlib_image);
to automatically free the premultiplied data along with the cairo surface.
(This assumes that Imlib_Image is a pointer. It is, but that's not
documented.)
HTH,
Bertram
More information about the cairo
mailing list