summaryrefslogtreecommitdiff
path: root/thumbnails.c
diff options
context:
space:
mode:
Diffstat (limited to 'thumbnails.c')
-rw-r--r--thumbnails.c138
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, &times) == 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);
+ }
+}