[gthumb: 42/129] adjust colors: use the cairo_surface directly instead of converting to/from a GdkPixbuf



commit 6e59438759605ae0b454f7d819cae0b62bcb89c3
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Mon Apr 18 23:28:29 2011 +0200

    adjust colors: use the cairo_surface directly instead of converting to/from a GdkPixbuf

 .../file_tools/gth-file-tool-adjust-colors.c       |  368 +++++++++++---------
 gthumb/cairo-utils.c                               |    3 +
 gthumb/cairo-utils.h                               |    4 +
 gthumb/gth-histogram.c                             |    5 +-
 4 files changed, 209 insertions(+), 171 deletions(-)
---
diff --git a/extensions/file_tools/gth-file-tool-adjust-colors.c b/extensions/file_tools/gth-file-tool-adjust-colors.c
index f031b7a..2eca2da 100644
--- a/extensions/file_tools/gth-file-tool-adjust-colors.c
+++ b/extensions/file_tools/gth-file-tool-adjust-colors.c
@@ -34,45 +34,48 @@ static gpointer parent_class = NULL;
 
 
 struct _GthFileToolAdjustColorsPrivate {
-	GdkPixbuf     *src_pixbuf;
-	GdkPixbuf     *dest_pixbuf;
-	GtkBuilder    *builder;
-	GtkAdjustment *gamma_adj;
-	GtkAdjustment *brightness_adj;
-	GtkAdjustment *contrast_adj;
-	GtkAdjustment *saturation_adj;
-	GtkAdjustment *cyan_red_adj;
-	GtkAdjustment *magenta_green_adj;
-	GtkAdjustment *yellow_blue_adj;
-	GtkWidget     *histogram_view;
-	GthHistogram  *histogram;
-	GthTask       *pixbuf_task;
-	guint          apply_event;
+	cairo_surface_t *source;
+	cairo_surface_t *destination;
+	GtkBuilder      *builder;
+	GtkAdjustment   *gamma_adj;
+	GtkAdjustment   *brightness_adj;
+	GtkAdjustment   *contrast_adj;
+	GtkAdjustment   *saturation_adj;
+	GtkAdjustment   *cyan_red_adj;
+	GtkAdjustment   *magenta_green_adj;
+	GtkAdjustment   *yellow_blue_adj;
+	GtkWidget       *histogram_view;
+	GthHistogram    *histogram;
+	GthTask         *image_task;
+	guint            apply_event;
 };
 
 
 typedef struct {
-	GtkWidget   *viewer_page;
-	double       gamma;
-	double       brightness;
-	double       contrast;
-	double       saturation;
-	double       color_level[3];
-	PixbufCache *cache;
-	double       midtone_distance[256];
+	GthFileToolAdjustColors *self;
+	cairo_surface_t         *source;
+	cairo_surface_t         *destination;
+	GtkWidget               *viewer_page;
+	double                   gamma;
+	double                   brightness;
+	double                   contrast;
+	double                   saturation;
+	double                   color_level[3];
+	PixbufCache             *cache;
+	double                   midtone_distance[256];
 } AdjustData;
 
 
 static void
-adjust_colors_init (GthPixbufTask *pixop)
+adjust_colors_before (GthAsyncTask *task,
+		      gpointer      user_data)
 {
-	AdjustData *data = pixop->data;
+	AdjustData *adjust_data = user_data;
 	int         i;
 
-	copy_source_to_destination (pixop);
-	data->cache = pixbuf_cache_new ();
+	adjust_data->cache = pixbuf_cache_new ();
 	for (i = 0; i < 256; i++)
-		data->midtone_distance[i] = 0.667 * (1 - SQR (((double) i - 127.0) / 127.0));
+		adjust_data->midtone_distance[i] = 0.667 * (1 - SQR (((double) i - 127.0) / 127.0));
 }
 
 
@@ -81,7 +84,7 @@ interpolate_value (guchar original,
 		   guchar reference,
 		   double distance)
 {
-	return CLAMP((distance * reference) + ((1.0 - distance) * original), 0, 255);
+	return CLAMP ((distance * reference) + ((1.0 - distance) * original), 0, 255);
 }
 
 
@@ -104,86 +107,145 @@ gamma_correction (guchar original,
 }
 
 
-static void
-adjust_colors_step (GthPixbufTask *pixop)
+static gpointer
+adjust_colors_exec (GthAsyncTask *task,
+		    gpointer      user_data)
 {
-	AdjustData *data = pixop->data;
-	int         channel;
-
-	if (pixop->has_alpha)
-		pixop->dest_pixel[ALPHA_PIX] = pixop->src_pixel[ALPHA_PIX];
-
-	/* gamma correction / brightness / contrast */
-
-	for (channel = RED_PIX; channel <= BLUE_PIX; channel++) {
-		guchar v;
-
-		v = pixop->src_pixel[channel];
-		if (! pixbuf_cache_get (data->cache, channel + 1, &v)) {
-			int i;
-
-			v = gamma_correction (v, data->gamma);
-
-			if (data->brightness > 0)
-				v = interpolate_value (v, 0, data->brightness);
-			else
-				v = interpolate_value (v, 255, - data->brightness);
-
-			if (data->contrast < 0)
-				v = interpolate_value (v, 127, tan (data->contrast * G_PI_2) /*data->contrast*/);
-			else
-				v = interpolate_value (v, 127, data->contrast);
-
-			i = v + data->color_level[channel] * data->midtone_distance[v];
-			v = CLAMP(i, 0, 255);
-
-			pixbuf_cache_set (data->cache, channel + 1, pixop->src_pixel[channel], v);
+	AdjustData      *adjust_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    values[4];
+	int              channel;
+	unsigned char    value;
+
+	format = cairo_image_surface_get_format (adjust_data->source);
+	width = cairo_image_surface_get_width (adjust_data->source);
+	height = cairo_image_surface_get_height (adjust_data->source);
+	source_stride = cairo_image_surface_get_stride (adjust_data->source);
+
+	adjust_data->destination = cairo_image_surface_create (format, width, height);
+	destination_stride = cairo_image_surface_get_stride (adjust_data->destination);
+	p_source_line = cairo_image_surface_get_data (adjust_data->source);
+	p_destination_line = cairo_image_surface_get_data (adjust_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, values[0], values[1], values[2], values[3]);
+
+			/* gamma correction / brightness / contrast */
+
+			for (channel = 0; channel < 3; channel++) {
+				value = values[channel];
+
+				if (! pixbuf_cache_get (adjust_data->cache, channel + 1, &value)) {
+					int i;
+
+					value = gamma_correction (value, adjust_data->gamma);
+
+					if (adjust_data->brightness > 0)
+						value = interpolate_value (value, 0, adjust_data->brightness);
+					else
+						value = interpolate_value (value, 255, - adjust_data->brightness);
+
+					if (adjust_data->contrast < 0)
+						value = interpolate_value (value, 127, tan (adjust_data->contrast * G_PI_2));
+					else
+						value = interpolate_value (value, 127, adjust_data->contrast);
+
+					i = value + adjust_data->color_level[channel] * adjust_data->midtone_distance[value];
+					value = CLAMP (i, 0, 255);
+
+					pixbuf_cache_set (adjust_data->cache, channel + 1, values[channel], value);
+				}
+
+				values[channel] = value;
+			}
+
+			/* saturation */
+
+			if (adjust_data->saturation != 0.0) {
+				guchar min, max, lightness;
+				double saturation;
+
+				max = MAX (MAX (values[0], values[1]), values[2]);
+				min = MIN (MIN (values[0], values[1]), values[2]);
+				lightness = (max + min) / 2;
+
+				if (adjust_data->saturation < 0)
+					saturation = tan (adjust_data->saturation * G_PI_2);
+				else
+					saturation = adjust_data->saturation;
+
+				values[0] = interpolate_value (values[0], lightness, saturation);
+				values[1] = interpolate_value (values[1], lightness, saturation);
+				values[2] = interpolate_value (values[2], lightness, saturation);
+			}
+
+			CAIRO_SET_RGBA (p_destination, values[0], values[1], values[2], values[3]);
+
+			p_source += 4;
+			p_destination += 4;
 		}
-
-		pixop->dest_pixel[channel] = v;
+		p_source_line += source_stride;
+		p_destination_line += destination_stride;
 	}
 
-	/* saturation */
+	terminated = TRUE;
+	gth_async_task_set_data (task, &terminated, NULL, NULL);
 
-	if (data->saturation != 0.0) {
-		guchar min, max, lightness;
-		double saturation;
-
-		max = MAX (pixop->dest_pixel[RED_PIX], pixop->dest_pixel[GREEN_PIX]);
-		max = MAX (max, pixop->dest_pixel[BLUE_PIX]);
-		min = MIN (pixop->dest_pixel[RED_PIX], pixop->dest_pixel[GREEN_PIX]);
-		min = MIN (min, pixop->dest_pixel[BLUE_PIX]);
-		lightness = (max + min) / 2;
-
-		if (data->saturation < 0)
-			saturation = tan (data->saturation * G_PI_2);
-		else
-			saturation = data->saturation;
-
-		pixop->dest_pixel[RED_PIX] = interpolate_value (pixop->dest_pixel[RED_PIX], lightness, saturation);
-		pixop->dest_pixel[GREEN_PIX] = interpolate_value (pixop->dest_pixel[GREEN_PIX], lightness, saturation);
-		pixop->dest_pixel[BLUE_PIX] = interpolate_value (pixop->dest_pixel[BLUE_PIX], lightness, saturation);
-	}
+	return NULL;
 }
 
 
 static void
-adjust_colors_release (GthPixbufTask *pixop,
-		       GError        *error)
+adjust_colors_after (GthAsyncTask *task,
+		     GError       *error,
+		     gpointer      user_data)
 {
-	AdjustData *data = pixop->data;
+	AdjustData *adjust_data = user_data;
+
+	if (error == NULL) {
+		GthFileToolAdjustColors *self = adjust_data->self;
+
+		cairo_surface_destroy (self->priv->destination);
+		self->priv->destination = cairo_surface_reference (adjust_data->destination);
+
+		gth_image_viewer_page_set_image (GTH_IMAGE_VIEWER_PAGE (adjust_data->viewer_page), self->priv->destination, FALSE);
+		gth_histogram_calculate_for_image (self->priv->histogram, self->priv->destination);
+	}
 
-	pixbuf_cache_free (data->cache);
+	pixbuf_cache_free (adjust_data->cache);
 }
 
 
 static void
-adjust_colors_destroy_data (gpointer user_data)
+adjust_data_free (gpointer user_data)
 {
-	AdjustData *data = user_data;
+	AdjustData *adjust_data = user_data;
 
-	g_object_unref (data->viewer_page);
-	g_free (data);
+	cairo_surface_destroy (adjust_data->destination);
+	cairo_surface_destroy (adjust_data->source);
+	g_object_unref (adjust_data->viewer_page);
+	g_free (adjust_data);
 }
 
 
@@ -203,16 +265,18 @@ gth_file_tool_adjust_colors_update_sensitivity (GthFileTool *base)
 
 
 static void
-ok_button_clicked_cb (GtkButton               *button,
-		      GthFileToolAdjustColors *self)
+ok_button_clicked_cb (GtkButton *button,
+		      gpointer   user_data)
 {
-	if (self->priv->dest_pixbuf != NULL) {
+	GthFileToolAdjustColors *self = user_data;
+
+	if (self->priv->destination != NULL) {
 		GtkWidget *window;
 		GtkWidget *viewer_page;
 
 		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, TRUE);
+		gth_image_viewer_page_set_image (GTH_IMAGE_VIEWER_PAGE (viewer_page), self->priv->destination, TRUE);
 	}
 
 	gth_file_tool_hide_options (GTH_FILE_TOOL (self));
@@ -220,11 +284,12 @@ ok_button_clicked_cb (GtkButton               *button,
 
 
 static void
-cancel_button_clicked_cb (GtkButton               *button,
-			  GthFileToolAdjustColors *self)
+cancel_button_clicked_cb (GtkButton *button,
+			  gpointer   user_data)
 {
-	GtkWidget *window;
-	GtkWidget *viewer_page;
+	GthFileToolAdjustColors *self = user_data;
+	GtkWidget               *window;
+	GtkWidget               *viewer_page;
 
 	if (self->priv->apply_event != 0) {
 		g_source_remove (self->priv->apply_event);
@@ -240,9 +305,11 @@ cancel_button_clicked_cb (GtkButton               *button,
 
 
 static void
-reset_button_clicked_cb (GtkButton               *button,
-			 GthFileToolAdjustColors *self)
+reset_button_clicked_cb (GtkButton *button,
+		  	 gpointer   user_data)
 {
+	GthFileToolAdjustColors *self = user_data;
+
 	gtk_adjustment_set_value (self->priv->gamma_adj, 0.0);
 	gtk_adjustment_set_value (self->priv->brightness_adj, 0.0);
 	gtk_adjustment_set_value (self->priv->contrast_adj, 0.0);
@@ -253,74 +320,41 @@ reset_button_clicked_cb (GtkButton               *button,
 }
 
 
-static void
-task_completed_cb (GthTask                 *task,
-		   GError                  *error,
-		   GthFileToolAdjustColors *self)
-{
-	if (self->priv->pixbuf_task == task)
-		self->priv->pixbuf_task = NULL;
-
-	if (error == NULL) {
-		GtkWidget *window;
-		GtkWidget *viewer_page;
-
-		_g_object_unref (self->priv->dest_pixbuf);
-		self->priv->dest_pixbuf = g_object_ref (GTH_PIXBUF_TASK (task)->dest);
-
-		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_for_pixbuf (self->priv->histogram, self->priv->dest_pixbuf);
-	}
-
-	g_object_unref (task);
-}
-
-
 static gboolean
 apply_cb (gpointer user_data)
 {
 	GthFileToolAdjustColors *self = user_data;
 	GtkWidget               *window;
-	AdjustData              *data;
+	AdjustData              *adjust_data;
 
 	if (self->priv->apply_event != 0) {
 		g_source_remove (self->priv->apply_event);
 		self->priv->apply_event = 0;
 	}
 
-	if (self->priv->pixbuf_task != NULL)
-		gth_task_cancel (self->priv->pixbuf_task);
+	if (self->priv->image_task != NULL)
+		gth_task_cancel (self->priv->image_task);
 
 	window = gth_file_tool_get_window (GTH_FILE_TOOL (self));
 
-	data = g_new0 (AdjustData, 1);
-	data->viewer_page = g_object_ref (gth_browser_get_viewer_page (GTH_BROWSER (window)));
-
-	data->gamma = pow (10, - (gtk_adjustment_get_value (self->priv->gamma_adj) / 100.0));
-	data->brightness = gtk_adjustment_get_value (self->priv->brightness_adj) / 100.0 * -1.0;
-	data->contrast = gtk_adjustment_get_value (self->priv->contrast_adj) / 100.0 * -1.0;
-	data->saturation = gtk_adjustment_get_value (self->priv->saturation_adj) / 100.0 * -1.0;
-	data->color_level[0] = gtk_adjustment_get_value (self->priv->cyan_red_adj);
-	data->color_level[1] = gtk_adjustment_get_value (self->priv->magenta_green_adj);
-	data->color_level[2] = gtk_adjustment_get_value (self->priv->yellow_blue_adj);
-
-	self->priv->pixbuf_task = gth_pixbuf_task_new (_("Applying changes"),
-						       FALSE,
-						       adjust_colors_init,
-						       adjust_colors_step,
-						       adjust_colors_release,
-						       data,
-						       adjust_colors_destroy_data);
-	gth_pixbuf_task_set_source (GTH_PIXBUF_TASK (self->priv->pixbuf_task),
-				    self->priv->src_pixbuf);
-	g_signal_connect (self->priv->pixbuf_task,
-			  "completed",
-			  G_CALLBACK (task_completed_cb),
-			  self);
-
-	gth_browser_exec_task (GTH_BROWSER (window), self->priv->pixbuf_task, FALSE);
+	adjust_data = g_new0 (AdjustData, 1);
+	adjust_data->self = self;
+	adjust_data->viewer_page = g_object_ref (gth_browser_get_viewer_page (GTH_BROWSER (window)));
+	adjust_data->source = cairo_surface_reference (self->priv->source);
+	adjust_data->gamma = pow (10, - (gtk_adjustment_get_value (self->priv->gamma_adj) / 100.0));
+	adjust_data->brightness = gtk_adjustment_get_value (self->priv->brightness_adj) / 100.0 * -1.0;
+	adjust_data->contrast = gtk_adjustment_get_value (self->priv->contrast_adj) / 100.0 * -1.0;
+	adjust_data->saturation = gtk_adjustment_get_value (self->priv->saturation_adj) / 100.0 * -1.0;
+	adjust_data->color_level[0] = gtk_adjustment_get_value (self->priv->cyan_red_adj);
+	adjust_data->color_level[1] = gtk_adjustment_get_value (self->priv->magenta_green_adj);
+	adjust_data->color_level[2] = gtk_adjustment_get_value (self->priv->yellow_blue_adj);
+
+	self->priv->image_task = gth_async_task_new (adjust_colors_before,
+						      adjust_colors_exec,
+						      adjust_colors_after,
+						      adjust_data,
+						      adjust_data_free);
+	gth_browser_exec_task (GTH_BROWSER (window), self->priv->image_task, FALSE);
 
 	return FALSE;
 }
@@ -354,15 +388,15 @@ gth_file_tool_adjust_colors_get_options (GthFileTool *base)
 	if (! GTH_IS_IMAGE_VIEWER_PAGE (viewer_page))
 		return NULL;
 
-	_g_object_unref (self->priv->src_pixbuf);
-	_g_object_unref (self->priv->dest_pixbuf);
+	cairo_surface_destroy (self->priv->source);
+	cairo_surface_destroy (self->priv->destination);
 
 	viewer = gth_image_viewer_page_get_image_viewer (GTH_IMAGE_VIEWER_PAGE (viewer_page));
-	self->priv->src_pixbuf = gth_image_viewer_get_current_pixbuf (GTH_IMAGE_VIEWER (viewer));
-	if (self->priv->src_pixbuf == NULL)
+	self->priv->source = cairo_surface_reference (gth_image_viewer_get_current_image (GTH_IMAGE_VIEWER (viewer)));
+	if (self->priv->source == NULL)
 		return NULL;
 
-	self->priv->dest_pixbuf = NULL;
+	self->priv->destination = NULL;
 
 	self->priv->builder = _gtk_builder_new_from_file ("adjust-colors-options.ui", "file_tools");
 	options = _gtk_builder_get_widget (self->priv->builder, "options");
@@ -435,7 +469,7 @@ gth_file_tool_adjust_colors_get_options (GthFileTool *base)
 			  G_CALLBACK (value_changed_cb),
 			  self);
 
-	gth_histogram_calculate_for_pixbuf (self->priv->histogram, self->priv->src_pixbuf);
+	gth_histogram_calculate_for_image (self->priv->histogram, self->priv->source);
 
 	return options;
 }
@@ -453,11 +487,11 @@ gth_file_tool_adjust_colors_destroy_options (GthFileTool *base)
 		self->priv->apply_event = 0;
 	}
 
-	_g_object_unref (self->priv->src_pixbuf);
-	_g_object_unref (self->priv->dest_pixbuf);
+	cairo_surface_destroy (self->priv->source);
+	cairo_surface_destroy (self->priv->destination);
 	_g_object_unref (self->priv->builder);
-	self->priv->src_pixbuf = NULL;
-	self->priv->dest_pixbuf = NULL;
+	self->priv->source = NULL;
+	self->priv->destination = NULL;
 	self->priv->builder = NULL;
 }
 
@@ -490,8 +524,8 @@ gth_file_tool_adjust_colors_finalize (GObject *object)
 
 	self = (GthFileToolAdjustColors *) object;
 
-	_g_object_unref (self->priv->src_pixbuf);
-	_g_object_unref (self->priv->dest_pixbuf);
+	cairo_surface_destroy (self->priv->source);
+	cairo_surface_destroy (self->priv->destination);
 	_g_object_unref (self->priv->builder);
 	_g_object_unref (self->priv->histogram);
 
diff --git a/gthumb/cairo-utils.c b/gthumb/cairo-utils.c
index 98c8e91..575f9ae 100644
--- a/gthumb/cairo-utils.c
+++ b/gthumb/cairo-utils.c
@@ -25,6 +25,9 @@
 #include "cairo-utils.h"
 
 
+const unsigned char cairo_channel[4] = { CAIRO_RED, CAIRO_GREEN, CAIRO_BLUE, CAIRO_ALPHA };
+
+
 typedef struct {
 	gboolean has_alpha;
 } cairo_surface_metadata_t;
diff --git a/gthumb/cairo-utils.h b/gthumb/cairo-utils.h
index d4c38ca..b97b813 100644
--- a/gthumb/cairo-utils.h
+++ b/gthumb/cairo-utils.h
@@ -115,6 +115,10 @@ typedef struct {
 	guchar a;
 } cairo_color_255_t;
 
+
+extern const unsigned char cairo_channel[4];
+
+
 /* colors */
 
 void               _gdk_color_to_cairo_color                (GdkColor          *g_color,
diff --git a/gthumb/gth-histogram.c b/gthumb/gth-histogram.c
index c107d6c..220a483 100644
--- a/gthumb/gth-histogram.c
+++ b/gthumb/gth-histogram.c
@@ -255,10 +255,7 @@ gth_histogram_calculate_for_image (GthHistogram    *self,
 		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);
+			CAIRO_GET_RGBA (pixel, red, green, blue, alpha);
 
 			/* count values for each RGB channel */
 



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