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 <[email protected]>
>         Hi.
>         
>         I missed list the first time (sorry Roei for spamming you).
>         
>         
>         ---------- Forwarded message ----------
>         From: Tadej Borovšak <[email protected]>
>         Date: 2009/2/22
>         Subject: Re: cairo_surface_t to pixbuf
>         To: Roei Azachi <[email protected]>
>         
>         
>         2009/2/22 Roei Azachi <[email protected]>:
>         > 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
>         > [email protected]
>         > 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
>         [email protected]
>         [email protected]
>         
>         
>         
>         --
>         Tadej Borovšak
>         [email protected]
>         [email protected]
>         
>         _______________________________________________
>         gtk-list mailing list
>         [email protected]
>         http://mail.gnome.org/mailman/listinfo/gtk-list
>         
> 
> 
> _______________________________________________
> gtk-list mailing list
> [email protected]
> http://mail.gnome.org/mailman/listinfo/gtk-list

_______________________________________________
gtk-list mailing list
[email protected]
http://mail.gnome.org/mailman/listinfo/gtk-list

Reply via email to