diff src/histogram.c @ 1439:2441a90c4bcf

compute histogram in idle time
author nadvornik
date Sun, 15 Mar 2009 11:34:09 +0000
parents cf4029d10d38
children 29aa897ea540
line wrap: on
line diff
--- a/src/histogram.c	Sun Mar 15 09:06:13 2009 +0000
+++ b/src/histogram.c	Sun Mar 15 11:34:09 2009 +0000
@@ -14,6 +14,7 @@
 #include "histogram.h"
 
 #include "pixbuf_util.h"
+#include "filedata.h"
 
 #include <math.h>
 
@@ -30,6 +31,10 @@
 	gulong g[HISTMAP_SIZE];
 	gulong b[HISTMAP_SIZE];
 	gulong max[HISTMAP_SIZE];
+	
+	gint idle_id;
+	GdkPixbuf *pixbuf;
+	gint y;
 };
 
 
@@ -123,22 +128,46 @@
 	return t1;
 }
 
-static HistMap *histmap_read(GdkPixbuf *imgpixbuf)
+static HistMap *histmap_new(void)
+{
+	HistMap *histmap = g_new0(HistMap, 1);
+	histmap->idle_id = -1;
+	return histmap;
+}
+
+void histmap_free(HistMap *histmap)
 {
-	gint w, h, i, j, srs, has_alpha, step;
+	if (!histmap) return;
+	if (histmap->idle_id != -1) g_source_remove(histmap->idle_id);
+	if (histmap->pixbuf) g_object_unref(histmap->pixbuf);
+	g_free(histmap);
+}
+
+static gboolean histmap_read(HistMap *histmap, gboolean whole)
+{
+	gint w, h, i, j, srs, has_alpha, step, end_line;
 	guchar *s_pix;
-	HistMap *histmap;
+	GdkPixbuf *imgpixbuf = histmap->pixbuf;
 	
 	w = gdk_pixbuf_get_width(imgpixbuf);
 	h = gdk_pixbuf_get_height(imgpixbuf);
 	srs = gdk_pixbuf_get_rowstride(imgpixbuf);
 	s_pix = gdk_pixbuf_get_pixels(imgpixbuf);
 	has_alpha = gdk_pixbuf_get_has_alpha(imgpixbuf);
-
-	histmap = g_new0(HistMap, 1);
+	
+	if (whole)
+		{
+		end_line = h;
+		}
+	else
+		{
+		gint lines = 1 + 16384 / w;
+		end_line = histmap->y + lines;
+		if (end_line > h) end_line = h;
+		}
 
 	step = 3 + !!(has_alpha);
-	for (i = 0; i < h; i++)
+	for (i = histmap->y; i < end_line; i++)
 		{
 		guchar *sp = s_pix + (i * srs); /* 8bit */
 		for (j = 0; j < w; j++)
@@ -155,22 +184,45 @@
 			sp += step;
 			}
 		}
-	
-	return histmap;
+	histmap->y = end_line;
+	return end_line >= h;	
 }
 
 const HistMap *histmap_get(FileData *fd)
 {
-	if (fd->histmap) return fd->histmap;
+	if (fd->histmap && fd->histmap->idle_id == -1) return fd->histmap; /* histmap exists and is finished */
 	
-	if (fd->pixbuf)
-		{
-		fd->histmap = histmap_read(fd->pixbuf);
-		return fd->histmap;
-		}
 	return NULL;
 }
 
+static gboolean histmap_idle_cb(gpointer data)
+{
+	FileData *fd = data;
+	if (histmap_read(fd->histmap, FALSE))
+		{
+		/* finished */
+		g_object_unref(fd->histmap->pixbuf); /*pixbuf is no longer needed */
+		fd->histmap->pixbuf = NULL;
+		fd->histmap->idle_id = -1;
+		file_data_send_notification(fd, NOTIFY_HISTMAP);
+		return FALSE;
+		}
+	return TRUE;
+}
+
+gboolean histmap_start_idle(FileData *fd)
+{
+	if (fd->histmap || !fd->pixbuf) return FALSE;
+
+	fd->histmap = histmap_new();
+	fd->histmap->pixbuf = fd->pixbuf;
+	g_object_ref(fd->histmap->pixbuf);
+
+	fd->histmap->idle_id = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, histmap_idle_cb, fd, NULL);
+	return TRUE;
+}
+
+
 static void histogram_vgrid(Histogram *histogram, GdkPixbuf *pixbuf, gint x, gint y, gint width, gint height)
 {
 	guint i;
@@ -322,7 +374,7 @@
 {
 	if ((type & (NOTIFY_CHANGE || NOTIFY_REREAD)) && fd->histmap)
 		{
-		g_free(fd->histmap);
+		histmap_free(fd->histmap);
 		fd->histmap = NULL;
 		}
 }