Как мне создать GtkImage с поверхности Каира? - PullRequest
3 голосов
/ 16 апреля 2011

Я хочу иметь возможность создать GtkImage из Каирской поверхности (без записи временного файла).

В настоящее время я записываю поверхность в виде PNG в массив символов, который я затем передаю в PixbufLoader, чтобы получитьPixbuf, который я использую для создания GtkImage:

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);
  1. Это кажется довольно громоздким - нет ли более простого способа сделать это?
  2. Как бы я определить размермассива в моем примере?

Ответы [ 2 ]

1 голос
/ 10 июля 2011

Одна функция сэкономит вам много усилий здесь. Посмотрите на gdk_pixbuf_get_from_surface. Он получает Pixbuf от cairo_surface_t. Грубый, понимая, как он это пишет, это доступно только если вы используете 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;
}
0 голосов
/ 29 августа 2018

Просто подсказка, я не уверен, как определить размер массива, но я уверен, как долго должен быть размер массива, поскольку ваш обратный вызов 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...