diff options
Diffstat (limited to 'thumbnails.c')
-rw-r--r-- | thumbnails.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/thumbnails.c b/thumbnails.c new file mode 100644 index 0000000..18e2d9f --- /dev/null +++ b/thumbnails.c @@ -0,0 +1,138 @@ +#include <unistd.h> +#include <utime.h> +#include <string.h> + +#include <glib/gstdio.h> +#include <gtk/gtk.h> + +#include "db.h" +#include "thumbnails.h" + +inline static gchar *get_wall_thumb_name(const gchar *filepath) { + GChecksum *ck; + gchar *s; + gchar *cksum; + + ck = g_checksum_new(G_CHECKSUM_MD5); + s = g_strdup_printf("file://%s", filepath); + g_checksum_update(ck, s, -1); + g_free(s); + cksum = g_strdup_printf("%s/.thumbnails/normal/%s.png", g_get_home_dir(), g_checksum_get_string(ck)); + g_checksum_free(ck); + return cksum; +} + +inline static time_t get_mtime(const gchar *filepath) { + struct utimbuf times; + + if(g_utime(filepath, ×) == 0) { + return times.modtime; + } else { + return 0; + } +} + +GdkPixbuf *get_thumbnail(const gchar *filepath) { + GdkPixbuf *pb, *pb2; + gint win_width, win_height, img_width, img_height, width, height; + gdouble scalex, scaley, width_ratio, height_ratio, max_ratio; + GError *error = NULL; + gchar *thumbname; + + thumbname = get_wall_thumb_name(filepath); + + if(g_access(thumbname, F_OK) == 0) { + pb = gdk_pixbuf_new_from_file(thumbname, &error); + g_free(thumbname); + return pb; + } else { + pb = gdk_pixbuf_new_from_file(filepath, &error); + } + + if(!pb) { + g_warning("%s", error->message); + g_free(error); + return NULL; + } + + img_width = gdk_pixbuf_get_width(pb); + img_height = gdk_pixbuf_get_height(pb); + win_width = win_height = 128; + + width_ratio = (gdouble)img_width / (gdouble)win_width; + height_ratio = (gdouble)img_height / (gdouble)win_height; + if(width_ratio > height_ratio) { + width = win_width; + height = (gint)(1.0 / width_ratio * img_height); + } else { + height = win_height; + width = (gint)(1.0 / height_ratio * img_width); + } + scalex = (gdouble)width / (gdouble)img_width; + scaley = (gdouble)height / (gdouble)img_height; + + pb2 = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, width, height); + gdk_pixbuf_scale(pb, pb2, 0, 0, width, height, 0, 0, scalex, scaley, GDK_INTERP_BILINEAR); + g_object_unref(pb); + + error = NULL; + if(!gdk_pixbuf_save(pb2, thumbname, "png", &error, + "tEXt::Thumb::URI", filepath, + "tEXt::Thumb::MTime", get_mtime(filepath), + "tEXt::Software", "walls", + NULL)) { + g_warning("%s", error->message); + g_free(error); + } + + g_free(thumbname); + + return pb2; +} + +static void fill_wall_list(GtkListStore *liststore, GArray *array) { + GtkTreeIter iter; + + for(int i = 0; i < array->len; i++) { + struct wallpaper_t *wall; + wall = &g_array_index(array, struct wallpaper_t, i); + + gtk_list_store_append(liststore, &iter); + gtk_list_store_set(liststore, &iter, 0, NULL, 1, wall->filepath, -1); + g_free(wall->filepath); + } + g_array_free(array, TRUE); +} + +gpointer add_thumbs_thread(gpointer data) { + GtkListStore *liststore; + GtkTreeIter iter; + int n; + GValue value; + GdkPixbuf *pb = NULL; + const gchar *filepath; + + liststore = GTK_LIST_STORE(data); + + if(!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(liststore), &iter)) { + return NULL; + } + + n = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(liststore), NULL); + + memset(&value, 0, sizeof(GValue)); + + for(int i = 0; i < n; i++) { + gtk_tree_model_get_value(GTK_TREE_MODEL(liststore), &iter, 1, &value); + printf("file: %s\n", g_value_get_string(&value)); + filepath = g_value_get_string(&value); + pb = get_thumbnail(filepath); + g_value_unset(&value); + if(pb) { + gtk_list_store_set(liststore, &iter, 0, pb, -1); + + g_object_unref(pb); + } + gtk_tree_model_iter_next(GTK_TREE_MODEL(liststore), &iter); + } +} |