[gthumb] rotate image: misc changes



commit 74c798d259ce01f831736c0d58ebe7af81db1c0a
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Mon May 16 19:14:25 2011 +0200

    rotate image: misc changes
    
    *) moved the code to get an high quality image in gth_image_rotator_get_result
    *) and fixed rotation of images with a transparency

 extensions/file_tools/cairo-rotate.c         |   63 +++++++++++---
 extensions/file_tools/cairo-rotate.h         |    2 +-
 extensions/file_tools/gth-file-tool-rotate.c |  118 ++++++--------------------
 extensions/file_tools/gth-image-rotator.c    |   62 +++++++++++++-
 extensions/file_tools/gth-image-rotator.h    |    3 +-
 5 files changed, 137 insertions(+), 111 deletions(-)
---
diff --git a/extensions/file_tools/cairo-rotate.c b/extensions/file_tools/cairo-rotate.c
index 7848548..bb78f5b 100644
--- a/extensions/file_tools/cairo-rotate.c
+++ b/extensions/file_tools/cairo-rotate.c
@@ -188,6 +188,7 @@ rotate (cairo_surface_t *image,
 	guchar           b0,
 	guchar           a0)
 {
+	cairo_surface_t *image_with_background;
 	cairo_surface_t *rotated;
 	double           angle_rad;
 	double           cos_angle, sin_angle;
@@ -218,22 +219,53 @@ rotate (cairo_surface_t *image,
 	new_width  = ROUND (      cos_angle  * src_width + fabs(sin_angle) * src_height);
 	new_height = ROUND (fabs (sin_angle) * src_width +      cos_angle  * src_height);
 
+	if (a0 == 0xff) {
+		/* pre-multiply the background color */
+
+		image_with_background = _cairo_image_surface_copy (image);
+		p_src = cairo_image_surface_get_data (image);
+		p_new = cairo_image_surface_get_data (image_with_background);
+		src_rowstride = cairo_image_surface_get_stride (image);
+		new_rowstride = cairo_image_surface_get_stride (image_with_background);
+
+		cairo_surface_flush (image_with_background);
+		for (yi = 0; yi < src_height; yi++) {
+			p_src2 = p_src;
+			p_new2 = p_new;
+			for (xi = 0; xi < src_width; xi++) {
+				a = p_src2[CAIRO_ALPHA];
+				r = p_src2[CAIRO_RED] + _cairo_multiply_alpha (r0, 0xff - a);
+				g = p_src2[CAIRO_GREEN] + _cairo_multiply_alpha (g0, 0xff - a);
+				b = p_src2[CAIRO_BLUE] + _cairo_multiply_alpha (b0, 0xff - a);
+				pixel = CAIRO_RGBA_TO_UINT32 (r, g, b, 0xff);
+				memcpy (p_new2, &pixel, sizeof (guint32));
+
+				p_new2 += 4;
+				p_src2 += 4;
+			}
+			p_src += src_rowstride;
+			p_new += new_rowstride;
+		}
+		cairo_surface_mark_dirty (image_with_background);
+	}
+	else
+		image_with_background = cairo_surface_reference (image);
+
+	/* create the rotated image */
+
 	rotated = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, new_width, new_height);
 
-	p_src = cairo_image_surface_get_data (image);
+	p_src = cairo_image_surface_get_data (image_with_background);
 	p_new = cairo_image_surface_get_data (rotated);
-	src_rowstride = cairo_image_surface_get_stride (image);
+	src_rowstride = cairo_image_surface_get_stride (image_with_background);
 	new_rowstride = cairo_image_surface_get_stride (rotated);
 
 	cairo_surface_flush (rotated);
-
 	for (yi = 0; yi < new_height; yi++) {
 		p_new2 = p_new;
-
 		y = yi - new_height / 2.0;
 
 		for (xi = 0; xi < new_width; xi++) {
-
 			x = xi - new_width / 2.0;
 
 			x2 = cos_angle * x - sin_angle * y + src_width  / 2.0;
@@ -270,7 +302,7 @@ rotate (cairo_surface_t *image,
 				x2min = ROUND (x2);
 				y2min = ROUND (y2);
 
-				GET_VALUES (p_new2[RED_PIX], p_new2[GREEN_PIX], p_new2[BLUE_PIX], p_new2[ALPHA_PIX], x2min, y2min);
+				GET_VALUES (p_new2[CAIRO_RED], p_new2[CAIRO_GREEN], p_new2[CAIRO_BLUE], p_new2[CAIRO_ALPHA], x2min, y2min);
 			}
 
 			p_new2 += 4;
@@ -278,18 +310,19 @@ rotate (cairo_surface_t *image,
 
 		p_new += new_rowstride;
 	}
-
 	cairo_surface_mark_dirty (rotated);
 
+	cairo_surface_destroy (image_with_background);
+
 	return rotated;
 }
 
 
 cairo_surface_t *
-_cairo_image_surface_rotate (cairo_surface_t   *image,
-		    	     double             angle,
-		    	     gboolean           high_quality,
-		    	     cairo_color_255_t *background_color)
+_cairo_image_surface_rotate (cairo_surface_t *image,
+		    	     double           angle,
+		    	     gboolean         high_quality,
+		    	     cairo_color_t   *background_color)
 {
 	cairo_surface_t *rotated;
 	cairo_surface_t *tmp = NULL;
@@ -307,10 +340,10 @@ _cairo_image_surface_rotate (cairo_surface_t   *image,
 		rotated = rotate (image,
 				  -angle,
 				  high_quality,
-				  background_color->r,
-				  background_color->g,
-				  background_color->b,
-				  background_color->a);
+				  background_color->r * 255.0,
+				  background_color->g * 255.0,
+				  background_color->b * 255.0,
+				  background_color->a * 255.0);
 	else
 		rotated = cairo_surface_reference (image);
 
diff --git a/extensions/file_tools/cairo-rotate.h b/extensions/file_tools/cairo-rotate.h
index dbf2030..189ee49 100644
--- a/extensions/file_tools/cairo-rotate.h
+++ b/extensions/file_tools/cairo-rotate.h
@@ -43,7 +43,7 @@ double             _cairo_image_surface_rotate_get_align_angle         (gboolean
 cairo_surface_t *  _cairo_image_surface_rotate                         (cairo_surface_t   *image,
 		    	     	     	     	     	     	        double             angle,
 		    	     	     	     	     	     	        gboolean           high_quality,
-		    	     	     	     	     	     	        cairo_color_255_t *background_color);
+		    	     	     	     	     	     	        cairo_color_t     *background_color);
 
 G_END_DECLS
 
diff --git a/extensions/file_tools/gth-file-tool-rotate.c b/extensions/file_tools/gth-file-tool-rotate.c
index c94a676..dff54a4 100644
--- a/extensions/file_tools/gth-file-tool-rotate.c
+++ b/extensions/file_tools/gth-file-tool-rotate.c
@@ -24,7 +24,6 @@
 #include <gthumb.h>
 #include <extensions/image_viewer/gth-image-viewer-page.h>
 #include "enum-types.h"
-#include "cairo-rotate.h"
 #include "gth-file-tool-rotate.h"
 #include "gth-image-rotator.h"
 
@@ -215,48 +214,32 @@ static gboolean
 apply_cb (gpointer user_data)
 {
 	GthFileToolRotate *self = user_data;
-	GtkWidget         *window;
-	GtkWidget         *viewer_page;
 	double             rotation_angle;
-	GdkColor           background_color;
-	guchar             r0, g0, b0, a0;
+	cairo_color_t      background_color;
 
 	if (self->priv->apply_event != 0) {
 		g_source_remove (self->priv->apply_event);
 		self->priv->apply_event = 0;
 	}
 
-	window = gth_file_tool_get_window (GTH_FILE_TOOL (self));
-	viewer_page = gth_browser_get_viewer_page (GTH_BROWSER (window));
-
-	rotation_angle = gtk_adjustment_get_value (self->priv->rotation_angle_adj);
-
-	if (! gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->priv->background_transparent))) {
-
-		gtk_color_button_get_color (GTK_COLOR_BUTTON (self->priv->background_colorbutton), &background_color);
-
-		r0 = background_color.red >> 8;
-		g0 = background_color.green >> 8;
-		b0 = background_color.blue >> 8;
-
-		if (self->priv->has_alpha)
-			a0 = gtk_color_button_get_alpha (GTK_COLOR_BUTTON (self->priv->background_colorbutton)) >> 8;
-		else
-			a0 = 0;
+	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->priv->background_transparent))) {
+		background_color.r = 0.0;
+		background_color.g = 0.0;
+		background_color.b = 0.0;
+		background_color.a = 0.0;
 	}
 	else {
-		r0 = 0;
-		g0 = 0;
-		b0 = 0;
-		a0 = 0;
-	}
+		GdkColor color;
 
-	/* FIXME
-	_g_object_unref (self->priv->rotate_pixbuf);
-	self->priv->rotate_pixbuf = _gdk_pixbuf_rotate (self->priv->src_pixbuf, rotation_angle, TRUE, r0, g0, b0, a0);
-	gth_image_viewer_page_set_pixbuf (GTH_IMAGE_VIEWER_PAGE (viewer_page), self->priv->rotate_pixbuf, FALSE);
-	*/
+		gtk_color_button_get_color (GTK_COLOR_BUTTON (self->priv->background_colorbutton), &color);
+		background_color.r = (double) color.red / 65535;
+		background_color.g = (double) color.green / 65535;
+		background_color.b = (double) color.blue / 65535;
+		background_color.a = 1.0;
+	}
+	gth_image_rotator_set_background (GTH_IMAGE_ROTATOR (self->priv->rotator), &background_color);
 
+	rotation_angle = gtk_adjustment_get_value (self->priv->rotation_angle_adj);
 	gth_image_rotator_set_angle (GTH_IMAGE_ROTATOR (self->priv->rotator), rotation_angle);
 
 	update_crop_parameters (self);
@@ -313,71 +296,18 @@ static void
 apply_button_clicked_cb (GtkButton         *button,
 			 GthFileToolRotate *self)
 {
-	GtkWidget         *window;
-	GtkWidget         *viewer_page;
-	double             rotation_angle;
-	GdkColor           color;
-	cairo_color_255_t  background_color;
-	cairo_surface_t   *rotated;
-	cairo_surface_t   *image;
-
-#if 0
-	if (self->priv->rotate_pixbuf != self->priv->src_pixbuf) {
-		GtkWidget *window;
-		GtkWidget *viewer_page;
-		GdkPixbuf *result;
-
-		window = gth_file_tool_get_window (GTH_FILE_TOOL (self));
-		viewer_page = gth_browser_get_viewer_page (GTH_BROWSER (window));
-
-		if (self->priv->crop_enabled
-		    && ((self->priv->crop_region.x != 0)
-		        || (self->priv->crop_region.y != 0)
-		        || (self->priv->crop_region.width != gdk_pixbuf_get_width (self->priv->rotate_pixbuf))
-		        || (self->priv->crop_region.height != gdk_pixbuf_get_height (self->priv->rotate_pixbuf))))
-		{
-			result = gdk_pixbuf_new_subpixbuf (self->priv->rotate_pixbuf,
-							   self->priv->crop_region.x,
-							   self->priv->crop_region.y,
-							   self->priv->crop_region.width,
-							   self->priv->crop_region.height);
-		}
-		else
-			result = g_object_ref (self->priv->rotate_pixbuf);
+	cairo_surface_t  *image;
+	GtkWidget        *window;
+	GtkWidget        *viewer_page;
 
-		gth_image_viewer_page_set_pixbuf (GTH_IMAGE_VIEWER_PAGE (viewer_page), result, TRUE);
-
-		g_object_unref (result);
-	}
-#endif
-
-	rotation_angle = gtk_adjustment_get_value (self->priv->rotation_angle_adj);
-
-	gtk_color_button_get_color (GTK_COLOR_BUTTON (self->priv->background_colorbutton), &color);
-	background_color.r = color.red;
-	background_color.g = color.green;
-	background_color.b = color.blue;
-	background_color.a = gtk_color_button_get_alpha (GTK_COLOR_BUTTON (self->priv->background_colorbutton));
-
-	rotated = _cairo_image_surface_rotate (self->priv->image, rotation_angle, TRUE, &background_color);
-	if (self->priv->crop_enabled)
-		image = _cairo_image_surface_copy_subsurface (rotated,
-							      self->priv->crop_region.x,
-							      self->priv->crop_region.y,
-							      self->priv->crop_region.width,
-							      self->priv->crop_region.height);
-	else
-		image = cairo_surface_reference (rotated);
-	/*image = gth_image_rotator_get_result (GTH_IMAGE_ROTATOR (self->priv->rotator)); FIXME*/
+	image = gth_image_rotator_get_result (GTH_IMAGE_ROTATOR (self->priv->rotator), TRUE);
 
 	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_image (GTH_IMAGE_VIEWER_PAGE (viewer_page), image, TRUE);
+	gth_file_tool_hide_options (GTH_FILE_TOOL (self));
 
 	cairo_surface_destroy (image);
-	cairo_surface_destroy (rotated);
-
-	gth_file_tool_hide_options (GTH_FILE_TOOL (self));
 }
 
 
@@ -451,7 +381,6 @@ background_color_changed_cb (GtkAdjustment     *adj,
 		             GthFileToolRotate *self)
 {
 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->priv->background_transparent), FALSE);
-
 	value_changed_cb (adj, self);
 }
 
@@ -490,6 +419,7 @@ gth_file_tool_rotate_get_options (GthFileTool *base)
 	GtkWidget         *window;
 	GtkWidget         *viewer_page;
 	GtkWidget         *viewer;
+	cairo_color_t      background_color;
 
 	self = (GthFileToolRotate *) base;
 
@@ -561,6 +491,12 @@ gth_file_tool_rotate_get_options (GthFileTool *base)
 	gth_image_rotator_set_center (GTH_IMAGE_ROTATOR (self->priv->rotator),
 				      cairo_image_surface_get_width (self->priv->image) / 2,
 				      cairo_image_surface_get_height (self->priv->image) / 2);
+
+	background_color.r = 0.0;
+	background_color.g = 0.0;
+	background_color.b = 0.0;
+	background_color.a = 0.0;
+	gth_image_rotator_set_background (GTH_IMAGE_ROTATOR (self->priv->rotator), &background_color);
 	gth_image_viewer_set_tool (GTH_IMAGE_VIEWER (viewer), self->priv->rotator);
 	gth_image_viewer_set_zoom_enabled (GTH_IMAGE_VIEWER (viewer), FALSE);
 	gth_viewer_page_update_sensitivity (GTH_VIEWER_PAGE (viewer_page));
diff --git a/extensions/file_tools/gth-image-rotator.c b/extensions/file_tools/gth-image-rotator.c
index 950ee20..50c76ac 100644
--- a/extensions/file_tools/gth-image-rotator.c
+++ b/extensions/file_tools/gth-image-rotator.c
@@ -22,6 +22,8 @@
 #include <config.h>
 #include <stdlib.h>
 #include <math.h>
+#include <gthumb.h>
+#include "cairo-rotate.h"
 #include "gth-image-rotator.h"
 
 
@@ -313,7 +315,7 @@ paint_grid (GthImageRotator *self,
 	cairo_scale (cr, self->priv->preview_zoom, self->priv->preview_zoom);
 
 #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 9, 2)
-	/* cairo_set_operator (cr, CAIRO_OPERATOR_DIFFERENCE); */
+	/*cairo_set_operator (cr, CAIRO_OPERATOR_DIFFERENCE);*/
 #endif
 	grid = self->priv->crop_region;
 	grid.x += self->priv->clip_area.x / self->priv->preview_zoom;
@@ -667,8 +669,8 @@ gth_image_rotator_set_background (GthImageRotator *self,
 }
 
 
-cairo_surface_t *
-gth_image_rotator_get_result (GthImageRotator *self)
+static cairo_surface_t *
+gth_image_rotator_get_result_fast (GthImageRotator *self)
 {
 	double           tx, ty;
 	cairo_matrix_t   matrix;
@@ -737,3 +739,57 @@ gth_image_rotator_get_result (GthImageRotator *self)
 
 	return output;
 }
+
+
+static cairo_surface_t *
+gth_image_rotator_get_result_high_quality (GthImageRotator *self)
+{
+	cairo_surface_t *rotated;
+	cairo_surface_t *result;
+
+	rotated = _cairo_image_surface_rotate (gth_image_viewer_get_current_image (GTH_IMAGE_VIEWER (self->priv->viewer)),
+					       self->priv->angle / G_PI * 180.0,
+					       TRUE,
+					       &self->priv->background_color);
+
+	switch (self->priv->resize) {
+	case GTH_TRANSFORM_RESIZE_BOUNDING_BOX:
+		self->priv->crop_region.x = 0;
+		self->priv->crop_region.y = 0;
+		self->priv->crop_region.width = cairo_image_surface_get_width (rotated);
+		self->priv->crop_region.height = cairo_image_surface_get_height (rotated);
+		break;
+
+	case GTH_TRANSFORM_RESIZE_CLIP:
+		self->priv->crop_region.x = (cairo_image_surface_get_width (rotated) - self->priv->original_width) / 2;
+		self->priv->crop_region.y = (cairo_image_surface_get_height (rotated) - self->priv->original_height) / 2;
+		self->priv->crop_region.width = self->priv->original_width;
+		self->priv->crop_region.height = self->priv->original_height;
+		break;
+
+	case GTH_TRANSFORM_RESIZE_CROP:
+		/* set by the user */
+		break;
+	}
+
+	result = _cairo_image_surface_copy_subsurface (rotated,
+						       self->priv->crop_region.x,
+						       self->priv->crop_region.y,
+						       self->priv->crop_region.width,
+						       self->priv->crop_region.height);
+
+	cairo_surface_destroy (rotated);
+
+	return result;
+}
+
+
+cairo_surface_t *
+gth_image_rotator_get_result (GthImageRotator *self,
+			      gboolean         high_quality)
+{
+	if (high_quality)
+		return gth_image_rotator_get_result_high_quality (self);
+	else
+		return gth_image_rotator_get_result_fast (self);
+}
diff --git a/extensions/file_tools/gth-image-rotator.h b/extensions/file_tools/gth-image-rotator.h
index 50a1ec3..14ce8f3 100644
--- a/extensions/file_tools/gth-image-rotator.h
+++ b/extensions/file_tools/gth-image-rotator.h
@@ -81,7 +81,8 @@ void                  gth_image_rotator_set_crop_region (GthImageRotator       *
 							 GdkRectangle          *region);
 void                  gth_image_rotator_set_background  (GthImageRotator       *self,
 							 cairo_color_t         *color);
-cairo_surface_t *     gth_image_rotator_get_result      (GthImageRotator       *self);
+cairo_surface_t *     gth_image_rotator_get_result      (GthImageRotator       *self,
+							 gboolean               high_quality);
 
 G_END_DECLS
 



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