[gthumb: 17/129] gth-image-histogram: calculate the histogram directly from the cairo_surface
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gthumb: 17/129] gth-image-histogram: calculate the histogram directly from the cairo_surface
- Date: Wed, 27 Apr 2011 20:51:48 +0000 (UTC)
commit 66f4c1a7aaebeaa23c7de24995429a45516484d9
Author: Paolo Bacchilega <paobac src gnome org>
Date: Fri Apr 15 13:38:36 2011 +0200
gth-image-histogram: calculate the histogram directly from the cairo_surface
.../file_tools/gth-file-tool-adjust-colors.c | 4 +-
extensions/file_tools/gth-file-tool-enhance.c | 2 +-
extensions/file_tools/gth-file-tool-equalize.c | 2 +-
extensions/image_viewer/gth-image-histogram.c | 12 +--
gthumb/cairo-utils.c | 2 +-
gthumb/cairo-utils.h | 45 ++++++++---
gthumb/gth-histogram.c | 85 ++++++++++++++++++--
gthumb/gth-histogram.h | 37 +++++----
gthumb/gth-image-viewer.c | 2 +-
gthumb/pixbuf-utils.c | 2 +-
10 files changed, 143 insertions(+), 50 deletions(-)
---
diff --git a/extensions/file_tools/gth-file-tool-adjust-colors.c b/extensions/file_tools/gth-file-tool-adjust-colors.c
index ea2b614..f031b7a 100644
--- a/extensions/file_tools/gth-file-tool-adjust-colors.c
+++ b/extensions/file_tools/gth-file-tool-adjust-colors.c
@@ -271,7 +271,7 @@ task_completed_cb (GthTask *task,
window = gth_file_tool_get_window (GTH_FILE_TOOL (self));
viewer_page = gth_browser_get_viewer_page (GTH_BROWSER (window));
gth_image_viewer_page_set_pixbuf (GTH_IMAGE_VIEWER_PAGE (viewer_page), self->priv->dest_pixbuf, FALSE);
- gth_histogram_calculate (self->priv->histogram, self->priv->dest_pixbuf);
+ gth_histogram_calculate_for_pixbuf (self->priv->histogram, self->priv->dest_pixbuf);
}
g_object_unref (task);
@@ -435,7 +435,7 @@ gth_file_tool_adjust_colors_get_options (GthFileTool *base)
G_CALLBACK (value_changed_cb),
self);
- gth_histogram_calculate (self->priv->histogram, self->priv->src_pixbuf);
+ gth_histogram_calculate_for_pixbuf (self->priv->histogram, self->priv->src_pixbuf);
return options;
}
diff --git a/extensions/file_tools/gth-file-tool-enhance.c b/extensions/file_tools/gth-file-tool-enhance.c
index f9c5517..ed2213f 100644
--- a/extensions/file_tools/gth-file-tool-enhance.c
+++ b/extensions/file_tools/gth-file-tool-enhance.c
@@ -115,7 +115,7 @@ adjust_levels_init (GthPixbufTask *pixop)
copy_source_to_destination (pixop);
data->histogram = gth_histogram_new ();
- gth_histogram_calculate (data->histogram, pixop->src);
+ gth_histogram_calculate_for_pixbuf (data->histogram, pixop->src);
data->levels = g_new0 (Levels, 1);
diff --git a/extensions/file_tools/gth-file-tool-equalize.c b/extensions/file_tools/gth-file-tool-equalize.c
index 65d216f..6c12b1d 100644
--- a/extensions/file_tools/gth-file-tool-equalize.c
+++ b/extensions/file_tools/gth-file-tool-equalize.c
@@ -82,7 +82,7 @@ equalize_init (GthPixbufTask *pixop)
copy_source_to_destination (pixop);
data->histogram = gth_histogram_new ();
- gth_histogram_calculate (data->histogram, pixop->src);
+ gth_histogram_calculate_for_pixbuf (data->histogram, pixop->src);
data->part = g_new0 (int *, GTH_HISTOGRAM_N_CHANNELS);
for (i = 0; i < GTH_HISTOGRAM_N_CHANNELS; i++)
diff --git a/extensions/image_viewer/gth-image-histogram.c b/extensions/image_viewer/gth-image-histogram.c
index e589d07..dcc6aea 100644
--- a/extensions/image_viewer/gth-image-histogram.c
+++ b/extensions/image_viewer/gth-image-histogram.c
@@ -44,31 +44,27 @@ gth_image_histogram_real_set_file (GthPropertyView *base,
GthFileData *file_data)
{
GthImageHistogram *self = GTH_IMAGE_HISTOGRAM (base);
- GdkPixbuf *pixbuf;
GthBrowser *browser;
GtkWidget *viewer_page;
if (file_data == NULL) {
- gth_histogram_calculate (self->priv->histogram, NULL);
+ gth_histogram_calculate_for_image (self->priv->histogram, NULL);
return;
}
browser = (GthBrowser *) gtk_widget_get_toplevel (GTK_WIDGET (base));
if (! gtk_widget_is_toplevel (GTK_WIDGET (browser))) {
- gth_histogram_calculate (self->priv->histogram, NULL);
+ gth_histogram_calculate_for_image (self->priv->histogram, NULL);
return;
}
viewer_page = gth_browser_get_viewer_page (browser);
if (! GTH_IS_IMAGE_VIEWER_PAGE (viewer_page)) {
- gth_histogram_calculate (self->priv->histogram, NULL);
+ gth_histogram_calculate_for_image (self->priv->histogram, NULL);
return;
}
- pixbuf = gth_image_viewer_page_get_pixbuf (GTH_IMAGE_VIEWER_PAGE (viewer_page)); /* FIXME: use the cairo_surface here */
- gth_histogram_calculate (self->priv->histogram, pixbuf);
-
- g_object_unref (pixbuf);
+ gth_histogram_calculate_for_image (self->priv->histogram, gth_image_viewer_page_get_image (GTH_IMAGE_VIEWER_PAGE (viewer_page)));
}
diff --git a/gthumb/cairo-utils.c b/gthumb/cairo-utils.c
index 7a16d54..2ff4f1f 100644
--- a/gthumb/cairo-utils.c
+++ b/gthumb/cairo-utils.c
@@ -130,7 +130,7 @@ _cairo_clear_surface (cairo_surface_t **surface)
gboolean
-_cairo_image_surface_has_alpha (cairo_surface_t *surface)
+_cairo_image_surface_get_has_alpha (cairo_surface_t *surface)
{
cairo_surface_metadata_t *metadata;
diff --git a/gthumb/cairo-utils.h b/gthumb/cairo-utils.h
index ea78fbb..38b6bc4 100644
--- a/gthumb/cairo-utils.h
+++ b/gthumb/cairo-utils.h
@@ -51,17 +51,38 @@
#endif
-#define CAIRO_SET_RGB(s_iter, red, green, blue) \
- s_iter[CAIRO_RED] = (red); \
- s_iter[CAIRO_GREEN] = (green); \
- s_iter[CAIRO_BLUE] = (blue);
-
-#define CAIRO_SET_RGBA(s_iter, red, green, blue, alpha) \
- s_iter[CAIRO_RED] = (red); \
- s_iter[CAIRO_GREEN] = (green); \
- s_iter[CAIRO_BLUE] = (blue); \
- s_iter[CAIRO_ALPHA] = (alpha);
-
+#define CAIRO_SET_RGB(pixel, red, green, blue) \
+ do { \
+ pixel[CAIRO_RED] = (red); \
+ pixel[CAIRO_GREEN] = (green); \
+ pixel[CAIRO_BLUE] = (blue); \
+ } while (0)
+
+#define CAIRO_SET_RGBA(pixel, red, green, blue, alpha) \
+ do { \
+ pixel[CAIRO_RED] = (red); \
+ pixel[CAIRO_GREEN] = (green); \
+ pixel[CAIRO_BLUE] = (blue); \
+ pixel[CAIRO_ALPHA] = (alpha); \
+ } while (0)
+
+#define CAIRO_GET_RGB(pixel, red, green, blue) \
+ do { \
+ red = pixel[CAIRO_RED]; \
+ green = pixel[CAIRO_GREEN]; \
+ blue = pixel[CAIRO_BLUE]; \
+ } while (0)
+
+#define CAIRO_GET_RGBA(pixel, red, green, blue, alpha) \
+ do { \
+ gdouble alpha_factor; \
+ \
+ alpha = pixel[CAIRO_ALPHA]; \
+ alpha_factor = (gdouble) 0xff / alpha; \
+ red = (guchar) (pixel[CAIRO_RED] * alpha_factor + .5); \
+ green = (guchar) (pixel[CAIRO_GREEN] * alpha_factor + .5); \
+ blue = (guchar) (pixel[CAIRO_BLUE] * alpha_factor + .5); \
+ } while (0)
typedef struct {
double r;
@@ -87,7 +108,7 @@ void _cairo_paint_full_gradient (cairo_surface_t *surface,
GdkColor *v_color1,
GdkColor *v_color2);
void _cairo_clear_surface (cairo_surface_t **surface);
-gboolean _cairo_image_surface_has_alpha (cairo_surface_t *surface);
+gboolean _cairo_image_surface_get_has_alpha (cairo_surface_t *surface);
cairo_surface_t *
_cairo_image_surface_create_from_pixbuf
(GdkPixbuf *pixbuf);
diff --git a/gthumb/gth-histogram.c b/gthumb/gth-histogram.c
index 71fbfae..55f5387 100644
--- a/gthumb/gth-histogram.c
+++ b/gthumb/gth-histogram.c
@@ -21,6 +21,7 @@
#include <string.h>
+#include "cairo-utils.h"
#include "gth-histogram.h"
@@ -151,8 +152,8 @@ gth_histogram_changed (GthHistogram *self)
void
-gth_histogram_calculate (GthHistogram *self,
- const GdkPixbuf *pixbuf)
+gth_histogram_calculate_for_pixbuf (GthHistogram *self,
+ const GdkPixbuf *pixbuf)
{
int **values;
int *values_max;
@@ -185,16 +186,15 @@ gth_histogram_calculate (GthHistogram *self,
for (i = 0; i < height; i++) {
pixel = line;
- line += rowstride;
for (j = 0; j < width; j++) {
- /* count values for each RGB channel */
+ /* count values for each RGB channel */
values[1][pixel[0]] += 1;
values[2][pixel[1]] += 1;
values[3][pixel[2]] += 1;
if (n_channels > 3)
values[4][ pixel[3] ] += 1;
-
+
/* count value for Value channel */
max = MAX (pixel[0], pixel[1]);
max = MAX (pixel[2], max);
@@ -210,6 +210,79 @@ gth_histogram_calculate (GthHistogram *self,
pixel += n_channels;
}
+
+ line += rowstride;
+ }
+
+ gth_histogram_changed (self);
+}
+
+
+void
+gth_histogram_calculate_for_image (GthHistogram *self,
+ cairo_surface_t *image)
+{
+ int **values;
+ int *values_max;
+ int width, height, has_alpha;
+ int rowstride;
+ guchar *line, *pixel;
+ int i, j, max;
+ guchar red, green, blue, alpha;
+
+ g_return_if_fail (GTH_IS_HISTOGRAM (self));
+
+ values = self->priv->values;
+ values_max = self->priv->values_max;
+
+ if (image == NULL) {
+ self->priv->n_channels = 0;
+ histogram_reset_values (self);
+ gth_histogram_changed (self);
+ return;
+ }
+
+ has_alpha = _cairo_image_surface_get_has_alpha (image);
+ rowstride = cairo_image_surface_get_stride (image);
+ line = cairo_image_surface_get_data (image);
+ width = cairo_image_surface_get_width (image);
+ height = cairo_image_surface_get_height (image);
+
+ self->priv->n_channels = (has_alpha ? 4 : 3) + 1;
+ histogram_reset_values (self);
+
+ for (i = 0; i < height; i++) {
+ pixel = line;
+
+ for (j = 0; j < width; j++) {
+ if (has_alpha)
+ CAIRO_GET_RGBA(pixel, red, green, blue, alpha);
+ else
+ CAIRO_GET_RGB(pixel, red, green, blue);
+
+ /* count values for each RGB channel */
+ values[1][red] += 1;
+ values[2][green] += 1;
+ values[3][blue] += 1;
+ if (has_alpha)
+ values[4][alpha] += 1;
+
+ /* count value for Value channel */
+ max = MAX (MAX (red, green), blue);
+ values[0][max] += 1;
+
+ /* track max value for each channel */
+ values_max[0] = MAX (values_max[0], values[0][max]);
+ values_max[1] = MAX (values_max[1], values[1][red]);
+ values_max[2] = MAX (values_max[2], values[2][green]);
+ values_max[3] = MAX (values_max[3], values[3][blue]);
+ if (has_alpha)
+ values_max[4] = MAX (values_max[4], values[4][alpha]);
+
+ pixel += 4;
+ }
+
+ line += rowstride;
}
gth_histogram_changed (self);
@@ -228,7 +301,7 @@ gth_histogram_get_count (GthHistogram *self,
for (i = start; i <= end; i++)
count += self->priv->values[0][i];
-
+
return count;
}
diff --git a/gthumb/gth-histogram.h b/gthumb/gth-histogram.h
index 7ac61a4..77ea5e5 100644
--- a/gthumb/gth-histogram.h
+++ b/gthumb/gth-histogram.h
@@ -23,6 +23,7 @@
#define GTH_HISTOGRAM_H
#include <glib-object.h>
+#include <cairo.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
G_BEGIN_DECLS
@@ -61,23 +62,25 @@ struct _GthHistogramClass {
void (*changed) (GthHistogram *self);
};
-GType gth_histogram_get_type (void) G_GNUC_CONST;
-GthHistogram * gth_histogram_new (void);
-void gth_histogram_calculate (GthHistogram *self,
- const GdkPixbuf *pixbuf);
-double gth_histogram_get_count (GthHistogram *self,
- int start,
- int end);
-double gth_histogram_get_value (GthHistogram *self,
- GthHistogramChannel channel,
- int bin);
-double gth_histogram_get_channel (GthHistogram *self,
- GthHistogramChannel channel,
- int bin);
-double gth_histogram_get_channel_max (GthHistogram *self,
- GthHistogramChannel channel);
-double gth_histogram_get_max (GthHistogram *self);
-int gth_histogram_get_nchannels (GthHistogram *self);
+GType gth_histogram_get_type (void) G_GNUC_CONST;
+GthHistogram * gth_histogram_new (void);
+void gth_histogram_calculate_for_image (GthHistogram *self,
+ cairo_surface_t *image);
+void gth_histogram_calculate_for_pixbuf (GthHistogram *self,
+ const GdkPixbuf *pixbuf);
+double gth_histogram_get_count (GthHistogram *self,
+ int start,
+ int end);
+double gth_histogram_get_value (GthHistogram *self,
+ GthHistogramChannel channel,
+ int bin);
+double gth_histogram_get_channel (GthHistogram *self,
+ GthHistogramChannel channel,
+ int bin);
+double gth_histogram_get_channel_max (GthHistogram *self,
+ GthHistogramChannel channel);
+double gth_histogram_get_max (GthHistogram *self);
+int gth_histogram_get_nchannels (GthHistogram *self);
G_END_DECLS
diff --git a/gthumb/gth-image-viewer.c b/gthumb/gth-image-viewer.c
index a60d5c2..f44bbac 100644
--- a/gthumb/gth-image-viewer.c
+++ b/gthumb/gth-image-viewer.c
@@ -1845,7 +1845,7 @@ gth_image_viewer_get_original_size (GthImageViewer *self,
gboolean
gth_image_viewer_get_has_alpha (GthImageViewer *self)
{
- return _cairo_image_surface_has_alpha (self->priv->surface);
+ return _cairo_image_surface_get_has_alpha (self->priv->surface);
}
diff --git a/gthumb/pixbuf-utils.c b/gthumb/pixbuf-utils.c
index 52479c4..13083b0 100644
--- a/gthumb/pixbuf-utils.c
+++ b/gthumb/pixbuf-utils.c
@@ -88,7 +88,7 @@ _gdk_pixbuf_new_from_cairo_surface (cairo_surface_t *surface)
s_stride = cairo_image_surface_get_stride (surface);
s_pixels = cairo_image_surface_get_data (surface);
- pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, _cairo_image_surface_has_alpha (surface), 8, width, height);
+ pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, _cairo_image_surface_get_has_alpha (surface), 8, width, height);
p_stride = gdk_pixbuf_get_rowstride (pixbuf);
p_pixels = gdk_pixbuf_get_pixels (pixbuf);
p_n_channels = gdk_pixbuf_get_n_channels (pixbuf);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]