我希望能够从开罗表面制作GtkImage(无需编写临时文件)。
我目前将表面作为PNG写入一个char数组,然后我将其提供给PixbufLoader以获取我用来创建GtkImage的Pixbuf:
typedef struct
{
unsigned char *pos;
unsigned char *end;
} closure_t;
static cairo_status_t
png_to_array (void *closure, const unsigned char *data, unsigned int length)
{
closure_t *cl = (closure_t *) closure;
if ((cl->pos + length) > (cl->end))
return CAIRO_STATUS_WRITE_ERROR;
memcpy (cl->pos, data, length);
cl->pos += length;
return CAIRO_STATUS_SUCCESS;
}
// later in the code
cairo_surface_t *surface = ...
...
// how would i determine the right size?
unsigned char arr[...];
closure_t cl;
GtkWidget *image;
GdkPixbufLoader *pbloader;
GdkPixbuf *pb;
// copy surface png to arr
cl.pos = arr;
cl.end = arr + sizeof(arr);
cairo_surface_write_to_png_stream (surface,
(cairo_write_func_t) png_to_array,
&cl);
...
// write to pixbufloader, get pixbuf, create image
pbloader = gdk_pixbuf_loader_new();
gdk_pixbuf_loader_write(pbloader, arr, sizeof(arr), NULL);
gdk_pixbuf_loader_close(pbloader, NULL);
pb = gdk_pixbuf_loader_get_pixbuf(pbloader);
image = gtk_image_new_from_pixbuf(pb);
答案 0 :(得分:1)
一个功能可以为您节省大量精力。查找gdk_pixbuf_get_from_surface。它从cairo_surface_t获取一个Pixbuf。粗略的,在他写的时候意识到,只有你使用Gdk-3.0,这也意味着使用Gtk + -3.0。
粗略如果你想使用Gtk + -2.0那么你可以创建一个像素图,从中获取一个cairo_t然后通过
将你的另一个cairo_surface_t复制到它cairo_set_source_surface (cr, surface, x0, y0);
cairo_rectangle (cr, x0 + x, y0 + y, width, height);
cairo_fill (cr);
下面是一个如何创建像素图的示例,我将让您填写其余部分。
#include <gtk/gtk.h>
#include <cairo/cairo.h>
int main(gint argc, gchar *argv[])
{
GdkPixmap *pixmap;
GtkWidget *image;
GtkWidget *window;
cairo_t *cr;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(G_OBJECT(window), "delete-event", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all(window);
pixmap = gdk_pixmap_new(window->window, 100, 100, -1);
cr = gdk_cairo_create(pixmap);
cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
cairo_rectangle(cr, 10, 10, 80, 80);
cairo_fill(cr);
cairo_destroy(cr);
cr = NULL;
image = gtk_image_new_from_pixmap(pixmap, NULL);
gtk_container_add(GTK_CONTAINER(window), image);
gtk_widget_show(image);
gtk_main();
return 0;
}
答案 1 :(得分:0)
只是一个提示,我不确定如何确定数组的大小,但是我确定数组的大小应该多长时间,因为您的png_to_array回调将被调用为数组大小的几倍。是所有长度的总和
我正在使用跨步来确定数组的大小,但最后,total_lenght将确定png的大小
int total_lenght = 0;
typedef struct
{
unsigned char *pos;
unsigned char *end;
} closure_t;
static cairo_status_t
png_to_array (void *closure, const unsigned char *data, unsigned int length)
{
closure_t *cl = (closure_t *) closure;
if ((cl->pos + length) > (cl->end))
return CAIRO_STATUS_WRITE_ERROR;
memcpy (cl->pos, data, length);
cl->pos += length;
total_lenght += lenght;
return CAIRO_STATUS_SUCCESS;
}
// later in the code
cairo_surface_t *surface = ...
...
int stride = cairo_image_surface_get_stride(surface);
unsigned char *arr = (unsigned char *) malloc(stride);
closure_t cl;
GtkWidget *image;
GdkPixbufLoader *pbloader;
GdkPixbuf *pb;
// copy surface png to arr
cl.pos = arr;
cl.end = arr + stride;
cairo_surface_write_to_png_stream (surface,
(cairo_write_func_t) png_to_array,
&cl);
...
// write to pixbufloader, get pixbuf, create image
pbloader = gdk_pixbuf_loader_new();
gdk_pixbuf_loader_write(pbloader, arr, total_lenght), NULL);
gdk_pixbuf_loader_close(pbloader, NULL);
pb = gdk_pixbuf_loader_get_pixbuf(pbloader);
image = gtk_image_new_from_pixbuf(pb);