Re: cairo_surface_t to pixbuf



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]