Re: cairo_surface_t to pixbuf
- From: Jean Bréfort <jean brefort normalesup org>
- To: Dov Grobgeld <dov grobgeld gmail com>
- Cc: gtk-list <gtk-list gnome org>
- Subject: Re: cairo_surface_t to pixbuf
- Date: Sun, 22 Feb 2009 16:13:49 +0100
You might also have a look at go_cairo_convert_data_to_pixbuf
( http://svn.gnome.org/viewvc/goffice/trunk/goffice/utils/go-cairo.c?revision=1884&view=markup ) which works when there is an alpha channel (things are not as simple as exchanging the R and B bytes):
/**
* go_cairo_convert_data_to_pixbuf:
* @src: a pointer to pixel data in cairo format
* @dst: a pointer to pixel data in pixbuf format
* @width: image width
* @height: image height
* @rowstride: data rowstride
*
* Converts the pixel data stored in @src in CAIRO_FORMAT_ARGB32 cairo
format
* to GDK_COLORSPACE_RGB pixbuf format and move them
* to @dst. If @src == @dst, pixel are converted in place.
**/
void
go_cairo_convert_data_to_pixbuf (unsigned char *dst, unsigned char const
*src,
int width, int height, int rowstride)
{
int i,j;
unsigned int t;
unsigned char a, b, c;
g_return_if_fail (dst != NULL);
#define MULT(d,c,a,t) G_STMT_START { t = (a)? c * 255 / a: 0; d = t;}
G_STMT_END
if (src == dst || src == NULL) {
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
MULT(a, dst[2], dst[3], t);
MULT(b, dst[1], dst[3], t);
MULT(c, dst[0], dst[3], t);
dst[0] = a;
dst[1] = b;
dst[2] = c;
#else
MULT(a, dst[1], dst[0], t);
MULT(b, dst[2], dst[0], t);
MULT(c, dst[3], dst[0], t);
dst[3] = dst[0];
dst[0] = a;
dst[1] = b;
dst[2] = c;
#endif
dst += 4;
}
dst += rowstride - width * 4;
}
} else {
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
MULT(dst[0], src[2], src[3], t);
MULT(dst[1], src[1], src[3], t);
MULT(dst[2], src[0], src[3], t);
dst[3] = src[3];
#else
MULT(dst[0], src[1], src[0], t);
MULT(dst[1], src[2], src[0], t);
MULT(dst[2], src[3], src[0], t);
dst[3] = src[0];
#endif
src += 4;
dst += 4;
}
src += rowstride - width * 4;
dst += rowstride - width * 4;
}
}
#undef MULT
}
Regards,
Jean
Le dimanche 22 février 2009 à 16:24 +0200, Dov Grobgeld a écrit :
> You can also create a cairo surface of the pixbuf through
> cairo_image_surface_create_for_data() like this:
> int img_width = gdk_pixbuf_get_width(pixbuf);
>
> int img_height = gdk_pixbuf_get_height(pixbuf);
>
>
> cairo_surface_t *surface
> = cairo_image_surface_create_for_data(gdk_pixbuf_get_pixels(pixbuf),
>
> CAIRO_FORMAT_RGB24,
> img_width,
> img_height,
>
> gdk_pixbuf_get_rowstride(pixbuf));
>
> but beware that you will need to swap R and B when drawing. See the
> cairo-circles.c example at:
>
> http://giv.sourceforge.net/gtk-image-viewer/gtkimageviewer_tutorial.html
>
> Regards,
> Dov
>
> 2009/2/22 Tadej Borovšak <tadeboro gmail com>
> Hi.
>
> I missed list the first time (sorry Roei for spamming you).
>
>
> ---------- Forwarded message ----------
> From: Tadej Borovšak <tadeboro gmail com>
> Date: 2009/2/22
> Subject: Re: cairo_surface_t to pixbuf
> To: Roei Azachi <roei zon-networks com>
>
>
> 2009/2/22 Roei Azachi <roei zon-networks com>:
> > Hi,
> > I was wondering if there is a way of converting
> cairo_surface_t to pixbuf
> > currently I am doing:
> > cairo_surface_write_to_png(oimg2, "tmp.png");
> > pixbuf = gdk_pixbuf_new_from_file("tmp.png", &g_err);
> > I'm sure there is a way, but I don't know how...
> > Thanks,
> > Roei
> > _______________________________________________
> > gtk-list mailing list
> > gtk-list gnome org
> > http://mail.gnome.org/mailman/listinfo/gtk-list
> >
>
>
> Hi.
>
> I only converted cairo's image surfaces to PPM images. I did
> this by
> obtaining surface's width, height, rowstride and format, then
> manually
> copied pixel values from surface to PPM.
>
> Simple function for converting surface to pixbuf would look
> something like this:
>
> ------- CODE --------
> GdkPixbuf *
> convert( cairo_surface_t *surface )
> {
> GdkPixbuf *pixbuf;
> gint width = cairo_image_surface_get_width( surface );
> gint height = cairo_image_surface_get_height( surface );
> gint stride = cairo_image_surface_get_stride( surface );
> cairo_format_t format =
> cairo_image_surface_get_format( surface );
> guchar *data = cairo_image_surface_get_data( surface );
> gint row, col;
>
> if( format == CAIRO_FORMAT_ARGB32 )
> {
> guchar *pixels;
> gint pix_stride;
>
> /* Temporary pointers for iterating. */
> guchar *p_dat, *p_pix;
>
> pixbuf = gdk_pixbuf_new( GDK_COLORSPACE_RGB,
> TRUE, 8,
> width, height );
> pixels = gdk_pixbuf_get_pixels( pixbuf );
> pix_stride = gdk_pixbuf_get_rowstride( pixbuf );
>
> p_dat = data;
> p_pix = pixels;
>
> for( row = 0; row < height; row++ )
> {
> p_pix = pixels + row * pix_stride;
> p_dat = data + row * stride;
>
> for( col = 0; col < width; col++ )
> {
> /* Copy now. Cairo image
> surfaces use
> pre-multiplied
> * alpha, this is why we need to
> calculate RGB values. */
> p_pix[0] = p_dat[1] / p_dat[0] *
> 0xff;
> p_pix[1] = p_dat[2] / p_dat[0] *
> 0xff;
> p_pix[2] = p_dat[3] / p_dat[0] *
> 0xff;
> p_pix[3] = p_dat[0];
>
> p_pix += 4;
> p_dat += 4;
> }
> }
> }
> else if( format == CAIRO_FORMAT_RGB24 )
> {
> guchar *pixels;
> gint pix_stride;
>
> /* Temporary pointers for iterating. */
> guchar *p_dat, *p_pix;
>
> pixbuf = gdk_pixbuf_new( GDK_COLORSPACE_RGB,
> FALSE, 8,
> width, height );
> pixels = gdk_pixbuf_get_pixels( pixbuf );
> pix_stride = gdk_pixbuf_get_rowstride( pixbuf );
>
> p_dat = data;
> p_pix = pixels;
>
> for( row = 0; row < height; row++ )
> {
> p_pix = pixels + row * pix_stride;
> p_dat = data + row * stride;
>
> for( col = 0; col < width; col++ )
> {
> p_pix[0] = p_dat[0];
> p_pix[1] = p_dat[1];
> p_pix[2] = p_dat[2];
>
> p_pix += 3;
> p_dat += 4;
> }
> }
> }
>
> return( pixbuf );
> }
> -------- CODE ---------
>
> Note though that I haven't tested this function, so test it
> before
> using in real application.
>
> --
> Tadej Borovšak
> tadeboro gmail com
> tadej borovsak gmail com
>
>
>
> --
> Tadej Borovšak
> tadeboro gmail com
> tadej borovsak gmail com
>
> _______________________________________________
> gtk-list mailing list
> gtk-list gnome org
> http://mail.gnome.org/mailman/listinfo/gtk-list
>
>
>
> _______________________________________________
> gtk-list mailing list
> gtk-list gnome org
> http://mail.gnome.org/mailman/listinfo/gtk-list
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]