#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 stat sb; if(g_stat(filepath, &sb) == 0) { return sb.st_mtime; } 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, *mtime, *width_s, *height_s; 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; mtime = g_strdup_printf("%d", get_mtime(filepath)); width_s = g_strdup_printf("%d", img_width); height_s = g_strdup_printf("%d", img_height); if(!gdk_pixbuf_save(pb2, thumbname, "png", &error, "tEXt::Thumb::URI", filepath, "tEXt::Thumb::MTime", mtime, "tEXt::Software", "walls", "tEXt::Thumb::Image::Width", width_s, "tEXt::Thumb::Image::Height", height_s, NULL)) { g_warning("%s", error->message); g_error_free(error); } g_free(mtime); g_free(width_s); g_free(height_s); g_free(thumbname); return pb2; } 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); 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); } }