 |
GTK+ Forums Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
|
|
|
| Author |
Message |
|
|
satyria Familiar Face
Joined: 25 Feb 2008 Posts: 18
|
Posted: Tue Sep 02, 2008 1:49 pm Post subject: how can I change a GdkDrawable in an image? [SOLVED] |
|
|
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: 526 Location: Falun, WI USA
|
Posted: Tue Sep 02, 2008 4:25 pm Post subject: |
|
|
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
|
Posted: Thu Sep 04, 2008 1:19 pm Post subject: |
|
|
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: 526 Location: Falun, WI USA
|
Posted: Thu Sep 04, 2008 1:52 pm Post subject: |
|
|
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
|
Posted: Fri Sep 05, 2008 11:59 am Post subject: |
|
|
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
|
Posted: Mon Sep 08, 2008 7:43 am Post subject: |
|
|
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: 526 Location: Falun, WI USA
|
Posted: Mon Sep 08, 2008 1:38 pm Post subject: |
|
|
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
|
Posted: Tue Sep 09, 2008 5:13 am Post subject: |
|
|
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
|
Posted: Tue Sep 09, 2008 6:07 am Post subject: |
|
|
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: 526 Location: Falun, WI USA
|
Posted: Tue Sep 09, 2008 2:51 pm Post subject: |
|
|
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
|
Posted: Wed Sep 10, 2008 6:32 am Post subject: |
|
|
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: 526 Location: Falun, WI USA
|
Posted: Wed Sep 10, 2008 3:18 pm Post subject: |
|
|
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
|
Posted: Thu Sep 11, 2008 5:09 am Post subject: |
|
|
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 |
|
 |
|
Powered by phpBB © 2001, 2005 phpBB Group CodeBB 1.0 Beta 2
|