[gthumb: 41/129] desaturate tool: use the cairo_surface directly instead of converting to/from a GdkPixbuf



commit 5b71aeefaf1aae80add957b2eb0a2a43af6d112f
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Mon Apr 18 22:11:22 2011 +0200

    desaturate tool: use the cairo_surface directly instead of converting to/from a GdkPixbuf

 extensions/file_tools/gth-file-tool-desaturate.c |  152 ++++++++++++++++------
 1 files changed, 110 insertions(+), 42 deletions(-)
---
diff --git a/extensions/file_tools/gth-file-tool-desaturate.c b/extensions/file_tools/gth-file-tool-desaturate.c
index 724052b..3f27962 100644
--- a/extensions/file_tools/gth-file-tool-desaturate.c
+++ b/extensions/file_tools/gth-file-tool-desaturate.c
@@ -3,7 +3,7 @@
 /*
  *  GThumb
  *
- *  Copyright (C) 2009 Free Software Foundation, Inc.
+ *  Copyright (C) 2011 Free Software Foundation, Inc.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -25,6 +25,13 @@
 #include "gth-file-tool-desaturate.h"
 
 
+typedef struct {
+	GtkWidget       *viewer_page;
+	cairo_surface_t *source;
+	cairo_surface_t *destination;
+} DesaturateData;
+
+
 static void
 gth_file_tool_desaturate_update_sensitivity (GthFileTool *base)
 {
@@ -41,51 +48,114 @@ gth_file_tool_desaturate_update_sensitivity (GthFileTool *base)
 
 
 static void
-desaturate_step (GthPixbufTask *pixop)
+desaturate_data_free (gpointer user_data)
 {
-	guchar min, max, lightness;
-
-	max = MAX (pixop->src_pixel[RED_PIX], pixop->src_pixel[GREEN_PIX]);
-	max = MAX (max, pixop->src_pixel[BLUE_PIX]);
-	min = MIN (pixop->src_pixel[RED_PIX], pixop->src_pixel[GREEN_PIX]);
-	min = MIN (min, pixop->src_pixel[BLUE_PIX]);
-	lightness = (max + min) / 2;
-
-	pixop->dest_pixel[RED_PIX]   = lightness;
-	pixop->dest_pixel[GREEN_PIX] = lightness;
-	pixop->dest_pixel[BLUE_PIX]  = lightness;
+	DesaturateData *desaturate_data = user_data;
 
-	if (pixop->has_alpha)
-		pixop->dest_pixel[ALPHA_PIX] = pixop->src_pixel[ALPHA_PIX];
+	cairo_surface_destroy (desaturate_data->destination);
+	cairo_surface_destroy (desaturate_data->source);
+	g_free (desaturate_data);
 }
 
 
 static void
-task_completed_cb (GthTask  *task,
-		   GError   *error,
-		   gpointer  user_data)
+desaturate_init (GthAsyncTask *task,
+	         gpointer      user_data)
 {
-	GthFileTool *base = user_data;
+	gth_task_progress (GTH_TASK (task), _("Applying changes"), NULL, TRUE, 0.0);
+}
 
-	if (error == NULL) {
-		GthPixbufTask *pixbuf_task;
-		GtkWidget     *viewer_page;
 
-		pixbuf_task = GTH_PIXBUF_TASK (task);
-		viewer_page = gth_browser_get_viewer_page (GTH_BROWSER (gth_file_tool_get_window (base)));
-		gth_image_viewer_page_set_pixbuf (GTH_IMAGE_VIEWER_PAGE (viewer_page), pixbuf_task->dest, TRUE);
+static gpointer
+desaturate_exec (GthAsyncTask *task,
+	         gpointer      user_data)
+{
+	DesaturateData    *desaturate_data = user_data;
+	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;
+	unsigned char    min, max, lightness;
+
+	format = cairo_image_surface_get_format (desaturate_data->source);
+	width = cairo_image_surface_get_width (desaturate_data->source);
+	height = cairo_image_surface_get_height (desaturate_data->source);
+	source_stride = cairo_image_surface_get_stride (desaturate_data->source);
+
+	desaturate_data->destination = cairo_image_surface_create (format, width, height);
+	destination_stride = cairo_image_surface_get_stride (desaturate_data->destination);
+	p_source_line = cairo_image_surface_get_data (desaturate_data->source);
+	p_destination_line = cairo_image_surface_get_data (desaturate_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);
+
+			max = MAX (MAX (red, green), blue);
+			min = MIN (MIN (red, green), blue);
+			lightness = (max + min) / 2;
+
+			CAIRO_SET_RGBA (p_destination,
+					lightness,
+					lightness,
+					lightness,
+					alpha);
+
+			p_source += 4;
+			p_destination += 4;
+		}
+		p_source_line += source_stride;
+		p_destination_line += destination_stride;
 	}
+
+	terminated = TRUE;
+	gth_async_task_set_data (task, &terminated, NULL, NULL);
+
+	return NULL;
+}
+
+
+static void
+desaturate_after (GthAsyncTask *task,
+		  GError       *error,
+		  gpointer      user_data)
+{
+	DesaturateData *desaturate_data = user_data;
+
+	if (error == NULL)
+		gth_image_viewer_page_set_image (GTH_IMAGE_VIEWER_PAGE (desaturate_data->viewer_page),
+					         desaturate_data->destination,
+					         TRUE);
 }
 
 
 static void
 gth_file_tool_desaturate_activate (GthFileTool *base)
 {
-	GtkWidget *window;
-	GtkWidget *viewer_page;
-	GtkWidget *viewer;
-	GdkPixbuf *src_pixbuf;
-	GthTask   *task;
+	GtkWidget       *window;
+	GtkWidget       *viewer_page;
+	GtkWidget       *viewer;
+	cairo_surface_t *image;
+	DesaturateData  *desaturate_data;
+	GthTask         *task;
 
 	window = gth_file_tool_get_window (base);
 	viewer_page = gth_browser_get_viewer_page (GTH_BROWSER (window));
@@ -93,23 +163,21 @@ gth_file_tool_desaturate_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;
 
-	task = gth_pixbuf_task_new (_("Desaturating image"),
-				    FALSE,
-				    copy_source_to_destination,
-				    desaturate_step,
-				    NULL,
-				    NULL,
-				    NULL);
-	gth_pixbuf_task_set_source (GTH_PIXBUF_TASK (task), src_pixbuf);
-	g_signal_connect (task, "completed", G_CALLBACK (task_completed_cb), base);
+	desaturate_data = g_new0 (DesaturateData, 1);
+	desaturate_data->viewer_page = viewer_page;
+	desaturate_data->source = cairo_surface_reference (image);
+	task = gth_async_task_new (desaturate_init,
+				   desaturate_exec,
+				   desaturate_after,
+				   desaturate_data,
+				   desaturate_data_free);
 	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]