[gthumb: 17/129] gth-image-histogram: calculate the histogram directly from the cairo_surface



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]