GTK+ Forums Forum Index GTK+ Forums
Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

how can I change a GdkDrawable in an image? [SOLVED]

 
Post new topic   Reply to topic    GTK+ Forums Forum Index -> GTK+ Programming
Author Message
satyria
Familiar Face


Joined: 25 Feb 2008
Posts: 18

PostPosted: Tue Sep 02, 2008 1:49 pm    Post subject: how can I change a GdkDrawable in an image? [SOLVED] Reply with quote

Hello,

how can I change a GdkDrawable in an image?

First of all I do with my GLADE surface (DrawinArea). I draw with gdk_draw_line (). I would like this picture in an image and then save. How can I do?

satyria


Last edited by satyria on Thu Sep 11, 2008 5:14 am; edited 1 time in total
Back to top
dreblen
Never Seen the Sunlight


Joined: 14 Jun 2007
Posts: 568
Location: Falun, WI USA

PostPosted: Tue Sep 02, 2008 4:25 pm    Post subject: Reply with quote

you can use gdk_pixbuf_get_from_drawable
http://library.gnome.org/devel/gdk/stable/gdk-Pixbufs.html#gdk-pixbuf-get-from-drawable
and gdk_pixbuf_save
http://library.gnome.org/devel/gdk-pixbuf/unstable/gdk-pixbuf-file-saving.html#gdk-pixbuf-save
to save a pixbuf from a GdkDrawable.
Code: (C)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <gtk/gtk.h>

#define    FILENAME    "test_png.png"

gboolean expose_cb(GtkWidget *da, GdkEventExpose *ev, gpointer user_data)
{
    cairo_t *cr;
    gint x, y;
    gint w, h;

    /* get our dimensions */
   
x = da->allocation.x;
    y = da->allocation.y;
    w = da->allocation.width;
    h = da->allocation.height;

    /* create a cairo context */
   
cr = gdk_cairo_create(da->window);

    /* draw an X across the drawing area */
   
cairo_move_to(cr, x, y);
    cairo_line_to(cr, w, h);
    cairo_move_to(cr, w, y);
    cairo_line_to(cr, x, h);
    cairo_stroke(cr);

    /* free the context */
   
cairo_destroy(cr);

    return TRUE;
}

void save_drawable_cb(GtkWidget *button, GtkWidget *da)
{
    GdkPixbuf *pbuf;
    gint w, h;
    GError *err;

    err = NULL;

    /* get the width and height for the image */
   
w = da->allocation.width;
    h = da->allocation.height;

    /* create a new pixbuf from the drawing area */
   
pbuf = gdk_pixbuf_get_from_drawable(NULL, da->window, NULL, 0, 0, 0, 0, w, h);
    if(pbuf == NULL)
    {
        g_warning("Couldn't create pixbuf!");
        return;
    }

    /* WARNING: This will overwrite any file named FILENAME */
   
gdk_pixbuf_save(pbuf, FILENAME, "png", &err, NULL);
    if(err != NULL)
    {
        g_warning(err->message);
        g_error_free(err);
        return;
    }
}

int main(int argc, char **argv)
{
    GtkWidget *win;
    GtkWidget *vbox;
    GtkWidget *da;
    GtkWidget *button;

    gtk_init(&argc, &argv);

    win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect(G_OBJECT(win), "delete-event", G_CALLBACK(gtk_main_quit), NULL);
    gtk_container_set_border_width(GTK_CONTAINER(win), 2);

    vbox = gtk_vbox_new(FALSE, 2);
    gtk_container_add(GTK_CONTAINER(win), vbox);
    gtk_widget_show(vbox);

    da = gtk_drawing_area_new();
    g_signal_connect(G_OBJECT(da), "expose-event", G_CALLBACK(expose_cb), NULL);
    gtk_widget_set_size_request(da, 100, 100);
    gtk_box_pack_start(GTK_BOX(vbox), da, TRUE, TRUE, 0);
    gtk_widget_show(da);

    button = gtk_button_new_with_label("Save drawable");
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(save_drawable_cb), (gpointer)da);
    gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
    gtk_widget_show(button);

    gtk_widget_show(win);

    gtk_main();

    return 0;
}
Back to top
satyria
Familiar Face


Joined: 25 Feb 2008
Posts: 18

PostPosted: Thu Sep 04, 2008 1:19 pm    Post subject: Reply with quote

Thank you very much!

Now have I a new problem with that.

I have taken over your example with a FileChooserDialog.

When I save the picture is still the dialog box in the image.

My source code:

Code: (C)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

  GtkWidget *dialog;
  GdkPixbuf *pixbuf;
  gint w,h;
  GError *err;
  char *filename;
  GdkRectangle update_rect;

 
  dialog = gtk_file_chooser_dialog_new ("Save File", NULL, GTK_FILE_CHOOSER_ACTION_SAVE,
                                        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                        GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
                                        NULL);
gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);

if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
  {
    filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
    gtk_widget_destroy (dialog);
   
    update_rect.x = 0;
    update_rect.y = 0;
    update_rect.width = win_x;
    update_rect.height = win_y;

    gdk_window_invalidate_rect (draw->window,&update_rect,FALSE);

    err=NULL;
    w = draw->allocation.width;
    h = draw->allocation.height;

    pixbuf = gdk_pixbuf_get_from_drawable(NULL, draw->window, NULL, 0, 0, 0, 0, w, h);
    if(pixbuf == NULL)
    {
      g_warning("Couldn't create pixbuf!");
      return;
    }

    gdk_pixbuf_save(pixbuf, filename, "png", &err, NULL);
    if(err != NULL)
    {
        g_warning(err->message);
        g_error_free(err);
        return;
    }
  }
  else
 
{
   gtk_widget_destroy (dialog);
   filename="";
  }

  g_free (filename);


HELP!!!
Back to top
dreblen
Never Seen the Sunlight


Joined: 14 Jun 2007
Posts: 568
Location: Falun, WI USA

PostPosted: Thu Sep 04, 2008 1:52 pm    Post subject: Reply with quote

I don't have that problem I guess, but maybe the changes I've made will fix it.
if they don't, then it might help to un-comment the gtk_events_pending lines.
EDIT: with the release of GTK+ 2.14 today, there's a new function, gtk_widget_get_snapshot
http://library.gnome.org/devel/gtk/stable/GtkWidget.html#gtk-widget-get-snapshot
it returns a GdkPixmap which can be used by gdk_pixbuf_get_from_drawable.
This function may be of help if you are still having problems since it says it works even if the widget is obscured.
Even if you don't want to use gtk 2.14 yet, you can still look at the source code for it and maybe implement your own
http://svn.gnome.org/viewvc/gtk%2B/tags/GTK_2_14_0/gtk/gtkwidget.c?revision=21291&view=markup

Code: (C)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <gtk/gtk.h>

gboolean expose_cb(GtkWidget *da, GdkEventExpose *ev, gpointer user_data)
{
    cairo_t *cr;
    gint x, y;
    gint w, h;

    /* get our dimensions */
   
x = da->allocation.x;
    y = da->allocation.y;
    w = da->allocation.width;
    h = da->allocation.height;

    /* create a cairo context */
   
cr = gdk_cairo_create(da->window);

    /* draw an X across the drawing area */
   
cairo_move_to(cr, x, y);
    cairo_line_to(cr, w, h);
    cairo_move_to(cr, w, y);
    cairo_line_to(cr, x, h);
    cairo_stroke(cr);

    /* free the context */
   
cairo_destroy(cr);

    return TRUE;
}

void save_drawable_cb(GtkWidget *button, GtkWidget *da)
{
    GtkWidget *dialog;
    GdkPixbuf *pixbuf;
    gint w,h;
    GError *err;
    /* made filename a gchar instead of char */
   
gchar *filename;
    /* I got rid of update_rect */

   
dialog = gtk_file_chooser_dialog_new ("Save File", NULL, GTK_FILE_CHOOSER_ACTION_SAVE,
                                                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                                            GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
                                                            NULL);
    gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);

    if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
    {
        filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
        gtk_widget_destroy (dialog);

        /* if you pass NULL as the rectangle arg, it will invalidate the entire window */
       
gdk_window_invalidate_rect (da->window, NULL, FALSE);
        /* if you still have a problem, try this */
        //while(gtk_events_pending())
        //    gtk_main_iteration();

       
err = NULL;
        w = da->allocation.width;
        h = da->allocation.height;

        pixbuf = gdk_pixbuf_get_from_drawable(NULL, da->window, NULL, 0, 0, 0, 0, w, h);
        if(pixbuf == NULL)
        {
            g_warning("Couldn't create pixbuf!");
            return;
        }

        gdk_pixbuf_save(pixbuf, filename, "png", &err, NULL);
        if(err != NULL)
        {
            g_warning(err->message);
            g_error_free(err);
            return;
        }
    }
    else
   
{
        gtk_widget_destroy (dialog);
        filename="";
    }

    g_free (filename);
}

int main(int argc, char **argv)
{
    GtkWidget *win;
    GtkWidget *vbox;
    GtkWidget *da;
    GtkWidget *button;

    gtk_init(&argc, &argv);

    win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect(G_OBJECT(win), "delete-event", G_CALLBACK(gtk_main_quit), NULL);
    gtk_container_set_border_width(GTK_CONTAINER(win), 2);

    vbox = gtk_vbox_new(FALSE, 2);
    gtk_container_add(GTK_CONTAINER(win), vbox);
    gtk_widget_show(vbox);

    da = gtk_drawing_area_new();
    g_signal_connect(G_OBJECT(da), "expose-event", G_CALLBACK(expose_cb), NULL);
    gtk_widget_set_size_request(da, 100, 100);
    gtk_box_pack_start(GTK_BOX(vbox), da, TRUE, TRUE, 0);
    gtk_widget_show(da);

    button = gtk_button_new_with_label("Save drawable");
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(save_drawable_cb), (gpointer)da);
    gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
    gtk_widget_show(button);

    gtk_widget_show(win);

    gtk_main();

    return 0;
}
Back to top
satyria
Familiar Face


Joined: 25 Feb 2008
Posts: 18

PostPosted: Fri Sep 05, 2008 11:59 am    Post subject: Reply with quote

I've tried your version. I have attached the result. It is the same error, as in my trials. One idea, as I fix it?



Satyria

PS.:
I use version
gtk_binary_version 2.10.0
and
GIMP Tool Kit version 2.12.8

I will even try the new version. Let's see what emerges.

Greeting Satyria
Back to top
satyria
Familiar Face


Joined: 25 Feb 2008
Posts: 18

PostPosted: Mon Sep 08, 2008 7:43 am    Post subject: Reply with quote

Hello,

I've now updated my system (GTK + 2.14.1 and other tools). The error has remained!

Is there a function that is waiting for the dialogue really was?

Greeting Satyria
Back to top
dreblen
Never Seen the Sunlight


Joined: 14 Jun 2007
Posts: 568
Location: Falun, WI USA

PostPosted: Mon Sep 08, 2008 1:38 pm    Post subject: Reply with quote

can you post your code that is failing?
if it's too big can you make a minimal example that does the same thing?
thanks...
Back to top
satyria
Familiar Face


Joined: 25 Feb 2008
Posts: 18

PostPosted: Tue Sep 09, 2008 5:13 am    Post subject: Reply with quote

Hello, it is your code, see above example!

Incidentally, I use GTK + under Windows XP (MinGW and MSYS). Is it possibly a bug?

Greetings, Satyria
Back to top
satyria
Familiar Face


Joined: 25 Feb 2008
Posts: 18

PostPosted: Tue Sep 09, 2008 6:07 am    Post subject: Reply with quote

I have now rewritten the Save function. I get firstly the pixbuf and after the file name. The program is working. I think this solution is not elegant, first because I really want to have the name, which also ended with an abort could be. Another idea?

The functioning of gtk_widget_get-snapshot () I do not understand, so I let it be.

Greeting Satyria

excuse me! english is not my native language.
Back to top
dreblen
Never Seen the Sunlight


Joined: 14 Jun 2007
Posts: 568
Location: Falun, WI USA

PostPosted: Tue Sep 09, 2008 2:51 pm    Post subject: Reply with quote

so you got it to work? if so, can you post your working code?
thanks...
Back to top
satyria
Familiar Face


Joined: 25 Feb 2008
Posts: 18

PostPosted: Wed Sep 10, 2008 6:32 am    Post subject: Reply with quote

Hello,

the Code for the Save-function:
Code: (C)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
{
  GtkWidget *dialog;
  GdkPixbuf *pixbuf;
  gint w,h;
  GError *err;
  gchar *filename;

  w = draw->allocation.width;
  h = draw->allocation.height;
  pixbuf = gdk_pixbuf_get_from_drawable(NULL, draw->window, NULL, 0, 0, 0, 0, w, h);
 
  dialog = gtk_file_chooser_dialog_new ("Save File", NULL, GTK_FILE_CHOOSER_ACTION_SAVE,
                                        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                        GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
                                        NULL);
    gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);

    if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
    {
        filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
        gtk_widget_destroy (dialog);

        err=NULL;
        if(pixbuf == NULL)
        {
            g_warning("Couldn't create pixbuf!");
            return;
        }

        gdk_pixbuf_save(pixbuf, filename, "png", &err, NULL);
        if(err != NULL)
        {
            g_warning(err->message);
            g_error_free(err);
            return;
        }
    }
  else
 
{
   gtk_widget_destroy (dialog);
   filename="";
  }
  g_free (filename);
}


draw is the drawable Widget.

This Function unnecessary memory, if you do not save. But at least it will work.

I've yet to a question. Is there any way to the file type (jpeg, tiff, etc.) in dialog box to change accordingly and then it?

Greeting Satyria
Back to top
dreblen
Never Seen the Sunlight


Joined: 14 Jun 2007
Posts: 568
Location: Falun, WI USA

PostPosted: Wed Sep 10, 2008 3:18 pm    Post subject: Reply with quote

here's another version of my example that determines the file format from the filename.
you'll probably have to adjust it again to make it work, but the main thing to look at is the get_extension function:
Code: (C)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#include <gtk/gtk.h>
#include <string.h>

gboolean expose_cb(GtkWidget *da, GdkEventExpose *ev, gpointer user_data)
{
    cairo_t *cr;
    gint x, y;
    gint w, h;

    /* get our dimensions */
   
x = da->allocation.x;
    y = da->allocation.y;
    w = da->allocation.width;
    h = da->allocation.height;

    /* create a cairo context */
   
cr = gdk_cairo_create(da->window);

    /* draw an X across the drawing area */
   
cairo_move_to(cr, x, y);
    cairo_line_to(cr, w, h);
    cairo_move_to(cr, w, y);
    cairo_line_to(cr, x, h);
    cairo_stroke(cr);

    /* free the context */
   
cairo_destroy(cr);

    return TRUE;
}

gchar *get_extension(const gchar *filename)
{
    gchar *ext;
    gchar *dot;
    GSList *formats;
    gint i, j;
    gboolean okay_format;

    /* get the last dot in the filename */
   
dot = g_strrstr(filename, ".");
    /* if there is no dot, default to png */
   
if(dot == NULL)
        return "png";

    /* start at the char after the dot */
   
i = (dot - filename) + 1;
    /* allocate ext */
   
ext = (gchar*)g_malloc((strlen(filename) - i) + sizeof(gchar));
    if(ext == NULL)
    {
        g_warning("No memory!");
        return "png";
    }

    /* fill in ext with the extension */
   
for(j = 0; i < strlen(filename); i++)
        ext[j++] = filename[i];
    ext[j] = '\0';

    /* get the supported GdkPixbufFormat's */
   
formats = gdk_pixbuf_get_formats();
    for(okay_format = FALSE; formats != NULL; formats = g_slist_next(formats))
    {
        /* if it matches a valid format, then test the format */
       
if(!strcmp(gdk_pixbuf_format_get_name((GdkPixbufFormat*)formats->data), ext))
        {
            /* if the format is writable, then it's fine and we're done */
           
if(gdk_pixbuf_format_is_writable((GdkPixbufFormat*)formats->data))
            {
                okay_format = TRUE;
                break;
            }
        }
    }

    /* if it wasn't a valid format for writing, then return png */
   
if(okay_format == FALSE)
        return "png";

    /* return the saving extension */
   
return ext;
}

void save_drawable_cb(GtkWidget *button, GtkWidget *da)
{
    GtkWidget *dialog;
    GdkPixbuf *pixbuf;
    gint w,h;
    GError *err;
    gchar *filename;

    dialog = gtk_file_chooser_dialog_new ("Save File", NULL, GTK_FILE_CHOOSER_ACTION_SAVE,
                                                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
                                                            GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
                                                            NULL);
    gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);

    if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
    {
        filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
        gtk_widget_destroy (dialog);

        gdk_window_invalidate_rect (da->window, NULL, FALSE);

        err = NULL;
        w = da->allocation.width;
        h = da->allocation.height;

        pixbuf = gdk_pixbuf_get_from_drawable(NULL, da->window, NULL, 0, 0, 0, 0, w, h);
        if(pixbuf == NULL)
        {
            g_warning("Couldn't create pixbuf!");
            return;
        }

        gdk_pixbuf_save(pixbuf, filename, get_extension(filename), &err, NULL);
        if(err != NULL)
        {
            g_warning(err->message);
            g_error_free(err);
            return;
        }
    }
    else
   
{
        gtk_widget_destroy (dialog);
        filename="";
    }

    g_free(filename);
}

int main(int argc, char **argv)
{
    GtkWidget *win;
    GtkWidget *vbox;
    GtkWidget *da;
    GtkWidget *button;

    gtk_init(&argc, &argv);

    win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect(G_OBJECT(win), "delete-event", G_CALLBACK(gtk_main_quit), NULL);
    gtk_container_set_border_width(GTK_CONTAINER(win), 2);

    vbox = gtk_vbox_new(FALSE, 2);
    gtk_container_add(GTK_CONTAINER(win), vbox);
    gtk_widget_show(vbox);

    da = gtk_drawing_area_new();
    g_signal_connect(G_OBJECT(da), "expose-event", G_CALLBACK(expose_cb), NULL);
    gtk_widget_set_size_request(da, 100, 100);
    gtk_box_pack_start(GTK_BOX(vbox), da, TRUE, TRUE, 0);
    gtk_widget_show(da);

    button = gtk_button_new_with_label("Save drawable");
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(save_drawable_cb), (gpointer)da);
    gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
    gtk_widget_show(button);

    gtk_widget_show(win);

    gtk_main();

    return 0;
}
Back to top
satyria
Familiar Face


Joined: 25 Feb 2008
Posts: 18

PostPosted: Thu Sep 11, 2008 5:09 am    Post subject: Reply with quote

So there is no specific function of GTK. In any case I was already learned. The function gdk_pixbuf_get_formats () knew I did not!

Thank you!

Greeting Satyria
Back to top
Display posts from previous:   
Post new topic   Reply to topic    GTK+ Forums Forum Index -> GTK+ Programming All times are GMT
Page 1 of 1

 


Powered by phpBB © 2001, 2005 phpBB Group
CodeBB 1.0 Beta 2
Protected by Anti-Spam ACP