[gthumb] rotate image: misc changes
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gthumb] rotate image: misc changes
- Date: Tue, 17 May 2011 22:10:37 +0000 (UTC)
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]