# HG changeset patch # User nadvornik # Date 1234703481 0 # Node ID 7ac9664242b26ea3657bcfb504578cbf0f05937a # Parent 48e064b37ba6a52c81050531f4e9502ce778401d histogram caching histogram interface prepared for histogram pane diff -r 48e064b37ba6 -r 7ac9664242b2 src/filedata.c --- a/src/filedata.c Sun Feb 15 09:36:53 2009 +0000 +++ b/src/filedata.c Sun Feb 15 13:11:21 2009 +0000 @@ -515,7 +515,8 @@ 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); + g_assert(fd->sidecar_files == NULL); /* sidecar files must be freed before calling this */ file_data_change_info_free(NULL, fd); diff -r 48e064b37ba6 -r 7ac9664242b2 src/histogram.c --- a/src/histogram.c Sun Feb 15 09:36:53 2009 +0000 +++ b/src/histogram.c Sun Feb 15 13:11:21 2009 +0000 @@ -23,10 +23,22 @@ *---------------------------------------------------------------------------- */ -#define HISTOGRAM_SIZE 256 +#define HISTMAP_SIZE 256 +typedef enum { + HISTMAP_CHANNEL_R = 0, + HISTMAP_CHANNEL_G, + HISTMAP_CHANNEL_B, + HISTMAP_CHANNEL_AVG, + HISTMAP_CHANNEL_MAX, + HISTMAP_CHANNELS +} HistMapChannels; + +struct _HistMap { + gulong histmap[HISTMAP_SIZE * HISTMAP_CHANNELS]; + gulong area; +}; struct _Histogram { - gulong histmap[HISTOGRAM_SIZE*4]; gint histogram_chan; gint histogram_logmode; }; @@ -104,83 +116,83 @@ return t1; } -gulong histogram_read(Histogram *histogram, GdkPixbuf *imgpixbuf) +static HistMap *histmap_read(GdkPixbuf *imgpixbuf) { gint w, h, i, j, srs, has_alpha, step; guchar *s_pix; - if (!histogram) return 0; - + HistMap *histmap; + 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); - memset(histogram->histmap, 0, sizeof(histogram->histmap)); + histmap = g_new0(HistMap, 1); - /* code duplication is here to speed up the calculation */ step = 3 + !!(has_alpha); - if (histogram->histogram_chan == HCHAN_MAX) + for (i = 0; i < h; i++) { - for (i = 0; i < h; i++) + guchar *sp = s_pix + (i * srs); /* 8bit */ + for (j = 0; j < w; j++) { - guchar *sp = s_pix + (i * srs); /* 8bit */ - for (j = 0; j < w; j++) - { - guchar t = sp[0]; - if (sp[1]>t) t = sp[1]; - if (sp[2]>t) t = sp[2]; + guint avg = (sp[0] + sp[1] + sp[2]) / 3; + guint max = sp[0]; + if (sp[1] > max) max = sp[1]; + if (sp[2] > max) max = sp[2]; - histogram->histmap[sp[0] + 0 * HISTOGRAM_SIZE]++; - histogram->histmap[sp[1] + 1 * HISTOGRAM_SIZE]++; - histogram->histmap[sp[2] + 2 * HISTOGRAM_SIZE]++; - histogram->histmap[t + 3 * HISTOGRAM_SIZE]++; - sp += step; - } + histmap->histmap[sp[0] * HISTMAP_CHANNELS + HISTMAP_CHANNEL_R]++; + histmap->histmap[sp[1] * HISTMAP_CHANNELS + HISTMAP_CHANNEL_G]++; + histmap->histmap[sp[2] * HISTMAP_CHANNELS + HISTMAP_CHANNEL_B]++; + histmap->histmap[avg * HISTMAP_CHANNELS + HISTMAP_CHANNEL_AVG]++; + histmap->histmap[max * HISTMAP_CHANNELS + HISTMAP_CHANNEL_MAX]++; + sp += step; } } - else - { - for (i = 0; i < h; i++) - { - guchar *sp = s_pix + (i * srs); /* 8bit */ - for (j = 0; j < w; j++) - { - histogram->histmap[sp[0] + 0 * HISTOGRAM_SIZE]++; - histogram->histmap[sp[1] + 1 * HISTOGRAM_SIZE]++; - histogram->histmap[sp[2] + 2 * HISTOGRAM_SIZE]++; - histogram->histmap[3 * HISTOGRAM_SIZE + (sp[0]+sp[1]+sp[2])/3]++; - sp += step; - } - } - } - - return w*h; + histmap->area = w * h; + return histmap; } -gint histogram_draw(Histogram *histogram, GdkPixbuf *pixbuf, gint x, gint y, gint width, gint height) +HistMap *histmap_get(FileData *fd) +{ + if (fd->histmap) return fd->histmap; + + if (fd->pixbuf) + { + fd->histmap = histmap_read(fd->pixbuf); + return fd->histmap; + } + return NULL; +} + +gint histogram_draw(Histogram *histogram, HistMap *histmap, GdkPixbuf *pixbuf, gint x, gint y, gint width, gint height) { /* FIXME: use the coordinates correctly */ gint i; gulong max = 0; gdouble logmax; - if (!histogram) return 0; + if (!histogram || !histmap) return 0; for (i = 0; i < 1024; i++) { +#if 0 + /* this is probably broken for MAX or VAL mode */ gint flag = 0; switch (histogram->histogram_chan) { - case HCHAN_RGB: if ((i%4) != 3) flag = 1; break; - case HCHAN_R: if ((i%4) == 0) flag = 1; break; - case HCHAN_G: if ((i%4) == 1) flag = 1; break; - case HCHAN_B: if ((i%4) == 2) flag = 1; break; - case HCHAN_VAL: if ((i%4) == 3) flag = 1; break; - case HCHAN_MAX: if ((i%4) == 3) flag = 1; break; + case HCHAN_RGB: if ((i % HISTMAP_CHANNELS) < 3) flag = 1; break; + case HCHAN_R: if ((i % HISTMAP_CHANNELS) == HISTMAP_CHANNEL_R) flag = 1; break; + case HCHAN_G: if ((i % HISTMAP_CHANNELS) == HISTMAP_CHANNEL_G) flag = 1; break; + case HCHAN_B: if ((i % HISTMAP_CHANNELS) == HISTMAP_CHANNEL_B) flag = 1; break; + case HCHAN_VAL: if ((i % HISTMAP_CHANNELS) == HISTMAP_CHANNEL_AVG) flag = 1; break; + case HCHAN_MAX: if ((i % HISTMAP_CHANNELS) == HISTMAP_CHANNEL_MAX) flag = 1; break; } - if (flag && histogram->histmap[i] > max) max = histogram->histmap[i]; + if (flag && histmap->histmap[i] > max) max = histmap->histmap[i]; +#else + if (histmap->histmap[i] > max) max = histmap->histmap[i]; +#endif } logmax = log(max); @@ -191,15 +203,21 @@ gint rplus = 0; gint gplus = 0; gint bplus = 0; - gint ii = i * HISTOGRAM_SIZE / width; - gint combine = (HISTOGRAM_SIZE - 1) / width + 1; + gint ii = i * HISTMAP_SIZE / width; + gint combine = (HISTMAP_SIZE - 1) / width + 1; for (j = 0; j < combine; j++) { - v[0] += histogram->histmap[ii + j + 0 * HISTOGRAM_SIZE]; // r - v[1] += histogram->histmap[ii + j + 1 * HISTOGRAM_SIZE]; // g - v[2] += histogram->histmap[ii + j + 2 * HISTOGRAM_SIZE]; // b - v[3] += histogram->histmap[ii + j + 3 * HISTOGRAM_SIZE]; // value, max + v[0] += histmap->histmap[(ii + j) * HISTMAP_CHANNELS + HISTMAP_CHANNEL_R]; // r + v[1] += histmap->histmap[(ii + j) * HISTMAP_CHANNELS + HISTMAP_CHANNEL_G]; // g + v[2] += histmap->histmap[(ii + j) * HISTMAP_CHANNELS + HISTMAP_CHANNEL_B]; // b + v[3] += histmap->histmap[(ii + j) * HISTMAP_CHANNELS + + ((histogram->histogram_chan == HCHAN_VAL) ? HISTMAP_CHANNEL_AVG : HISTMAP_CHANNEL_MAX)]; // value, max + } + + for (j = 0; j < 4; j++) + { + v[j] /= combine; } for (j = 0; j < 4; j++) @@ -258,4 +276,14 @@ return TRUE; } + +void histogram_notify_cb(FileData *fd, NotifyType type, gpointer data) +{ + if (type != NOTIFY_TYPE_INTERNAL && fd->histmap) + { + g_free(fd->histmap); + fd->histmap = NULL; + } +} + /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r 48e064b37ba6 -r 7ac9664242b2 src/histogram.h --- a/src/histogram.h Sun Feb 15 09:36:53 2009 +0000 +++ b/src/histogram.h Sun Feb 15 13:11:21 2009 +0000 @@ -30,8 +30,10 @@ gint histogram_set_mode(Histogram *histogram, gint mode); gint histogram_get_mode(Histogram *histogram); const gchar *histogram_label(Histogram *histogram); -gulong histogram_read(Histogram *histogram, GdkPixbuf *imgpixbuf); -gint histogram_draw(Histogram *histogram, GdkPixbuf *pixbuf, gint x, gint y, gint width, gint height); +HistMap *histmap_get(FileData *fd); +gint histogram_draw(Histogram *histogram, HistMap *histmap, GdkPixbuf *pixbuf, gint x, gint y, gint width, gint height); + +void histogram_notify_cb(FileData *fd, NotifyType type, gpointer data); #endif /* HISTOGRAM_H */ /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r 48e064b37ba6 -r 7ac9664242b2 src/image-overlay.c --- a/src/image-overlay.c Sun Feb 15 09:36:53 2009 +0000 +++ b/src/image-overlay.c Sun Feb 15 13:11:21 2009 +0000 @@ -442,6 +442,7 @@ gchar *text; GdkPixbuf *imgpixbuf = NULL; gboolean with_hist; + HistMap *histmap; ImageWindow *imd = osd->imd; FileData *fd = image_get_fd(imd); @@ -553,7 +554,13 @@ text = g_markup_escape_text(_("Untitled"), -1); } - with_hist = (imgpixbuf && (osd->show & OSD_SHOW_HISTOGRAM) && osd->histogram && (!imd->il || image_loader_get_is_done(imd->il))); + with_hist = ((osd->show & OSD_SHOW_HISTOGRAM) && osd->histogram); + if (with_hist) + { + histmap = histmap_get(imd->image_fd); + if (!histmap) with_hist = FALSE; + } + { gint active_marks = 0; @@ -611,7 +618,6 @@ if (with_hist) { - histogram_read(osd->histogram, imgpixbuf); if (width < HISTOGRAM_WIDTH + 10) width = HISTOGRAM_WIDTH + 10; height += HISTOGRAM_HEIGHT + 5; } @@ -649,7 +655,7 @@ xoffset += add+d; } - histogram_draw(osd->histogram, pixbuf, x, y, w, HISTOGRAM_HEIGHT); + histogram_draw(osd->histogram, histmap, pixbuf, x, y, w, HISTOGRAM_HEIGHT); } pixbuf_draw_layout(pixbuf, layout, imd->pr, 5, 5, 0, 0, 0, 255); } diff -r 48e064b37ba6 -r 7ac9664242b2 src/image.c --- a/src/image.c Sun Feb 15 09:36:53 2009 +0000 +++ b/src/image.c Sun Feb 15 13:11:21 2009 +0000 @@ -538,14 +538,14 @@ DEBUG_1("%s image done", get_exec_time()); - g_object_set(G_OBJECT(imd->pr), "loading", FALSE, NULL); - image_state_unset(imd, IMAGE_STATE_LOADING); - if (options->image.enable_read_ahead && imd->image_fd && !imd->image_fd->pixbuf && image_loader_get_pixbuf(imd->il)) { imd->image_fd->pixbuf = g_object_ref(image_loader_get_pixbuf(imd->il)); image_cache_set(imd, imd->image_fd); } + /* call the callback triggered by image_state after fd->pixbuf is set */ + g_object_set(G_OBJECT(imd->pr), "loading", FALSE, NULL); + image_state_unset(imd, IMAGE_STATE_LOADING); if (!image_loader_get_pixbuf(imd->il)) { diff -r 48e064b37ba6 -r 7ac9664242b2 src/main.c --- a/src/main.c Sun Feb 15 09:36:53 2009 +0000 +++ b/src/main.c Sun Feb 15 13:11:21 2009 +0000 @@ -33,6 +33,7 @@ #include "metadata.h" #include "editors.h" #include "exif.h" +#include "histogram.h" #include /* for keyboard values */ @@ -743,6 +744,7 @@ /* register global notify functions */ file_data_register_notify_func(cache_notify_cb, NULL, NOTIFY_PRIORITY_HIGH); file_data_register_notify_func(thumb_notify_cb, NULL, NOTIFY_PRIORITY_HIGH); + file_data_register_notify_func(histogram_notify_cb, NULL, NOTIFY_PRIORITY_HIGH); file_data_register_notify_func(collect_manager_notify_cb, NULL, NOTIFY_PRIORITY_LOW); parse_command_line_for_debug_option(argc, argv); diff -r 48e064b37ba6 -r 7ac9664242b2 src/typedefs.h --- a/src/typedefs.h Sun Feb 15 09:36:53 2009 +0000 +++ b/src/typedefs.h Sun Feb 15 13:11:21 2009 +0000 @@ -200,6 +200,7 @@ typedef struct _PixmapFolders PixmapFolders; typedef struct _Histogram Histogram; +typedef struct _HistMap HistMap; typedef struct _SecureSaveInfo SecureSaveInfo; @@ -451,6 +452,8 @@ GdkPixbuf *pixbuf; /* full-size image, only complete images, NULL during loading all FileData with non-NULL pixbuf are referenced by image_cache */ + + HistMap *histmap; gint ref; gint version; /* increased when any field in this structure is changed */