cairo_surface_t * _cairo_image_surface_create_from_pixbuf (GdkPixbuf *pixbuf) { cairo_surface_t *surface; cairo_surface_metadata_t *metadata; int width; int height; int p_stride; int p_n_channels; guchar *p_pixels; int s_stride; unsigned char *s_pixels; int h, w; guint32 pixel; guchar r, g, b, a; if (pixbuf == NULL) return NULL; g_object_get (G_OBJECT (pixbuf), "width", &width, "height", &height, "rowstride", &p_stride, "n-channels", &p_n_channels, "pixels", &p_pixels, NULL ); surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); s_stride = cairo_image_surface_get_stride (surface); s_pixels = _cairo_image_surface_flush_and_get_data (surface); metadata = _cairo_image_surface_get_metadata (surface); metadata->has_alpha = (p_n_channels == 4); if (p_n_channels == 4) { guchar *s_iter; guchar *p_iter; for (h = 0; h < height; h++) { s_iter = s_pixels; p_iter = p_pixels; for (w = 0; w < width; w++) { a = p_iter[3]; if (a == 0xff) { pixel = CAIRO_RGBA_TO_UINT32 (p_iter[0], p_iter[1], p_iter[2], 0xff); } else if (a == 0) { pixel = 0; } else { r = _cairo_multiply_alpha (p_iter[0], a); g = _cairo_multiply_alpha (p_iter[1], a); b = _cairo_multiply_alpha (p_iter[2], a); pixel = CAIRO_RGBA_TO_UINT32 (r, g, b, a); } memcpy (s_iter, &pixel, sizeof (guint32)); s_iter += 4; p_iter += p_n_channels; } s_pixels += s_stride; p_pixels += p_stride; } } else { guchar *s_iter; guchar *p_iter; for (h = 0; h < height; h++) { s_iter = s_pixels; p_iter = p_pixels; for (w = 0; w < width; w++) { pixel = CAIRO_RGBA_TO_UINT32 (p_iter[0], p_iter[1], p_iter[2], 0xff); memcpy (s_iter, &pixel, sizeof (guint32)); s_iter += 4; p_iter += p_n_channels; } s_pixels += s_stride; p_pixels += p_stride; } } cairo_surface_mark_dirty (surface); return surface; }