#include #include #include #include #include #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); } }