Regenerate the thumbnail in the list when we change scaling type now

2004-04-05  Rodney Dawes  <dobey@ximian.com>

	* gnome-wp-capplet.c (gnome_wp_scale_type_changed): Regenerate the
	thumbnail in the list when we change scaling type now
	(wallpaper_properties_init): Add GtkFileFilter support (needs love)
	TreeView is buggy, so we need to not set the vertical-separator
	style property for it
	* gnome-wp-item.c: Include <config.h> and <gnome.h> here
	(collect_save_options): Add a function to set all of the pixbuf options
	for the thumbnail pixbuf properly, so we can save them back out
	(gnome_wp_item_get_thumbnail): Fix up the code to
	generate the thumbnails for the list a bit, so that we have sexy
	thumbnails that look exactly like how the image would, on-screen
	Initialize all of the width/height variables to 0
	Add a new pixbuf variable for loading the original image to get the
	dimensions of it, so we can do thumbnailing more properly
	Use a LIST_IMAGE_WIDTH define, for the width of the images in the list
	Just return the bgpixbuf if we are creating the "No Wallpaper" thumb
	Save the thumbnail back out with the dimensions for the original image
	If our image is smaller than the list thumbnail, then just use 1.0 as
	the ratio for scaling the image for tiling/etc...
	Use the new API to do scaling inside the center/tile functions
	Reload the thumbnail pixbuf after generating it with the thumbnail
	system, so that we get all of the pixbuf options set correctly
	* gnome-wp-item.h (GnomeWPItem): store the original image's width
	and height in the item, so we can avoid reopening the original image
	every time we generate the thumbnail, on systems where the thumbnail
	doesn't contain the appropriate information
	* gnome-wp-utils.c (gnome_wp_pixbuf_tile):
	(gnome_wp_pixbuf_center): Add API to do the scaling inside these calls

	Fixes #136691
This commit is contained in:
Rodney Dawes 2004-04-05 21:32:02 +00:00 committed by Rodney Dawes
parent b30e5bc57f
commit 00006d7745
6 changed files with 226 additions and 65 deletions

View file

@ -1,3 +1,36 @@
2004-04-05 Rodney Dawes <dobey@ximian.com>
* gnome-wp-capplet.c (gnome_wp_scale_type_changed): Regenerate the
thumbnail in the list when we change scaling type now
(wallpaper_properties_init): Add GtkFileFilter support (needs love)
TreeView is buggy, so we need to not set the vertical-separator
style property for it
* gnome-wp-item.c: Include <config.h> and <gnome.h> here
(collect_save_options): Add a function to set all of the pixbuf options
for the thumbnail pixbuf properly, so we can save them back out
(gnome_wp_item_get_thumbnail): Fix up the code to
generate the thumbnails for the list a bit, so that we have sexy
thumbnails that look exactly like how the image would, on-screen
Initialize all of the width/height variables to 0
Add a new pixbuf variable for loading the original image to get the
dimensions of it, so we can do thumbnailing more properly
Use a LIST_IMAGE_WIDTH define, for the width of the images in the list
Just return the bgpixbuf if we are creating the "No Wallpaper" thumb
Save the thumbnail back out with the dimensions for the original image
If our image is smaller than the list thumbnail, then just use 1.0 as
the ratio for scaling the image for tiling/etc...
Use the new API to do scaling inside the center/tile functions
Reload the thumbnail pixbuf after generating it with the thumbnail
system, so that we get all of the pixbuf options set correctly
* gnome-wp-item.h (GnomeWPItem): store the original image's width
and height in the item, so we can avoid reopening the original image
every time we generate the thumbnail, on systems where the thumbnail
doesn't contain the appropriate information
* gnome-wp-utils.c (gnome_wp_pixbuf_tile):
(gnome_wp_pixbuf_center): Add API to do the scaling inside these calls
Fixes #136691
2004-04-01 Jody Goldberg <jody@gnome.org>
* Release 2.6.0.3

View file

@ -332,6 +332,7 @@ static void wp_props_load_wallpaper (gchar * key,
gtk_list_store_append (GTK_LIST_STORE (capplet->model), &iter);
pixbuf = gnome_wp_item_get_thumbnail (item, capplet->thumbs);
gnome_wp_item_update_description (item);
if (pixbuf != NULL) {
gtk_list_store_set (GTK_LIST_STORE (capplet->model), &iter,
@ -525,6 +526,7 @@ static void wallpaper_properties_clicked (GtkWidget * dialog,
static void gnome_wp_scale_type_changed (GtkMenuShell * shell,
GnomeWPCapplet * capplet) {
GnomeWPItem * item = NULL;
GdkPixbuf * pixbuf;
GtkTreeIter iter;
GtkTreeModel * model;
GtkTreeSelection * selection;
@ -558,6 +560,11 @@ static void gnome_wp_scale_type_changed (GtkMenuShell * shell,
default:
break;
}
pixbuf = gnome_wp_item_get_thumbnail (item, capplet->thumbs);
gtk_list_store_set (GTK_LIST_STORE (capplet->model), &iter,
0, pixbuf,
-1);
g_object_unref (pixbuf);
gconf_client_set_string (capplet->client, WP_OPTIONS_KEY,
item->options, NULL);
}
@ -1145,7 +1152,6 @@ static void wallpaper_properties_init (void) {
gtk_rc_parse_string ("style \"wp-tree-defaults\" {\n"
" GtkTreeView::horizontal-separator = 6\n"
" GtkTreeView::vertical-separator = 6\n"
"} widget_class \"*TreeView*\""
" style \"wp-tree-defaults\"\n\n"
"style \"wp-dialog-defaults\" {\n"

View file

@ -18,11 +18,15 @@
*
*/
#include "gnome-wp-item.h"
#include "gnome-wp-utils.h"
#include <config.h>
#include <gnome.h>
#include <string.h>
#include <libgnomevfs/gnome-vfs-mime-handlers.h>
#include "gnome-wp-item.h"
#include "gnome-wp-utils.h"
void gnome_wp_item_free (GnomeWPItem * item) {
if (item == NULL) {
return;
@ -49,38 +53,92 @@ void gnome_wp_item_free (GnomeWPItem * item) {
item = NULL;
}
static void collect_save_options (GdkPixbuf * pixbuf,
gchar *** keys,
gchar *** vals,
gint width,
gint height) {
gchar ** options;
gint n, count;
count = 0;
options = g_object_get_qdata (G_OBJECT (pixbuf),
g_quark_from_static_string ("gdk_pixbuf_options"));
if (options) {
for (n = 0; options[2 * n]; n++) {
++count;
*keys = g_realloc (*keys, sizeof (gchar *) * (count + 1));
*vals = g_realloc (*vals, sizeof (gchar *) * (count + 1));
(*keys)[count - 1] = g_strdup (options[2 * n]);
(*vals)[count - 1] = g_strdup (options[2 * n + 1]);
(*keys)[count] = NULL;
(*vals)[count] = NULL;
}
}
++count;
*keys = g_realloc (*keys, sizeof (gchar *) * (count + 1));
*vals = g_realloc (*vals, sizeof (gchar *) * (count + 1));
(*keys)[count - 1] = g_strdup ("tEXt::Thumb::Image::Width");
(*vals)[count - 1] = g_strdup_printf ("%d", width);
(*keys)[count] = NULL;
(*vals)[count] = NULL;
++count;
*keys = g_realloc (*keys, sizeof (gchar *) * (count + 1));
*vals = g_realloc (*vals, sizeof (gchar *) * (count + 1));
(*keys)[count - 1] = g_strdup ("tEXt::Thumb::Image::Height");
(*vals)[count - 1] = g_strdup_printf ("%d", height);
(*keys)[count] = NULL;
(*vals)[count] = NULL;
}
#define LIST_IMAGE_WIDTH 64
GdkPixbuf * gnome_wp_item_get_thumbnail (GnomeWPItem * item,
GnomeThumbnailFactory * thumbs) {
GdkPixbuf * pixbuf, * bgpixbuf;
GdkPixbuf * tmpbuf;
GdkPixbuf * scaled = NULL;
gint w, h, ratio;
gint bw, bh;
gint sw, sh, bw, bh, pw, ph, tw, th;
gdouble ratio;
sw = sh = bw = bh = pw = ph = tw = th = 0;
/*
Get the size of the screen and calculate our aspect ratio divisor
We do this, so that images are thumbnailed as they would look on
the screen in reality
*/
w = gdk_screen_get_width (gdk_screen_get_default ());
h = gdk_screen_get_height (gdk_screen_get_default ());
ratio = h / 48;
bw = w / ratio;
bh = h / ratio;
sw = gdk_screen_get_width (gdk_screen_get_default ());
sh = gdk_screen_get_height (gdk_screen_get_default ());
ratio = (gdouble) sw / (gdouble) LIST_IMAGE_WIDTH;
bw = sw / ratio;
bh = sh / ratio;
/*
Create the pixbuf for the background colors, which will show up for
oddly sized images, smaller images that are centered, or alpha images
*/
if (!strcmp (item->shade_type, "solid")) {
bgpixbuf = gnome_wp_pixbuf_new_solid (item->pcolor, w / ratio, h / ratio);
bgpixbuf = gnome_wp_pixbuf_new_solid (item->pcolor, bw, bh);
} else if (!strcmp (item->shade_type, "vertical-gradient")) {
bgpixbuf = gnome_wp_pixbuf_new_gradient (GTK_ORIENTATION_VERTICAL,
item->pcolor, item->scolor,
w / ratio, h / ratio);
bw, bh);
} else {
bgpixbuf = gnome_wp_pixbuf_new_gradient (GTK_ORIENTATION_HORIZONTAL,
item->pcolor, item->scolor,
w / ratio, h / ratio);
bw, bh);
}
/*
@ -93,7 +151,7 @@ GdkPixbuf * gnome_wp_item_get_thumbnail (GnomeWPItem * item,
g_file_test (item->fileinfo->thumburi, G_FILE_TEST_EXISTS)) {
pixbuf = gdk_pixbuf_new_from_file (item->fileinfo->thumburi, NULL);
} else if (!strcmp (item->filename, "(none)")) {
pixbuf = gdk_pixbuf_copy (bgpixbuf);
return bgpixbuf;
} else {
pixbuf = gnome_thumbnail_factory_generate_thumbnail (thumbs,
gnome_vfs_escape_path_string (item->filename),
@ -101,50 +159,65 @@ GdkPixbuf * gnome_wp_item_get_thumbnail (GnomeWPItem * item,
gnome_thumbnail_factory_save_thumbnail (thumbs, pixbuf,
gnome_vfs_escape_path_string (item->filename),
item->fileinfo->mtime);
g_object_unref (pixbuf);
pixbuf = gdk_pixbuf_new_from_file (item->fileinfo->thumburi, NULL);
}
if (pixbuf != NULL) {
w = gdk_pixbuf_get_width (pixbuf);
h = gdk_pixbuf_get_height (pixbuf);
const gchar * w_val, * h_val;
/*
Handle images large and small. We default to 1, since images smaller
than 64x48 don't need to be scaled down, and the tiled thumbnails
will look correct for really small pattern images
*/
if (h >= 48)
ratio = h / 48;
else if (w >= 64)
ratio = w / 64;
else
ratio = 1;
w_val = gdk_pixbuf_get_option (pixbuf, "tEXt::Thumb::Image::Width");
h_val = gdk_pixbuf_get_option (pixbuf, "tEXt::Thumb::Image::Height");
if (item->width <= 0 || item->height <= 0) {
if (w_val && h_val) {
item->width = atoi (w_val);
item->height = atoi (h_val);
} else {
gchar ** keys = NULL;
gchar ** vals = NULL;
scaled = gnome_thumbnail_scale_down_pixbuf (pixbuf, w / ratio, h / ratio);
tmpbuf = gdk_pixbuf_new_from_file (item->filename, NULL);
item->width = gdk_pixbuf_get_width (tmpbuf);
item->height = gdk_pixbuf_get_height (tmpbuf);
collect_save_options (pixbuf, &keys, &vals, item->width, item->height);
gdk_pixbuf_savev (pixbuf, item->fileinfo->thumburi, "png",
keys, vals, NULL);
g_object_unref (tmpbuf);
g_strfreev (keys);
g_strfreev (vals);
}
}
pw = gdk_pixbuf_get_width (pixbuf);
ph = gdk_pixbuf_get_height (pixbuf);
if (item->width <= bw && item->height <= bh)
ratio = 1.0;
tw = item->width / ratio;
th = item->height / ratio;
if (!strcmp (item->options, "wallpaper")) {
w = gdk_pixbuf_get_width (scaled);
h = gdk_pixbuf_get_height (scaled);
scaled = gnome_wp_pixbuf_tile (scaled, bgpixbuf);
scaled = gnome_wp_pixbuf_tile (pixbuf, bgpixbuf, tw, th);
} else if (!strcmp (item->options, "centered")) {
w = gdk_pixbuf_get_width (scaled);
h = gdk_pixbuf_get_height (scaled);
/*
This is for alpha centered images like gnome-logo-transparent.jpg
It's an ugly hack, that can potentially be removed when round() or
something like it decides to work
We scale it down again so that it looks proper, instead of the off-
center look that seems to appear without this hack
*/
if (gdk_pixbuf_get_has_alpha (pixbuf) && (w > bw || h > bh))
scaled = gnome_thumbnail_scale_down_pixbuf (scaled, w / 2, h / 2);
scaled = gnome_wp_pixbuf_center (scaled, bgpixbuf);
scaled = gnome_wp_pixbuf_center (pixbuf, bgpixbuf, tw, th);
} else if (!strcmp (item->options, "stretched")) {
scaled = gnome_wp_pixbuf_center (pixbuf, bgpixbuf, bw, bh);
} else if (!strcmp (item->options, "scaled")) {
if ((gdouble) ph * (gdouble) bw > (gdouble) pw * (gdouble) bh) {
tw = 0.5 + (gdouble) pw * (gdouble) bh / (gdouble) ph;
th = bh;
} else {
th = 0.5 + (gdouble) ph * (gdouble) bw / (gdouble) pw;
tw = bw;
}
scaled = gnome_wp_pixbuf_center (pixbuf, bgpixbuf, tw, th);
}
} else {
scaled = gdk_pixbuf_copy (bgpixbuf);
}
g_object_unref (pixbuf);
g_object_unref (bgpixbuf);
@ -155,7 +228,8 @@ void gnome_wp_item_update_description (GnomeWPItem * item) {
if (!strcmp (item->filename, "(none)")) {
item->description = g_strdup_printf ("<b>%s</b>", item->name);
} else {
item->description = g_strdup_printf ("<b>%s</b>\n%s (%LuK)",
item->description = g_strdup_printf ("<b>%s</b>\n"
"%s (%LuK)",
item->name,
gnome_vfs_mime_get_description (item->fileinfo->mime_type),
item->fileinfo->size / 1024);

View file

@ -52,6 +52,10 @@ struct _GnomeWPItem {
/* Did the user remove us? */
gboolean deleted;
/* Width and Height of the original image */
gint width;
gint height;
};
void gnome_wp_item_free (GnomeWPItem * item);

View file

@ -105,7 +105,10 @@ GdkPixbuf * gnome_wp_pixbuf_new_solid (GdkColor * color,
}
GdkPixbuf * gnome_wp_pixbuf_tile (GdkPixbuf * src_pixbuf,
GdkPixbuf * dest_pixbuf) {
GdkPixbuf * dest_pixbuf,
gint scaled_width,
gint scaled_height) {
GdkPixbuf * tmpbuf;
gdouble cx, cy;
gint dwidth, dheight;
gint swidth, sheight;
@ -115,47 +118,81 @@ GdkPixbuf * gnome_wp_pixbuf_tile (GdkPixbuf * src_pixbuf,
return gdk_pixbuf_copy (src_pixbuf);
}
swidth = gdk_pixbuf_get_width (src_pixbuf);
sheight = gdk_pixbuf_get_height (src_pixbuf);
tmpbuf = gdk_pixbuf_scale_simple (src_pixbuf, scaled_width, scaled_height,
GDK_INTERP_BILINEAR);
swidth = gdk_pixbuf_get_width (tmpbuf);
sheight = gdk_pixbuf_get_height (tmpbuf);
dwidth = gdk_pixbuf_get_width (dest_pixbuf);
dheight = gdk_pixbuf_get_height (dest_pixbuf);
for (cy = 0; cy < dheight; cy += sheight) {
for (cx = 0; cx < dwidth; cx += swidth) {
gdk_pixbuf_composite (src_pixbuf, dest_pixbuf, cx, cy,
gdk_pixbuf_composite (tmpbuf, dest_pixbuf, cx, cy,
MIN (swidth, dwidth - cx),
MIN (sheight, dheight - cy),
cx, cy, 1.0, 1.0, GDK_INTERP_BILINEAR, alpha);
cx, cy, 1.0, 1.0,
GDK_INTERP_BILINEAR, alpha);
}
}
g_object_unref (tmpbuf);
return gdk_pixbuf_copy (dest_pixbuf);
}
GdkPixbuf * gnome_wp_pixbuf_center (GdkPixbuf * src_pixbuf,
GdkPixbuf * dest_pixbuf) {
gdouble cx, cy;
GdkPixbuf * dest_pixbuf,
gint scaled_width,
gint scaled_height) {
GdkPixbuf * tmpbuf;
gint ox, oy, cx, cy;
gint dwidth, dheight;
gint swidth, sheight;
gint cwidth, cheight;
guint alpha = 255;
if (dest_pixbuf == NULL) {
return gdk_pixbuf_copy (src_pixbuf);
}
swidth = gdk_pixbuf_get_width (src_pixbuf);
sheight = gdk_pixbuf_get_height (src_pixbuf);
ox = cx = oy = cy = 0;
tmpbuf = gdk_pixbuf_scale_simple (src_pixbuf, scaled_width, scaled_height,
GDK_INTERP_BILINEAR);
swidth = gdk_pixbuf_get_width (tmpbuf);
sheight = gdk_pixbuf_get_height (tmpbuf);
dwidth = gdk_pixbuf_get_width (dest_pixbuf);
dheight = gdk_pixbuf_get_height (dest_pixbuf);
cx = (dwidth - swidth) / 2;
cy = (dheight - sheight) / 2;
if (dwidth > swidth) {
ox = (dwidth - swidth) / 2;
cx = 0;
cwidth = swidth;
} else {
cx = (swidth - dwidth) / 2;
oy = 0;
cwidth = dwidth;
}
gdk_pixbuf_composite (src_pixbuf, dest_pixbuf, cx, cy,
swidth, sheight,
cx, cy, 1.0, 1.0, GDK_INTERP_BILINEAR, alpha);
if (dheight > sheight) {
oy = ((dheight - sheight) / 2);
cy = 0;
cheight = sheight;
} else {
cy = (sheight - dheight) / 2;
oy = 0;
cheight = dheight;
}
gdk_pixbuf_composite (tmpbuf, dest_pixbuf, ox, oy,
cwidth, cheight,
ox - cx, oy - cy, 1.0, 1.0,
GDK_INTERP_BILINEAR, alpha);
g_object_unref (tmpbuf);
return gdk_pixbuf_copy (dest_pixbuf);
}

View file

@ -30,12 +30,19 @@ GdkPixbuf * gnome_wp_pixbuf_new_gradient (GtkOrientation orientation,
GdkColor * c1,
GdkColor * c2,
gint width, gint height);
GdkPixbuf * gnome_wp_pixbuf_new_solid (GdkColor * color,
gint width, gint height);
GdkPixbuf * gnome_wp_pixbuf_tile (GdkPixbuf * src_pixbuf,
GdkPixbuf * dest_pixbuf);
GdkPixbuf * dest_pixbuf,
gint scaled_width,
gint scaled_height);
GdkPixbuf * gnome_wp_pixbuf_center (GdkPixbuf * src_pixbuf,
GdkPixbuf * dest_pixbuf);
GdkPixbuf * dest_pixbuf,
gint scaled_width,
gint scaled_height);
G_END_DECLS