# HG changeset patch # User nadvornik # Date 1237116849 0 # Node ID 2441a90c4bcf1d2d50e52ec2b96a108b162007ec # Parent 9141908e0609d9c49d897da3a4bae8a22f2763af compute histogram in idle time diff -r 9141908e0609 -r 2441a90c4bcf src/bar_histogram.c --- a/src/bar_histogram.c Sun Mar 15 09:06:13 2009 +0000 +++ b/src/bar_histogram.c Sun Mar 15 11:34:09 2009 +0000 @@ -83,7 +83,11 @@ histmap = histmap_get(phd->fd); - if (!histmap) return FALSE; + if (!histmap) + { + histmap_start_idle(phd->fd); + return FALSE; + } phd->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, phd->histogram_width, phd->histogram_height); gdk_pixbuf_fill(phd->pixbuf, 0xffffffff); @@ -126,7 +130,7 @@ static void bar_pane_histogram_notify_cb(FileData *fd, NotifyType type, gpointer data) { PaneHistogramData *phd = data; - if (fd == phd->fd) bar_pane_histogram_update(phd); + if ((type & (NOTIFY_REREAD | NOTIFY_CHANGE | NOTIFY_HISTMAP | NOTIFY_PIXBUF)) && fd == phd->fd) bar_pane_histogram_update(phd); } static gboolean bar_pane_histogram_expose_event_cb(GtkWidget *widget, GdkEventExpose *event, gpointer data) diff -r 9141908e0609 -r 2441a90c4bcf src/filedata.c --- a/src/filedata.c Sun Mar 15 09:06:13 2009 +0000 +++ b/src/filedata.c Sun Mar 15 11:34:09 2009 +0000 @@ -20,6 +20,7 @@ #include "ui_fileops.h" #include "metadata.h" #include "trash.h" +#include "histogram.h" static GHashTable *file_data_pool = NULL; @@ -509,7 +510,7 @@ g_free(fd->collate_key_name); g_free(fd->collate_key_name_nocase); if (fd->thumb_pixbuf) g_object_unref(fd->thumb_pixbuf); - g_free(fd->histmap); + histmap_free(fd->histmap); g_assert(fd->sidecar_files == NULL); /* sidecar files must be freed before calling this */ diff -r 9141908e0609 -r 2441a90c4bcf src/histogram.c --- 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 @@ -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; } } diff -r 9141908e0609 -r 2441a90c4bcf src/histogram.h --- a/src/histogram.h Sun Mar 15 09:06:13 2009 +0000 +++ b/src/histogram.h Sun Mar 15 11:34:09 2009 +0000 @@ -31,7 +31,12 @@ gint histogram_toggle_channel(Histogram *histogram); gint histogram_toggle_mode(Histogram *histogram); const gchar *histogram_label(Histogram *histogram); + +void histmap_free(HistMap *histmap); + const HistMap *histmap_get(FileData *fd); +gboolean histmap_start_idle(FileData *fd); + gboolean histogram_draw(Histogram *histogram, const HistMap *histmap, GdkPixbuf *pixbuf, gint x, gint y, gint width, gint height); void histogram_notify_cb(FileData *fd, NotifyType type, gpointer data); diff -r 9141908e0609 -r 2441a90c4bcf src/image-overlay.c --- a/src/image-overlay.c Sun Mar 15 09:06:13 2009 +0000 +++ b/src/image-overlay.c Sun Mar 15 11:34:09 2009 +0000 @@ -37,6 +37,7 @@ struct _OverlayStateData { ImageWindow *imd; ImageState changed_states; + NotifyType notify; Histogram *histogram; @@ -557,7 +558,11 @@ if (with_hist) { histmap = histmap_get(imd->image_fd); - if (!histmap) with_hist = FALSE; + if (!histmap) + { + histmap_start_idle(imd->image_fd); + with_hist = FALSE; + } } @@ -829,7 +834,8 @@ /* redraw when the image was changed, with histogram we have to redraw also when loading is finished */ if (osd->changed_states & IMAGE_STATE_IMAGE || - (osd->changed_states & IMAGE_STATE_LOADING && osd->show & OSD_SHOW_HISTOGRAM)) + (osd->changed_states & IMAGE_STATE_LOADING && osd->show & OSD_SHOW_HISTOGRAM) || + osd->notify & NOTIFY_HISTMAP) { GdkPixbuf *pixbuf; @@ -884,6 +890,7 @@ if (osd->imd->il && image_loader_get_is_done(osd->imd->il)) osd->changed_states = IMAGE_STATE_NONE; + osd->notify = 0; osd->idle_id = -1; return FALSE; } @@ -958,6 +965,18 @@ image_osd_update_schedule(osd, FALSE); } +static void image_osd_notify_cb(FileData *fd, NotifyType type, gpointer data) +{ + OverlayStateData *osd = data; + + if ((type & (NOTIFY_HISTMAP)) && osd->imd && fd == osd->imd->image_fd) + { + osd->notify |= type; + image_osd_update_schedule(osd, FALSE); + } +} + + static void image_osd_free(OverlayStateData *osd) { if (!osd) return; @@ -965,6 +984,8 @@ if (osd->idle_id != -1) g_source_remove(osd->idle_id); if (osd->timer_id != -1) g_source_remove(osd->timer_id); + file_data_unregister_notify_func(image_osd_notify_cb, osd); + if (osd->imd) { image_set_osd_data(osd->imd, NULL); @@ -1017,6 +1038,7 @@ image_set_osd_data(imd, osd); image_set_state_func(osd->imd, image_osd_state_cb, osd); + file_data_register_notify_func(image_osd_notify_cb, osd, NOTIFY_PRIORITY_LOW); } if (show & OSD_SHOW_STATUS)