[gthumb: 32/129] flip, mirror, rotate left and right: use the cairo_surface instead of a GdkPixbuf
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gthumb: 32/129] flip, mirror, rotate left and right: use the cairo_surface instead of a GdkPixbuf
- Date: Wed, 27 Apr 2011 20:53:04 +0000 (UTC)
commit 9c5689aac673fbae964cadc577b31a9dcafc9b26
Author: Paolo Bacchilega <paobac src gnome org>
Date: Sat Apr 16 14:14:42 2011 +0200
flip, mirror, rotate left and right: use the cairo_surface instead of a GdkPixbuf
extensions/file_tools/gth-file-tool-flip.c | 21 +-
extensions/file_tools/gth-file-tool-mirror.c | 21 +-
extensions/file_tools/gth-file-tool-rotate-left.c | 21 +-
extensions/file_tools/gth-file-tool-rotate-right.c | 21 +-
gthumb/cairo-utils.c | 252 ++++++++++++++++++++
gthumb/cairo-utils.h | 9 +
6 files changed, 301 insertions(+), 44 deletions(-)
---
diff --git a/extensions/file_tools/gth-file-tool-flip.c b/extensions/file_tools/gth-file-tool-flip.c
index b2cb0b1..c74e3d3 100644
--- a/extensions/file_tools/gth-file-tool-flip.c
+++ b/extensions/file_tools/gth-file-tool-flip.c
@@ -29,11 +29,11 @@
static void
gth_file_tool_flip_activate (GthFileTool *base)
{
- GtkWidget *window;
- GtkWidget *viewer_page;
- GtkWidget *viewer;
- GdkPixbuf *src_pixbuf;
- GdkPixbuf *dest_pixbuf;
+ GtkWidget *window;
+ GtkWidget *viewer_page;
+ GtkWidget *viewer;
+ cairo_surface_t *old_image;
+ cairo_surface_t *new_image;
window = gth_file_tool_get_window (base);
viewer_page = gth_browser_get_viewer_page (GTH_BROWSER (window));
@@ -41,15 +41,14 @@ gth_file_tool_flip_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)); /* FIXME: use the cairo_surface directly */
- if (src_pixbuf == NULL)
+ old_image = gth_image_viewer_get_current_image (GTH_IMAGE_VIEWER (viewer));
+ if (old_image == NULL)
return;
- dest_pixbuf = _gdk_pixbuf_transform (src_pixbuf, GTH_TRANSFORM_FLIP_V);
- gth_image_viewer_page_set_pixbuf (GTH_IMAGE_VIEWER_PAGE (viewer_page), dest_pixbuf, TRUE);
+ new_image = _cairo_image_surface_transform (old_image, GTH_TRANSFORM_FLIP_V);
+ gth_image_viewer_page_set_image (GTH_IMAGE_VIEWER_PAGE (viewer_page), new_image, TRUE);
- g_object_unref (dest_pixbuf);
- g_object_unref (src_pixbuf);
+ cairo_surface_destroy (new_image);
}
diff --git a/extensions/file_tools/gth-file-tool-mirror.c b/extensions/file_tools/gth-file-tool-mirror.c
index 454caa5..fa0fe44 100644
--- a/extensions/file_tools/gth-file-tool-mirror.c
+++ b/extensions/file_tools/gth-file-tool-mirror.c
@@ -29,11 +29,11 @@
static void
gth_file_tool_mirror_activate (GthFileTool *base)
{
- GtkWidget *window;
- GtkWidget *viewer_page;
- GtkWidget *viewer;
- GdkPixbuf *src_pixbuf;
- GdkPixbuf *dest_pixbuf;
+ GtkWidget *window;
+ GtkWidget *viewer_page;
+ GtkWidget *viewer;
+ cairo_surface_t *old_image;
+ cairo_surface_t *new_image;
window = gth_file_tool_get_window (base);
viewer_page = gth_browser_get_viewer_page (GTH_BROWSER (window));
@@ -41,15 +41,14 @@ gth_file_tool_mirror_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)
+ old_image = gth_image_viewer_get_current_image (GTH_IMAGE_VIEWER (viewer));
+ if (old_image == NULL)
return;
- dest_pixbuf = _gdk_pixbuf_transform (src_pixbuf, GTH_TRANSFORM_FLIP_H);
- gth_image_viewer_page_set_pixbuf (GTH_IMAGE_VIEWER_PAGE (viewer_page), dest_pixbuf, TRUE);
+ new_image = _cairo_image_surface_transform (old_image, GTH_TRANSFORM_FLIP_H);
+ gth_image_viewer_page_set_image (GTH_IMAGE_VIEWER_PAGE (viewer_page), new_image, TRUE);
- g_object_unref (dest_pixbuf);
- g_object_unref (src_pixbuf);
+ cairo_surface_destroy (new_image);
}
diff --git a/extensions/file_tools/gth-file-tool-rotate-left.c b/extensions/file_tools/gth-file-tool-rotate-left.c
index 596fd8f..517b6d8 100644
--- a/extensions/file_tools/gth-file-tool-rotate-left.c
+++ b/extensions/file_tools/gth-file-tool-rotate-left.c
@@ -29,11 +29,11 @@
static void
gth_file_tool_rotate_left_activate (GthFileTool *base)
{
- GtkWidget *window;
- GtkWidget *viewer_page;
- GtkWidget *viewer;
- GdkPixbuf *src_pixbuf;
- GdkPixbuf *dest_pixbuf;
+ GtkWidget *window;
+ GtkWidget *viewer_page;
+ GtkWidget *viewer;
+ cairo_surface_t *old_image;
+ cairo_surface_t *new_image;
window = gth_file_tool_get_window (base);
viewer_page = gth_browser_get_viewer_page (GTH_BROWSER (window));
@@ -41,15 +41,14 @@ gth_file_tool_rotate_left_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)
+ old_image = gth_image_viewer_get_current_image (GTH_IMAGE_VIEWER (viewer));
+ if (old_image == NULL)
return;
- dest_pixbuf = _gdk_pixbuf_transform (src_pixbuf, GTH_TRANSFORM_ROTATE_270);
- gth_image_viewer_page_set_pixbuf (GTH_IMAGE_VIEWER_PAGE (viewer_page), dest_pixbuf, TRUE);
+ new_image = _cairo_image_surface_transform (old_image, GTH_TRANSFORM_ROTATE_270);
+ gth_image_viewer_page_set_image (GTH_IMAGE_VIEWER_PAGE (viewer_page), new_image, TRUE);
- g_object_unref (dest_pixbuf);
- g_object_unref (src_pixbuf);
+ cairo_surface_destroy (new_image);
}
diff --git a/extensions/file_tools/gth-file-tool-rotate-right.c b/extensions/file_tools/gth-file-tool-rotate-right.c
index 1e6bff6..99d71c7 100644
--- a/extensions/file_tools/gth-file-tool-rotate-right.c
+++ b/extensions/file_tools/gth-file-tool-rotate-right.c
@@ -29,11 +29,11 @@
static void
gth_file_tool_rotate_right_activate (GthFileTool *base)
{
- GtkWidget *window;
- GtkWidget *viewer_page;
- GtkWidget *viewer;
- GdkPixbuf *src_pixbuf;
- GdkPixbuf *dest_pixbuf;
+ GtkWidget *window;
+ GtkWidget *viewer_page;
+ GtkWidget *viewer;
+ cairo_surface_t *old_image;
+ cairo_surface_t *new_image;
window = gth_file_tool_get_window (base);
viewer_page = gth_browser_get_viewer_page (GTH_BROWSER (window));
@@ -41,15 +41,14 @@ gth_file_tool_rotate_right_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)
+ old_image = gth_image_viewer_get_current_image (GTH_IMAGE_VIEWER (viewer));
+ if (old_image == NULL)
return;
- dest_pixbuf = _gdk_pixbuf_transform (src_pixbuf, GTH_TRANSFORM_ROTATE_90);
- gth_image_viewer_page_set_pixbuf (GTH_IMAGE_VIEWER_PAGE (viewer_page), dest_pixbuf, TRUE);
+ new_image = _cairo_image_surface_transform (old_image, GTH_TRANSFORM_ROTATE_90);
+ gth_image_viewer_page_set_image (GTH_IMAGE_VIEWER_PAGE (viewer_page), new_image, TRUE);
- g_object_unref (dest_pixbuf);
- g_object_unref (src_pixbuf);
+ cairo_surface_destroy (new_image);
}
diff --git a/gthumb/cairo-utils.c b/gthumb/cairo-utils.c
index 04b6d07..98c8e91 100644
--- a/gthumb/cairo-utils.c
+++ b/gthumb/cairo-utils.c
@@ -21,6 +21,7 @@
#include <config.h>
#include <math.h>
+#include <string.h>
#include "cairo-utils.h"
@@ -30,6 +31,7 @@ typedef struct {
static cairo_user_data_key_t surface_metadata_key;
+static cairo_user_data_key_t surface_pixels_key;
static void
@@ -40,6 +42,13 @@ surface_metadata_free (void *data)
}
+static void
+surface_pixels_free (void *data)
+{
+ g_free (data);
+}
+
+
void
_gdk_color_to_cairo_color (GdkColor *g_color,
cairo_color_t *c_color)
@@ -87,6 +96,90 @@ _cairo_image_surface_get_has_alpha (cairo_surface_t *surface)
cairo_surface_t *
+_cairo_image_surface_copy (cairo_surface_t *surface)
+{
+ cairo_surface_t *result;
+ cairo_format_t format;
+ int width;
+ int height;
+ int stride;
+ unsigned char *pixels;
+ cairo_status_t status;
+
+ if (surface == NULL)
+ return NULL;
+
+ format = cairo_image_surface_get_format (surface);
+ width = cairo_image_surface_get_width (surface);
+ height = cairo_image_surface_get_height (surface);
+ stride = cairo_format_stride_for_width (format, width);
+ pixels = g_try_malloc (stride * height);
+ if (pixels == NULL)
+ return NULL;
+
+ result = cairo_image_surface_create_for_data (pixels, format, width, height, stride);
+ status = cairo_surface_status (result);
+ if (status != CAIRO_STATUS_SUCCESS) {
+ g_warning ("_cairo_image_surface_copy: could not create the surface: %s", cairo_status_to_string (status));
+ cairo_surface_destroy (result);
+ return NULL;
+ }
+
+ status = cairo_surface_set_user_data (result, &surface_pixels_key, pixels, surface_pixels_free);
+ if (status != CAIRO_STATUS_SUCCESS) {
+ g_warning ("_cairo_image_surface_copy: could not set the user data: %s", cairo_status_to_string (status));
+ cairo_surface_destroy (result);
+ return NULL;
+ }
+
+ return result;
+}
+
+
+cairo_surface_t *
+_cairo_image_surface_copy_subsurface (cairo_surface_t *source,
+ int src_x,
+ int src_y,
+ int width,
+ int height)
+{
+ cairo_surface_t *destination;
+ cairo_status_t status;
+ int source_stride;
+ int destination_stride;
+ unsigned char *p_source;
+ unsigned char *p_destination;
+ int row_size;
+
+ g_return_val_if_fail (source != NULL, NULL);
+ g_return_val_if_fail (src_x + width <= cairo_image_surface_get_width (source), NULL);
+ g_return_val_if_fail (src_y + height <= cairo_image_surface_get_height (source), NULL);
+
+ destination = cairo_image_surface_create (cairo_image_surface_get_format (source), width, height);
+ status = cairo_surface_status (destination);
+ if (status != CAIRO_STATUS_SUCCESS) {
+ g_warning ("_cairo_image_surface_copy_subsurface: could not create the surface: %s", cairo_status_to_string (status));
+ cairo_surface_destroy (destination);
+ return NULL;
+ }
+
+ source_stride = cairo_image_surface_get_stride (source);
+ destination_stride = cairo_image_surface_get_stride (destination);
+ p_source = cairo_image_surface_get_data (source) + (src_y * source_stride) + (src_x * 4);
+ p_destination = cairo_image_surface_get_data (destination);
+ row_size = width * 4;
+ while (height-- > 0) {
+ memcpy (p_destination, p_source, row_size);
+
+ p_source += source_stride;
+ p_destination += destination_stride;
+ }
+
+ return destination;
+}
+
+
+cairo_surface_t *
_cairo_image_surface_create_from_pixbuf (GdkPixbuf *pixbuf)
{
cairo_surface_t *surface;
@@ -184,6 +277,165 @@ _cairo_image_surface_scale_to (cairo_surface_t *surface,
}
+cairo_surface_t *
+_cairo_image_surface_transform (cairo_surface_t *source,
+ GthTransform transform)
+{
+ cairo_surface_t *destination = NULL;
+ 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;
+ int x;
+
+ if (source == NULL)
+ return NULL;
+
+ format = cairo_image_surface_get_format (source);
+ width = cairo_image_surface_get_width (source);
+ height = cairo_image_surface_get_height (source);
+ source_stride = cairo_image_surface_get_stride (source);
+
+ switch (transform) {
+ case GTH_TRANSFORM_NONE:
+ destination = _cairo_image_surface_copy (source);
+ break;
+
+ case GTH_TRANSFORM_FLIP_H:
+ destination = cairo_image_surface_create (format, width, height);
+ destination_stride = cairo_image_surface_get_stride (destination);
+ p_source_line = cairo_image_surface_get_data (source);
+ p_destination_line = cairo_image_surface_get_data (destination) + ((width - 1) * 4);
+ while (height-- > 0) {
+ p_source = p_source_line;
+ p_destination = p_destination_line;
+ for (x = 0; x < width; x++) {
+ memcpy (p_destination, p_source, 4);
+ p_source += 4;
+ p_destination -= 4;
+ }
+ p_source_line += source_stride;
+ p_destination_line += destination_stride;
+ }
+ break;
+
+ case GTH_TRANSFORM_ROTATE_180:
+ destination = cairo_image_surface_create (format, width, height);
+ destination_stride = cairo_image_surface_get_stride (destination);
+ p_source_line = cairo_image_surface_get_data (source);
+ p_destination_line = cairo_image_surface_get_data (destination) + ((height - 1) * destination_stride) + ((width - 1) * 4);
+ while (height-- > 0) {
+ p_source = p_source_line;
+ p_destination = p_destination_line;
+ for (x = 0; x < width; x++) {
+ memcpy (p_destination, p_source, 4);
+ p_source += 4;
+ p_destination -= 4;
+ }
+ p_source_line += source_stride;
+ p_destination_line -= destination_stride;
+ }
+ break;
+
+ case GTH_TRANSFORM_FLIP_V:
+ destination = cairo_image_surface_create (format, width, height);
+ destination_stride = cairo_image_surface_get_stride (destination);
+ g_return_val_if_fail (source_stride == destination_stride, NULL);
+ p_source_line = cairo_image_surface_get_data (source);
+ p_destination_line = cairo_image_surface_get_data (destination) + ((height - 1) * destination_stride);
+ while (height-- > 0) {
+ memcpy (p_destination_line, p_source_line, source_stride);
+ p_source_line += source_stride;
+ p_destination_line -= destination_stride;
+ }
+ break;
+
+ case GTH_TRANSFORM_TRANSPOSE:
+ destination = cairo_image_surface_create (format, height, width);
+ destination_stride = cairo_image_surface_get_stride (destination);
+ p_source_line = cairo_image_surface_get_data (source);
+ p_destination_line = cairo_image_surface_get_data (destination);
+ while (height-- > 0) {
+ p_source = p_source_line;
+ p_destination = p_destination_line;
+ for (x = 0; x < width; x++) {
+ memcpy (p_destination, p_source, 4);
+ p_source += 4;
+ p_destination += destination_stride;
+ }
+ p_source_line += source_stride;
+ p_destination_line += 4;
+ }
+ break;
+
+ case GTH_TRANSFORM_ROTATE_90:
+ destination = cairo_image_surface_create (format, height, width);
+ destination_stride = cairo_image_surface_get_stride (destination);
+ p_source_line = cairo_image_surface_get_data (source);
+ p_destination_line = cairo_image_surface_get_data (destination) + ((height - 1) * 4);
+ while (height-- > 0) {
+ p_source = p_source_line;
+ p_destination = p_destination_line;
+ for (x = 0; x < width; x++) {
+ memcpy (p_destination, p_source, 4);
+ p_source += 4;
+ p_destination += destination_stride;
+ }
+ p_source_line += source_stride;
+ p_destination_line -= 4;
+ }
+ break;
+
+ case GTH_TRANSFORM_TRANSVERSE:
+ destination = cairo_image_surface_create (format, height, width);
+ destination_stride = cairo_image_surface_get_stride (destination);
+ p_source_line = cairo_image_surface_get_data (source);
+ p_destination_line = cairo_image_surface_get_data (destination) + ((width - 1) * destination_stride) + ((height - 1) * 4);
+ while (height-- > 0) {
+ p_source = p_source_line;
+ p_destination = p_destination_line;
+ for (x = 0; x < width; x++) {
+ memcpy (p_destination, p_source, 4);
+ p_source += 4;
+ p_destination -= destination_stride;
+ }
+ p_source_line += source_stride;
+ p_destination_line -= 4;
+ }
+ break;
+
+ case GTH_TRANSFORM_ROTATE_270:
+ destination = cairo_image_surface_create (format, height, width);
+ destination_stride = cairo_image_surface_get_stride (destination);
+ p_source_line = cairo_image_surface_get_data (source);
+ p_destination_line = cairo_image_surface_get_data (destination) + ((width - 1) * destination_stride);
+ while (height-- > 0) {
+ p_source = p_source_line;
+ p_destination = p_destination_line;
+ for (x = 0; x < width; x++) {
+ memcpy (p_destination, p_source, 4);
+ p_source += 4;
+ p_destination -= destination_stride;
+ }
+ p_source_line += source_stride;
+ p_destination_line += 4;
+ }
+ break;
+
+ default:
+ g_warning ("_cairo_image_surface_transform: unknown transformation value %d", transform);
+ break;
+ }
+
+ return destination;
+}
+
+
void
_cairo_paint_full_gradient (cairo_surface_t *surface,
GdkColor *h_color1,
diff --git a/gthumb/cairo-utils.h b/gthumb/cairo-utils.h
index 8e8b551..a1f3d5c 100644
--- a/gthumb/cairo-utils.h
+++ b/gthumb/cairo-utils.h
@@ -26,6 +26,7 @@
#include <gdk/gdk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <cairo.h>
+#include "typedefs.h"
#if G_BYTE_ORDER == G_LITTLE_ENDIAN /* BGRA */
@@ -114,11 +115,19 @@ void _gdk_color_to_cairo_color_255 (GdkColor *
void _cairo_clear_surface (cairo_surface_t **surface);
gboolean _cairo_image_surface_get_has_alpha (cairo_surface_t *surface);
+cairo_surface_t * _cairo_image_surface_copy (cairo_surface_t *surface);
+cairo_surface_t * _cairo_image_surface_copy_subsurface (cairo_surface_t *surface,
+ int src_x,
+ int src_y,
+ int width,
+ int height);
cairo_surface_t * _cairo_image_surface_create_from_pixbuf (GdkPixbuf *pixbuf);
cairo_surface_t * _cairo_image_surface_scale_to (cairo_surface_t *surface,
int width,
int height,
cairo_filter_t filter);
+cairo_surface_t * _cairo_image_surface_transform (cairo_surface_t *surface,
+ GthTransform transform);
/* paint / draw */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]