[gthumb: 46/129] equalize tool: operate on the image_surface directly instead of converting to/from a GdkPixbuf



commit 7542cf265a6d27a41e03626b713bebaafddbc241
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Tue Apr 19 13:19:43 2011 +0200

    equalize tool: operate on the image_surface directly instead of converting to/from a GdkPixbuf

 extensions/file_tools/gth-file-tool-equalize.c |  162 ++++++++++++++++--------
 1 files changed, 110 insertions(+), 52 deletions(-)
---
diff --git a/extensions/file_tools/gth-file-tool-equalize.c b/extensions/file_tools/gth-file-tool-equalize.c
index 6c12b1d..6468b07 100644
--- a/extensions/file_tools/gth-file-tool-equalize.c
+++ b/extensions/file_tools/gth-file-tool-equalize.c
@@ -27,9 +27,11 @@
 
 
 typedef struct {
-	GtkWidget     *viewer_page;
-	GthHistogram  *histogram;
-	int          **part;
+	GtkWidget        *viewer_page;
+	cairo_surface_t  *source;
+	cairo_surface_t  *destination;
+	GthHistogram     *histogram;
+	int             **part;
 } EqualizeData;
 
 
@@ -75,19 +77,10 @@ equalize_histogram_setup (GthHistogram  *hist,
 
 
 static void
-equalize_init (GthPixbufTask *pixop)
+equalize_before (GthAsyncTask *task,
+	         gpointer      user_data)
 {
-	EqualizeData *data = pixop->data;
-	int           i;
-
-	copy_source_to_destination (pixop);
-	data->histogram = gth_histogram_new ();
-	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++)
-		data->part[i] = g_new0 (int, 257);
-	equalize_histogram_setup (data->histogram, data->part);
+	gth_task_progress (GTH_TASK (task), _("Equalizing image histogram"), NULL, TRUE, 0.0);
 }
 
 
@@ -103,55 +96,123 @@ equalize_func (guchar   u_value,
 }
 
 
-static void
-equalize_step (GthPixbufTask *pixop)
+static gpointer
+equalize_exec (GthAsyncTask *task,
+	       gpointer      user_data)
 {
-	EqualizeData *data = pixop->data;
+	EqualizeData    *equalize_data = user_data;
+	int              i;
+	cairo_format_t   format;
+	int              width;
+	int              height;
+	int              source_stride;
+	int              destination_stride;
+	unsigned char   *p_source_line;
+	unsigned char   *p_destination_line;
+	unsigned char   *p_source;
+	unsigned char   *p_destination;
+	gboolean         cancelled;
+	double           progress;
+	gboolean         terminated;
+	int              x, y;
+	unsigned char    red, green, blue, alpha;
+
+	/* initialize the extra data */
+
+	equalize_data->histogram = gth_histogram_new ();
+	gth_histogram_calculate_for_image (equalize_data->histogram, equalize_data->source);
+
+	equalize_data->part = g_new0 (int *, GTH_HISTOGRAM_N_CHANNELS);
+	for (i = 0; i < GTH_HISTOGRAM_N_CHANNELS; i++)
+		equalize_data->part[i] = g_new0 (int, 257);
+	equalize_histogram_setup (equalize_data->histogram, equalize_data->part);
+
+	/* convert the image */
+
+	format = cairo_image_surface_get_format (equalize_data->source);
+	width = cairo_image_surface_get_width (equalize_data->source);
+	height = cairo_image_surface_get_height (equalize_data->source);
+	source_stride = cairo_image_surface_get_stride (equalize_data->source);
+
+	equalize_data->destination = cairo_image_surface_create (format, width, height);
+	destination_stride = cairo_image_surface_get_stride (equalize_data->destination);
+	p_source_line = cairo_image_surface_get_data (equalize_data->source);
+	p_destination_line = cairo_image_surface_get_data (equalize_data->destination);
+	for (y = 0; y < height; y++) {
+		gth_async_task_get_data (task, NULL, &cancelled, NULL);
+		if (cancelled)
+			return NULL;
+
+		progress = (double) y / height;
+		gth_async_task_set_data (task, NULL, NULL, &progress);
+
+		p_source = p_source_line;
+		p_destination = p_destination_line;
+		for (x = 0; x < width; x++) {
+			CAIRO_GET_RGBA (p_source, red, green, blue, alpha);
+			red   = equalize_func (red, equalize_data->part, RED_PIX);
+			green = equalize_func (green, equalize_data->part, GREEN_PIX);
+			blue  = equalize_func (blue, equalize_data->part, BLUE_PIX);
+			if (alpha != 0xff)
+				alpha = equalize_func (alpha, equalize_data->part, ALPHA_PIX);
+			CAIRO_SET_RGBA (p_destination, red, green, blue, alpha);
+
+			p_source += 4;
+			p_destination += 4;
+		}
+		p_source_line += source_stride;
+		p_destination_line += destination_stride;
+	}
 
-	pixop->dest_pixel[RED_PIX]   = equalize_func (pixop->src_pixel[RED_PIX], data->part, 0);
-	pixop->dest_pixel[GREEN_PIX] = equalize_func (pixop->src_pixel[GREEN_PIX], data->part, 1);
-	pixop->dest_pixel[BLUE_PIX]  = equalize_func (pixop->src_pixel[BLUE_PIX], data->part, 2);
-	if (pixop->has_alpha)
-		pixop->dest_pixel[ALPHA_PIX] = equalize_func (pixop->src_pixel[ALPHA_PIX], data->part, 3);
+	terminated = TRUE;
+	gth_async_task_set_data (task, &terminated, NULL, NULL);
+
+	return NULL;
 }
 
 
 static void
-equalize_release (GthPixbufTask *pixop,
-		  GError        *error)
+equalize_after (GthAsyncTask *task,
+	        GError       *error,
+	        gpointer      user_data)
 {
-	EqualizeData *data = pixop->data;
+	EqualizeData *equalize_data = user_data;
 	int           i;
 
 	if (error == NULL)
-		gth_image_viewer_page_set_pixbuf (GTH_IMAGE_VIEWER_PAGE (data->viewer_page), pixop->dest, TRUE);
+		gth_image_viewer_page_set_image (GTH_IMAGE_VIEWER_PAGE (equalize_data->viewer_page), equalize_data->destination, TRUE);
 
 	for (i = 0; i < GTH_HISTOGRAM_N_CHANNELS; i++)
-		g_free (data->part[i]);
-	g_free (data->part);
-	g_object_unref (data->histogram);
+		g_free (equalize_data->part[i]);
+	g_free (equalize_data->part);
+	equalize_data->part = NULL;
+
+	g_object_unref (equalize_data->histogram);
+	equalize_data->histogram = NULL;
 }
 
 
 static void
 equalize_destroy_data (gpointer user_data)
 {
-	EqualizeData *data = user_data;
+	EqualizeData *equalize_data = user_data;
 
-	g_object_unref (data->viewer_page);
-	g_free (data);
+	g_object_unref (equalize_data->viewer_page);
+	cairo_surface_destroy (equalize_data->destination);
+	cairo_surface_destroy (equalize_data->source);
+	g_free (equalize_data);
 }
 
 
 static void
 gth_file_tool_equalize_activate (GthFileTool *base)
 {
-	GtkWidget    *window;
-	GtkWidget    *viewer_page;
-	GtkWidget    *viewer;
-	GdkPixbuf    *src_pixbuf;
-	EqualizeData *data;
-	GthTask      *task;
+	GtkWidget       *window;
+	GtkWidget       *viewer_page;
+	GtkWidget       *viewer;
+	cairo_surface_t *image;
+	EqualizeData    *equalize_data;
+	GthTask         *task;
 
 	window = gth_file_tool_get_window (base);
 	viewer_page = gth_browser_get_viewer_page (GTH_BROWSER (window));
@@ -159,24 +220,21 @@ gth_file_tool_equalize_activate (GthFileTool *base)
 		return;
 
 	viewer = gth_image_viewer_page_get_image_viewer (GTH_IMAGE_VIEWER_PAGE (viewer_page));
-	src_pixbuf = gth_image_viewer_get_current_pixbuf (GTH_IMAGE_VIEWER (viewer));
-	if (src_pixbuf == NULL)
+	image = gth_image_viewer_get_current_image (GTH_IMAGE_VIEWER (viewer));
+	if (image == NULL)
 		return;
 
-	data = g_new0 (EqualizeData, 1);
-	data->viewer_page = g_object_ref (viewer_page);
-	task = gth_pixbuf_task_new (_("Equalizing image histogram"),
-				    FALSE,
-				    equalize_init,
-				    equalize_step,
-				    equalize_release,
-				    data,
-				    equalize_destroy_data);
-	gth_pixbuf_task_set_source (GTH_PIXBUF_TASK (task), src_pixbuf);
+	equalize_data = g_new0 (EqualizeData, 1);
+	equalize_data->viewer_page = g_object_ref (viewer_page);
+	equalize_data->source = cairo_surface_reference (image);
+	task = gth_async_task_new (equalize_before,
+				   equalize_exec,
+				   equalize_after,
+				   equalize_data,
+				   equalize_destroy_data);
 	gth_browser_exec_task (GTH_BROWSER (window), task, FALSE);
 
 	g_object_unref (task);
-	g_object_unref (src_pixbuf);
 }
 
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]