mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-18 17:30:10 +00:00
872ef111ec
The ownership of the return value for gdk_pixbuf_get_from_window() and gdk_pixbuf_get_from_surface() was determined by the first argument. Because that is an ugly design and the functions are new to GTK3, we decided to adapt them. And that adaptation was quite easy since almost no one passses anything but NULL as the first argument.
390 lines
14 KiB
C
390 lines
14 KiB
C
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
|
|
|
|
#include "config.h"
|
|
#include <stdio.h>
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
static void
|
|
compare_pixbufs (GdkPixbuf *pixbuf, GdkPixbuf *compare, const gchar *file_type)
|
|
{
|
|
if ((gdk_pixbuf_get_width (pixbuf) !=
|
|
gdk_pixbuf_get_width (compare)) ||
|
|
(gdk_pixbuf_get_height (pixbuf) !=
|
|
gdk_pixbuf_get_height (compare)) ||
|
|
(gdk_pixbuf_get_n_channels (pixbuf) !=
|
|
gdk_pixbuf_get_n_channels (compare)) ||
|
|
(gdk_pixbuf_get_has_alpha (pixbuf) !=
|
|
gdk_pixbuf_get_has_alpha (compare)) ||
|
|
(gdk_pixbuf_get_bits_per_sample (pixbuf) !=
|
|
gdk_pixbuf_get_bits_per_sample (compare))) {
|
|
fprintf (stderr,
|
|
"saved %s file differs from copy in memory\n",
|
|
file_type);
|
|
} else {
|
|
guchar *orig_pixels;
|
|
guchar *compare_pixels;
|
|
gint orig_rowstride;
|
|
gint compare_rowstride;
|
|
gint width;
|
|
gint height;
|
|
gint bytes_per_pixel;
|
|
gint x, y;
|
|
guchar *p1, *p2;
|
|
gint count = 0;
|
|
|
|
orig_pixels = gdk_pixbuf_get_pixels (pixbuf);
|
|
compare_pixels = gdk_pixbuf_get_pixels (compare);
|
|
|
|
orig_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
|
|
compare_rowstride = gdk_pixbuf_get_rowstride (compare);
|
|
|
|
width = gdk_pixbuf_get_width (pixbuf);
|
|
height = gdk_pixbuf_get_height (pixbuf);
|
|
|
|
/* well... */
|
|
bytes_per_pixel = gdk_pixbuf_get_n_channels (pixbuf);
|
|
|
|
p1 = orig_pixels;
|
|
p2 = compare_pixels;
|
|
|
|
for (y = 0; y < height; y++) {
|
|
for (x = 0; x < width * bytes_per_pixel; x++)
|
|
count += (*p1++ != *p2++);
|
|
|
|
orig_pixels += orig_rowstride;
|
|
compare_pixels += compare_rowstride;
|
|
|
|
p1 = orig_pixels;
|
|
p2 = compare_pixels;
|
|
}
|
|
|
|
if (count > 0) {
|
|
fprintf (stderr,
|
|
"saved %s file differs from copy in memory\n",
|
|
file_type);
|
|
}
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
save_to_loader (const gchar *buf, gsize count, GError **err, gpointer data)
|
|
{
|
|
GdkPixbufLoader *loader = data;
|
|
|
|
return gdk_pixbuf_loader_write (loader, (const guchar *)buf, count, err);
|
|
}
|
|
|
|
static GdkPixbuf *
|
|
buffer_to_pixbuf (const gchar *buf, gsize count, GError **err)
|
|
{
|
|
GdkPixbufLoader *loader;
|
|
GdkPixbuf *pixbuf;
|
|
|
|
loader = gdk_pixbuf_loader_new ();
|
|
if (gdk_pixbuf_loader_write (loader, (const guchar *)buf, count, err) &&
|
|
gdk_pixbuf_loader_close (loader, err)) {
|
|
pixbuf = g_object_ref (gdk_pixbuf_loader_get_pixbuf (loader));
|
|
g_object_unref (loader);
|
|
return pixbuf;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static void
|
|
do_compare (GdkPixbuf *pixbuf, GdkPixbuf *compare, GError *err)
|
|
{
|
|
if (compare == NULL) {
|
|
fprintf (stderr, "%s", err->message);
|
|
g_error_free (err);
|
|
} else {
|
|
compare_pixbufs (pixbuf, compare, "jpeg");
|
|
g_object_unref (compare);
|
|
}
|
|
}
|
|
|
|
static void
|
|
keypress_check (GtkWidget *widget, GdkEventKey *evt, gpointer data)
|
|
{
|
|
GdkPixbuf *pixbuf;
|
|
GtkDrawingArea *da = (GtkDrawingArea*)data;
|
|
GError *err = NULL;
|
|
gchar *buffer;
|
|
gsize count;
|
|
GdkPixbufLoader *loader;
|
|
|
|
pixbuf = (GdkPixbuf *) g_object_get_data (G_OBJECT (da), "pixbuf");
|
|
|
|
if (evt->keyval == 'q')
|
|
gtk_main_quit ();
|
|
|
|
if (evt->keyval == 's' && (evt->state & GDK_CONTROL_MASK)) {
|
|
/* save to callback */
|
|
if (pixbuf == NULL) {
|
|
fprintf (stderr, "PIXBUF NULL\n");
|
|
return;
|
|
}
|
|
|
|
loader = gdk_pixbuf_loader_new ();
|
|
if (!gdk_pixbuf_save_to_callback (pixbuf, save_to_loader, loader, "jpeg",
|
|
&err,
|
|
"quality", "100",
|
|
NULL) ||
|
|
!gdk_pixbuf_loader_close (loader, &err)) {
|
|
fprintf (stderr, "%s", err->message);
|
|
g_error_free (err);
|
|
} else {
|
|
do_compare (pixbuf,
|
|
g_object_ref (gdk_pixbuf_loader_get_pixbuf (loader)),
|
|
err);
|
|
g_object_unref (loader);
|
|
}
|
|
}
|
|
else if (evt->keyval == 'S') {
|
|
/* save to buffer */
|
|
if (!gdk_pixbuf_save_to_buffer (pixbuf, &buffer, &count, "jpeg",
|
|
&err,
|
|
"quality", "100",
|
|
NULL)) {
|
|
fprintf (stderr, "%s", err->message);
|
|
g_error_free (err);
|
|
} else {
|
|
do_compare (pixbuf,
|
|
buffer_to_pixbuf (buffer, count, &err),
|
|
err);
|
|
}
|
|
}
|
|
else if (evt->keyval == 's') {
|
|
/* save normally */
|
|
if (pixbuf == NULL) {
|
|
fprintf (stderr, "PIXBUF NULL\n");
|
|
return;
|
|
}
|
|
|
|
if (!gdk_pixbuf_save (pixbuf, "foo.jpg", "jpeg",
|
|
&err,
|
|
"quality", "100",
|
|
NULL)) {
|
|
fprintf (stderr, "%s", err->message);
|
|
g_error_free (err);
|
|
} else {
|
|
do_compare (pixbuf,
|
|
gdk_pixbuf_new_from_file ("foo.jpg", &err),
|
|
err);
|
|
}
|
|
}
|
|
|
|
if (evt->keyval == 'p' && (evt->state & GDK_CONTROL_MASK)) {
|
|
/* save to callback */
|
|
if (pixbuf == NULL) {
|
|
fprintf (stderr, "PIXBUF NULL\n");
|
|
return;
|
|
}
|
|
|
|
loader = gdk_pixbuf_loader_new ();
|
|
if (!gdk_pixbuf_save_to_callback (pixbuf, save_to_loader, loader, "png",
|
|
&err,
|
|
"tEXt::Software", "testpixbuf-save",
|
|
NULL)
|
|
|| !gdk_pixbuf_loader_close (loader, &err)) {
|
|
fprintf (stderr, "%s", err->message);
|
|
g_error_free (err);
|
|
} else {
|
|
do_compare (pixbuf,
|
|
g_object_ref (gdk_pixbuf_loader_get_pixbuf (loader)),
|
|
err);
|
|
g_object_unref (loader);
|
|
}
|
|
}
|
|
else if (evt->keyval == 'P') {
|
|
/* save to buffer */
|
|
if (!gdk_pixbuf_save_to_buffer (pixbuf, &buffer, &count, "png",
|
|
&err,
|
|
"tEXt::Software", "testpixbuf-save",
|
|
NULL)) {
|
|
fprintf (stderr, "%s", err->message);
|
|
g_error_free (err);
|
|
} else {
|
|
do_compare (pixbuf,
|
|
buffer_to_pixbuf (buffer, count, &err),
|
|
err);
|
|
}
|
|
}
|
|
else if (evt->keyval == 'p') {
|
|
if (pixbuf == NULL) {
|
|
fprintf (stderr, "PIXBUF NULL\n");
|
|
return;
|
|
}
|
|
|
|
if (!gdk_pixbuf_save (pixbuf, "foo.png", "png",
|
|
&err,
|
|
"tEXt::Software", "testpixbuf-save",
|
|
NULL)) {
|
|
fprintf (stderr, "%s", err->message);
|
|
g_error_free (err);
|
|
} else {
|
|
do_compare(pixbuf,
|
|
gdk_pixbuf_new_from_file ("foo.png", &err),
|
|
err);
|
|
}
|
|
}
|
|
|
|
if (evt->keyval == 'i' && (evt->state & GDK_CONTROL_MASK)) {
|
|
/* save to callback */
|
|
if (pixbuf == NULL) {
|
|
fprintf (stderr, "PIXBUF NULL\n");
|
|
return;
|
|
}
|
|
|
|
loader = gdk_pixbuf_loader_new ();
|
|
if (!gdk_pixbuf_save_to_callback (pixbuf, save_to_loader, loader, "ico",
|
|
&err,
|
|
NULL)
|
|
|| !gdk_pixbuf_loader_close (loader, &err)) {
|
|
fprintf (stderr, "%s", err->message);
|
|
g_error_free (err);
|
|
} else {
|
|
do_compare (pixbuf,
|
|
g_object_ref (gdk_pixbuf_loader_get_pixbuf (loader)),
|
|
err);
|
|
g_object_unref (loader);
|
|
}
|
|
}
|
|
else if (evt->keyval == 'I') {
|
|
/* save to buffer */
|
|
if (!gdk_pixbuf_save_to_buffer (pixbuf, &buffer, &count, "ico",
|
|
&err,
|
|
NULL)) {
|
|
fprintf (stderr, "%s", err->message);
|
|
g_error_free (err);
|
|
} else {
|
|
do_compare (pixbuf,
|
|
buffer_to_pixbuf (buffer, count, &err),
|
|
err);
|
|
}
|
|
}
|
|
else if (evt->keyval == 'i') {
|
|
if (pixbuf == NULL) {
|
|
fprintf (stderr, "PIXBUF NULL\n");
|
|
return;
|
|
}
|
|
|
|
if (!gdk_pixbuf_save (pixbuf, "foo.ico", "ico",
|
|
&err,
|
|
NULL)) {
|
|
fprintf (stderr, "%s", err->message);
|
|
g_error_free (err);
|
|
} else {
|
|
do_compare(pixbuf,
|
|
gdk_pixbuf_new_from_file ("foo.ico", &err),
|
|
err);
|
|
}
|
|
}
|
|
|
|
if (evt->keyval == 'a') {
|
|
if (pixbuf == NULL) {
|
|
fprintf (stderr, "PIXBUF NULL\n");
|
|
return;
|
|
} else {
|
|
GdkPixbuf *alpha_buf;
|
|
|
|
alpha_buf = gdk_pixbuf_add_alpha (pixbuf,
|
|
FALSE, 0, 0, 0);
|
|
|
|
g_object_set_data_full (G_OBJECT (da),
|
|
"pixbuf", alpha_buf,
|
|
(GDestroyNotify) g_object_unref);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static int
|
|
close_app (GtkWidget *widget, gpointer data)
|
|
{
|
|
gtk_main_quit ();
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
draw_cb (GtkWidget *drawing_area, cairo_t *cr, gpointer data)
|
|
{
|
|
GdkPixbuf *pixbuf;
|
|
|
|
pixbuf = (GdkPixbuf *) g_object_get_data (G_OBJECT (drawing_area),
|
|
"pixbuf");
|
|
|
|
gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
|
|
cairo_paint (cr);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static int
|
|
configure_cb (GtkWidget *drawing_area, GdkEventConfigure *evt, gpointer data)
|
|
{
|
|
GdkPixbuf *pixbuf;
|
|
|
|
pixbuf = (GdkPixbuf *) g_object_get_data (G_OBJECT (drawing_area),
|
|
"pixbuf");
|
|
|
|
g_print ("X:%d Y:%d\n", evt->width, evt->height);
|
|
if (evt->width != gdk_pixbuf_get_width (pixbuf) || evt->height != gdk_pixbuf_get_height (pixbuf)) {
|
|
GdkWindow *root;
|
|
GdkPixbuf *new_pixbuf;
|
|
|
|
root = gdk_get_default_root_window ();
|
|
new_pixbuf = gdk_pixbuf_get_from_window (root,
|
|
0, 0, evt->width, evt->height);
|
|
g_object_set_data_full (G_OBJECT (drawing_area), "pixbuf", new_pixbuf,
|
|
(GDestroyNotify) g_object_unref);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
int
|
|
main (int argc, char **argv)
|
|
{
|
|
GdkWindow *root;
|
|
GtkWidget *window;
|
|
GtkWidget *vbox;
|
|
GtkWidget *drawing_area;
|
|
GdkPixbuf *pixbuf;
|
|
|
|
gtk_init (&argc, &argv);
|
|
|
|
root = gdk_get_default_root_window ();
|
|
pixbuf = gdk_pixbuf_get_from_window (root,
|
|
0, 0, 150, 160);
|
|
|
|
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
|
g_signal_connect (window, "delete_event",
|
|
G_CALLBACK (close_app), NULL);
|
|
g_signal_connect (window, "destroy",
|
|
G_CALLBACK (close_app), NULL);
|
|
|
|
vbox = gtk_vbox_new (FALSE, 0);
|
|
gtk_container_add (GTK_CONTAINER (window), vbox);
|
|
|
|
drawing_area = gtk_drawing_area_new ();
|
|
gtk_widget_set_size_request (GTK_WIDGET (drawing_area),
|
|
gdk_pixbuf_get_width (pixbuf),
|
|
gdk_pixbuf_get_height (pixbuf));
|
|
g_signal_connect (drawing_area, "draw",
|
|
G_CALLBACK (draw_cb), NULL);
|
|
|
|
g_signal_connect (drawing_area, "configure_event",
|
|
G_CALLBACK (configure_cb), NULL);
|
|
g_signal_connect (window, "key_press_event",
|
|
G_CALLBACK (keypress_check), drawing_area);
|
|
g_object_set_data_full (G_OBJECT (drawing_area), "pixbuf", pixbuf,
|
|
(GDestroyNotify) g_object_unref);
|
|
gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
|
|
|
|
gtk_widget_show_all (window);
|
|
gtk_main ();
|
|
return 0;
|
|
}
|