[gthumb: 47/129] sharpen tool: operate on a cairo_surface directly instead of converting to/from a GdkPixbuf
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gthumb: 47/129] sharpen tool: operate on a cairo_surface directly instead of converting to/from a GdkPixbuf
- Date: Wed, 27 Apr 2011 20:54:20 +0000 (UTC)
commit fb42cc0e47d225f75d1aa495663cf463334ed65a
Author: Paolo Bacchilega <paobac src gnome org>
Date: Tue Apr 19 15:44:45 2011 +0200
sharpen tool: operate on a cairo_surface directly instead of converting to/from a GdkPixbuf
extensions/file_tools/Makefile.am | 4 +-
extensions/file_tools/cairo-blur.c | 271 +++++++++++++++++++
.../file_tools/{gdk-pixbuf-blur.h => cairo-blur.h} | 15 +-
extensions/file_tools/gdk-pixbuf-blur.c | 273 --------------------
.../file_tools/gth-file-tool-adjust-colors.c | 9 -
extensions/file_tools/gth-file-tool-sharpen.c | 204 +++++++++------
gthumb/cairo-utils.c | 36 +++-
gthumb/cairo-utils.h | 5 +
8 files changed, 442 insertions(+), 375 deletions(-)
---
diff --git a/extensions/file_tools/Makefile.am b/extensions/file_tools/Makefile.am
index 6625eb8..1c01abb 100644
--- a/extensions/file_tools/Makefile.am
+++ b/extensions/file_tools/Makefile.am
@@ -8,7 +8,7 @@ ENUM_TYPES = \
enum-types.c
HEADER_FILES = \
- gdk-pixbuf-blur.h \
+ cairo-blur.h \
gth-file-tool-adjust-colors.h \
gth-file-tool-crop.h \
gth-file-tool-desaturate.h \
@@ -56,7 +56,7 @@ libfile_tools_la_SOURCES = \
$(HEADER_FILES) \
callbacks.c \
callbacks.h \
- gdk-pixbuf-blur.c \
+ cairo-blur.c \
gth-file-tool-adjust-colors.c \
gth-file-tool-crop.c \
gth-file-tool-desaturate.c \
diff --git a/extensions/file_tools/cairo-blur.c b/extensions/file_tools/cairo-blur.c
new file mode 100644
index 0000000..287a2fd
--- /dev/null
+++ b/extensions/file_tools/cairo-blur.c
@@ -0,0 +1,271 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2011 The 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <math.h>
+#include <string.h>
+#include <gthumb.h>
+#include "cairo-blur.h"
+
+
+
+static void
+_cairo_image_surface_gaussian_blur (cairo_surface_t *source,
+ int radius)
+{
+ /* FIXME: to do */
+}
+
+
+static void
+box_blur (cairo_surface_t *source,
+ cairo_surface_t *destination,
+ int radius,
+ guchar *div_kernel_size)
+{
+ int width, height, src_rowstride, dest_rowstride;
+ guchar *p_src, *p_dest, *c1, *c2;
+ int x, y, i, i1, i2, width_minus_1, height_minus_1, radius_plus_1;
+ int r, g, b, a;
+ guchar *p_dest_row, *p_dest_col;
+
+ width = cairo_image_surface_get_width (source);
+ height = cairo_image_surface_get_height (source);
+ radius_plus_1 = radius + 1;
+
+ /* horizontal blur */
+
+ p_src = cairo_image_surface_get_data (source);
+ p_dest = cairo_image_surface_get_data (destination);
+ src_rowstride = cairo_image_surface_get_stride (source);
+ dest_rowstride = cairo_image_surface_get_stride (destination);
+ width_minus_1 = width - 1;
+ for (y = 0; y < height; y++) {
+
+ /* calc the initial sums of the kernel */
+
+ r = g = b = a = 0;
+
+ for (i = -radius; i <= radius; i++) {
+ c1 = p_src + (CLAMP (i, 0, width_minus_1) * 4);
+ r += c1[CAIRO_RED];
+ g += c1[CAIRO_GREEN];
+ b += c1[CAIRO_BLUE];
+ /*if (n_channels == 4)
+ a += c1[CAIRO_ALPHA];*/
+ }
+
+ p_dest_row = p_dest;
+ for (x = 0; x < width; x++) {
+ /* set as the mean of the kernel */
+
+ p_dest_row[CAIRO_RED] = div_kernel_size[r];
+ p_dest_row[CAIRO_GREEN] = div_kernel_size[g];
+ p_dest_row[CAIRO_BLUE] = div_kernel_size[b];
+ p_dest_row[CAIRO_ALPHA] = 0xff;
+ /*if (n_channels == 4)
+ p_dest_row[CAIRO_ALPHA] = div_kernel_size[a];*/
+ p_dest_row += 4;
+
+ /* the pixel to add to the kernel */
+
+ i1 = x + radius_plus_1;
+ if (i1 > width_minus_1)
+ i1 = width_minus_1;
+ c1 = p_src + (i1 * 4);
+
+ /* the pixel to remove from the kernel */
+
+ i2 = x - radius;
+ if (i2 < 0)
+ i2 = 0;
+ c2 = p_src + (i2 * 4);
+
+ /* calc the new sums of the kernel */
+
+ r += c1[CAIRO_RED] - c2[CAIRO_RED];
+ g += c1[CAIRO_GREEN] - c2[CAIRO_GREEN];
+ b += c1[CAIRO_BLUE] - c2[CAIRO_BLUE];
+ /*if (n_channels == 4)
+ a += c1[CAIRO_ALPHA] - c2[CAIRO_ALPHA];*/
+ }
+
+ p_src += src_rowstride;
+ p_dest += dest_rowstride;
+ }
+
+ /* vertical blur */
+
+ p_src = cairo_image_surface_get_data (destination);
+ p_dest = cairo_image_surface_get_data (source);
+ src_rowstride = cairo_image_surface_get_stride (destination);
+ dest_rowstride = cairo_image_surface_get_stride (source);
+ height_minus_1 = height - 1;
+ for (x = 0; x < width; x++) {
+
+ /* calc the initial sums of the kernel */
+
+ r = g = b = a = 0;
+
+ for (i = -radius; i <= radius; i++) {
+ c1 = p_src + (CLAMP (i, 0, height_minus_1) * src_rowstride);
+ r += c1[CAIRO_RED];
+ g += c1[CAIRO_GREEN];
+ b += c1[CAIRO_BLUE];
+ /*if (n_channels == 4)
+ a += c1[CAIRO_ALPHA];*/
+ }
+
+ p_dest_col = p_dest;
+ for (y = 0; y < height; y++) {
+ /* set as the mean of the kernel */
+
+ p_dest_col[CAIRO_RED] = div_kernel_size[r];
+ p_dest_col[CAIRO_GREEN] = div_kernel_size[g];
+ p_dest_col[CAIRO_BLUE] = div_kernel_size[b];
+ p_dest_col[CAIRO_ALPHA] = 0xff;
+ /*if (n_channels == 4)
+ p_dest_row[CAIRO_ALPHA] = div_kernel_size[a];*/
+ p_dest_col += dest_rowstride;
+
+ /* the pixel to add to the kernel */
+
+ i1 = y + radius_plus_1;
+ if (i1 > height_minus_1)
+ i1 = height_minus_1;
+ c1 = p_src + (i1 * src_rowstride);
+
+ /* the pixel to remove from the kernel */
+
+ i2 = y - radius;
+ if (i2 < 0)
+ i2 = 0;
+ c2 = p_src + (i2 * src_rowstride);
+
+ /* calc the new sums of the kernel */
+
+ r += c1[CAIRO_RED] - c2[CAIRO_RED];
+ g += c1[CAIRO_GREEN] - c2[CAIRO_GREEN];
+ b += c1[CAIRO_BLUE] - c2[CAIRO_BLUE];
+ /*if (n_channels == 4)
+ a += c1[CAIRO_ALPHA] - c2[CAIRO_ALPHA];*/
+ }
+
+ p_src += 4;
+ p_dest += 4;
+ }
+}
+
+
+static void
+_cairo_image_surface_box_blur (cairo_surface_t *source,
+ int radius,
+ int iterations)
+{
+ gint64 kernel_size;
+ guchar *div_kernel_size;
+ int i;
+ cairo_surface_t *tmp;
+
+ kernel_size = 2 * radius + 1;
+ div_kernel_size = g_new (guchar, 256 * kernel_size);
+ for (i = 0; i < 256 * kernel_size; i++)
+ div_kernel_size[i] = (guchar) (i / kernel_size);
+
+ tmp = _cairo_image_surface_create_compatible (source);
+ while (iterations-- > 0)
+ box_blur (source, tmp, radius, div_kernel_size);
+
+ cairo_surface_destroy (tmp);
+}
+
+
+void
+_cairo_image_surface_blur (cairo_surface_t *source,
+ int radius)
+{
+ if (radius <= 10)
+ _cairo_image_surface_box_blur (source, radius, 3);
+ else
+ _cairo_image_surface_gaussian_blur (source, radius);
+}
+
+
+void
+_cairo_image_surface_sharpen (cairo_surface_t *source,
+ int radius,
+ double amount,
+ guchar threshold)
+{
+ cairo_surface_t *blurred;
+ int width, height;
+ int source_rowstride, blurred_rowstride;
+ int x, y;
+ guchar *p_src, *p_blurred;
+ guchar *p_src_row, *p_blurred_row;
+ guchar r1, g1, b1;
+ guchar r2, g2, b2;
+
+ blurred = _cairo_image_surface_copy (source);
+ _cairo_image_surface_blur (blurred, radius);
+
+ width = cairo_image_surface_get_width (source);
+ height = cairo_image_surface_get_height (source);
+ source_rowstride = cairo_image_surface_get_stride (source);
+ blurred_rowstride = cairo_image_surface_get_stride (blurred);
+
+ p_src = cairo_image_surface_get_data (source);
+ p_blurred = cairo_image_surface_get_data (blurred);
+
+ for (y = 0; y < height; y++) {
+ p_src_row = p_src;
+ p_blurred_row = p_blurred;
+
+ for (x = 0; x < width; x++) {
+ r1 = p_src_row[CAIRO_RED];
+ g1 = p_src_row[CAIRO_GREEN];
+ b1 = p_src_row[CAIRO_BLUE];
+
+ r2 = p_blurred_row[CAIRO_RED];
+ g2 = p_blurred_row[CAIRO_GREEN];
+ b2 = p_blurred_row[CAIRO_BLUE];
+
+ if (ABS (r1 - r2) >= threshold)
+ r1 = interpolate_value (r1, r2, amount);
+ if (ABS (g1 - g2) >= threshold)
+ g1 = interpolate_value (g1, g2, amount);
+ if (ABS (b1 - b2) >= threshold)
+ b1 = interpolate_value (b1, b2, amount);
+
+ p_src_row[CAIRO_RED] = r1;
+ p_src_row[CAIRO_GREEN] = g1;
+ p_src_row[CAIRO_BLUE] = b1;
+
+ p_src_row += 4;
+ p_blurred_row += 4;
+ }
+
+ p_src += source_rowstride;
+ p_blurred += blurred_rowstride;
+ }
+
+ cairo_surface_destroy (blurred);
+}
diff --git a/extensions/file_tools/gdk-pixbuf-blur.h b/extensions/file_tools/cairo-blur.h
similarity index 76%
rename from extensions/file_tools/gdk-pixbuf-blur.h
rename to extensions/file_tools/cairo-blur.h
index 58311b9..bcc61d1 100644
--- a/extensions/file_tools/gdk-pixbuf-blur.h
+++ b/extensions/file_tools/cairo-blur.h
@@ -23,17 +23,16 @@
#define GDK_PIXBUF_BLUR_H
#include <glib.h>
-#include <gdk/gdk.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <cairo.h>
G_BEGIN_DECLS
-void _gdk_pixbuf_blur (GdkPixbuf *src,
- int radius);
-void _gdk_pixbuf_sharpen (GdkPixbuf *src,
- int radius,
- double amount,
- guchar threshold);
+void _cairo_image_surface_blur (cairo_surface_t *source,
+ int radius);
+void _cairo_image_surface_sharpen (cairo_surface_t *source,
+ int radius,
+ double amount,
+ guchar threshold);
G_END_DECLS
diff --git a/extensions/file_tools/gth-file-tool-adjust-colors.c b/extensions/file_tools/gth-file-tool-adjust-colors.c
index 2eca2da..8fbf371 100644
--- a/extensions/file_tools/gth-file-tool-adjust-colors.c
+++ b/extensions/file_tools/gth-file-tool-adjust-colors.c
@@ -80,15 +80,6 @@ adjust_colors_before (GthAsyncTask *task,
static guchar
-interpolate_value (guchar original,
- guchar reference,
- double distance)
-{
- return CLAMP ((distance * reference) + ((1.0 - distance) * original), 0, 255);
-}
-
-
-static guchar
gamma_correction (guchar original,
double gamma)
{
diff --git a/extensions/file_tools/gth-file-tool-sharpen.c b/extensions/file_tools/gth-file-tool-sharpen.c
index 012ff5b..b1971f5 100644
--- a/extensions/file_tools/gth-file-tool-sharpen.c
+++ b/extensions/file_tools/gth-file-tool-sharpen.c
@@ -23,7 +23,7 @@
#include <gthumb.h>
#include <extensions/image_viewer/gth-image-viewer-page.h>
#include "gth-file-tool-sharpen.h"
-#include "gdk-pixbuf-blur.h"
+#include "cairo-blur.h"
#define GET_WIDGET(x) (_gtk_builder_get_widget (self->priv->builder, (x)))
@@ -37,16 +37,16 @@ static gpointer parent_class = NULL;
struct _GthFileToolSharpenPrivate {
- GdkPixbuf *src_pixbuf;
- GdkPixbuf *dest_pixbuf;
- GtkBuilder *builder;
- GtkAdjustment *radius_adj;
- GtkAdjustment *amount_adj;
- GtkAdjustment *threshold_adj;
- GtkWidget *preview;
- GthTask *pixbuf_task;
- guint apply_event;
- gboolean show_preview;
+ cairo_surface_t *source;
+ cairo_surface_t *destination;
+ GtkBuilder *builder;
+ GtkAdjustment *radius_adj;
+ GtkAdjustment *amount_adj;
+ GtkAdjustment *threshold_adj;
+ GtkWidget *preview;
+ GthTask *pixbuf_task;
+ guint apply_event;
+ gboolean show_preview;
};
@@ -65,28 +65,14 @@ gth_file_tool_sharpen_update_sensitivity (GthFileTool *base)
}
-static void
-task_completed_cb (GthTask *task,
- GError *error,
- gpointer user_data)
-{
- GthFileTool *base = user_data;
-
- 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);
- }
-}
-
-
typedef struct {
- int radius;
- double amount;
- int threshold;
+ GthFileToolSharpen *self;
+ cairo_surface_t *source;
+ cairo_surface_t *destination;
+ GtkWidget *viewer_page;
+ int radius;
+ double amount;
+ int threshold;
} SharpenData;
@@ -95,7 +81,10 @@ sharpen_data_new (GthFileToolSharpen *self)
{
SharpenData *sharpen_data;
- sharpen_data = g_new (SharpenData, 1);
+ sharpen_data = g_new0 (SharpenData, 1);
+ sharpen_data->source = NULL;
+ sharpen_data->destination = NULL;
+ sharpen_data->viewer_page = NULL;
sharpen_data->radius = gtk_adjustment_get_value (self->priv->radius_adj);
sharpen_data->amount = - gtk_adjustment_get_value (self->priv->amount_adj) / 100.0;
sharpen_data->threshold = gtk_adjustment_get_value (self->priv->threshold_adj);
@@ -105,15 +94,53 @@ sharpen_data_new (GthFileToolSharpen *self)
static void
-sharpen_step (GthPixbufTask *pixbuf_task)
+sharpen_before (GthAsyncTask *task,
+ gpointer user_data)
+{
+ gth_task_progress (GTH_TASK (task), _("Sharpening image"), NULL, TRUE, 0.0);
+}
+
+
+static gpointer
+sharpen_exec (GthAsyncTask *task,
+ gpointer user_data)
{
- SharpenData *sharpen_data = pixbuf_task->data;
+ SharpenData *sharpen_data = user_data;
+
+ sharpen_data->destination = _cairo_image_surface_copy (sharpen_data->source);
+
+ /* FIXME: set progress info and allow cancellation */
+
+ _cairo_image_surface_sharpen (sharpen_data->destination,
+ sharpen_data->radius,
+ sharpen_data->amount,
+ sharpen_data->threshold);
- pixbuf_task->dest = gdk_pixbuf_copy (pixbuf_task->src);
- _gdk_pixbuf_sharpen (pixbuf_task->dest,
- sharpen_data->radius,
- sharpen_data->amount,
- sharpen_data->threshold);
+ return NULL;
+}
+
+
+static void
+sharpen_after (GthAsyncTask *task,
+ GError *error,
+ gpointer user_data)
+{
+ SharpenData *sharpen_data = user_data;
+
+ if (error == NULL)
+ gth_image_viewer_page_set_image (GTH_IMAGE_VIEWER_PAGE (sharpen_data->viewer_page), sharpen_data->destination, TRUE);
+}
+
+
+static void
+sharpen_data_free (gpointer user_data)
+{
+ SharpenData *sharpen_data = user_data;
+
+ _g_object_unref (sharpen_data->viewer_page);
+ cairo_surface_destroy (sharpen_data->destination);
+ cairo_surface_destroy (sharpen_data->source);
+ g_free (sharpen_data);
}
@@ -121,19 +148,29 @@ static void
ok_button_clicked_cb (GtkButton *button,
GthFileToolSharpen *self)
{
+ GtkWidget *window;
+ GtkWidget *viewer_page;
SharpenData *sharpen_data;
GthTask *task;
+ 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));
+ if (! GTH_IS_IMAGE_VIEWER_PAGE (viewer_page))
+ return;
+
sharpen_data = sharpen_data_new (self);
- task = gth_pixbuf_task_new (_("Sharpening image"),
- TRUE,
- NULL,
- sharpen_step,
- NULL,
- sharpen_data,
- g_free);
- gth_pixbuf_task_set_source (GTH_PIXBUF_TASK (task), self->priv->src_pixbuf);
- g_signal_connect (task, "completed", G_CALLBACK (task_completed_cb), self);
+ sharpen_data->viewer_page = g_object_ref (viewer_page);
+ sharpen_data->source = cairo_surface_reference (self->priv->source);
+ task = gth_async_task_new (sharpen_before,
+ sharpen_exec,
+ sharpen_after,
+ sharpen_data,
+ sharpen_data_free);
gth_browser_exec_task (GTH_BROWSER (gth_file_tool_get_window (GTH_FILE_TOOL (self))), task, FALSE);
g_object_unref (task);
@@ -185,9 +222,10 @@ apply_cb (gpointer user_data)
preview = GTH_IMAGE_VIEWER (self->priv->preview);
if (self->priv->show_preview) {
- SharpenData *sharpen_data;
- GdkPixbuf *preview_subpixbuf;
- int x, y, w ,h;
+ SharpenData *sharpen_data;
+ int x, y, w ,h;
+ cairo_surface_t *preview_surface;
+ cairo_t *cr;
sharpen_data = sharpen_data_new (self);
x = gtk_adjustment_get_value (preview->hadj);
@@ -195,20 +233,30 @@ apply_cb (gpointer user_data)
w = gtk_adjustment_get_page_size (preview->hadj);
h = gtk_adjustment_get_page_size (preview->vadj);
- _g_object_unref (self->priv->dest_pixbuf);
- self->priv->dest_pixbuf = gdk_pixbuf_copy (self->priv->src_pixbuf);
- preview_subpixbuf = gdk_pixbuf_new_subpixbuf (self->priv->dest_pixbuf, x, y, w, h);
- _gdk_pixbuf_sharpen (preview_subpixbuf,
- sharpen_data->radius,
- sharpen_data->amount,
- sharpen_data->threshold);
- gth_image_viewer_set_pixbuf (preview, self->priv->dest_pixbuf, -1, -1);
-
- g_object_unref (preview_subpixbuf);
- g_free (sharpen_data);
+ cairo_surface_destroy (self->priv->destination);
+ self->priv->destination = _cairo_image_surface_copy (self->priv->source);
+
+ /* FIXME: use a cairo sub-surface when cairo 1.10 will be requiered */
+
+ preview_surface = _cairo_image_surface_copy_subsurface (self->priv->destination, x, y, w, h);
+ _cairo_image_surface_sharpen (preview_surface,
+ sharpen_data->radius,
+ sharpen_data->amount,
+ sharpen_data->threshold);
+
+ cr = cairo_create (self->priv->destination);
+ cairo_set_source_surface (cr, preview_surface, x, y);
+ cairo_rectangle (cr, x, y, w, h);
+ cairo_fill (cr);
+ cairo_destroy (cr);
+
+ gth_image_viewer_set_image (preview, self->priv->destination, -1, -1);
+
+ cairo_surface_destroy (preview_surface);
+ sharpen_data_free (sharpen_data);
}
else
- gth_image_viewer_set_pixbuf (preview, self->priv->src_pixbuf, -1, -1);
+ gth_image_viewer_set_image (preview, self->priv->source, -1, -1);
return FALSE;
}
@@ -256,15 +304,15 @@ gth_file_tool_sharpen_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 ("sharpen-options.ui", "file_tools");
options = _gtk_builder_get_widget (self->priv->builder, "options");
@@ -276,7 +324,7 @@ gth_file_tool_sharpen_get_options (GthFileTool *base)
gth_image_viewer_set_zoom_change (GTH_IMAGE_VIEWER (self->priv->preview), GTH_ZOOM_CHANGE_KEEP_PREV);
gth_image_viewer_set_zoom (GTH_IMAGE_VIEWER (self->priv->preview), 1.0);
gth_image_viewer_enable_zoom_with_keys (GTH_IMAGE_VIEWER (self->priv->preview), FALSE);
- gth_image_viewer_set_pixbuf (GTH_IMAGE_VIEWER (self->priv->preview), self->priv->src_pixbuf, -1, -1);
+ gth_image_viewer_set_image (GTH_IMAGE_VIEWER (self->priv->preview), self->priv->source, -1, -1);
image_navigator = gth_image_navigator_new (GTH_IMAGE_VIEWER (self->priv->preview));
gtk_widget_show_all (image_navigator);
gtk_box_pack_start (GTK_BOX (GET_WIDGET ("preview_hbox")), image_navigator, TRUE, TRUE, 0);
@@ -344,11 +392,11 @@ gth_file_tool_sharpen_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;
}
@@ -364,8 +412,8 @@ static void
gth_file_tool_sharpen_instance_init (GthFileToolSharpen *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_FILE_TOOL_SHARPEN, GthFileToolSharpenPrivate);
- self->priv->src_pixbuf = NULL;
- self->priv->dest_pixbuf = NULL;
+ self->priv->source = NULL;
+ self->priv->destination = NULL;
self->priv->builder = NULL;
self->priv->show_preview = TRUE;
@@ -383,8 +431,8 @@ gth_file_tool_sharpen_finalize (GObject *object)
self = (GthFileToolSharpen *) 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);
/* Chain up */
diff --git a/gthumb/cairo-utils.c b/gthumb/cairo-utils.c
index 575f9ae..c8f0766 100644
--- a/gthumb/cairo-utils.c
+++ b/gthumb/cairo-utils.c
@@ -99,7 +99,7 @@ _cairo_image_surface_get_has_alpha (cairo_surface_t *surface)
cairo_surface_t *
-_cairo_image_surface_copy (cairo_surface_t *surface)
+_cairo_image_surface_copy (cairo_surface_t *source)
{
cairo_surface_t *result;
cairo_format_t format;
@@ -108,13 +108,18 @@ _cairo_image_surface_copy (cairo_surface_t *surface)
int stride;
unsigned char *pixels;
cairo_status_t status;
+ int source_stride;
+ int destination_stride;
+ unsigned char *p_source;
+ unsigned char *p_destination;
+ int row_size;
- if (surface == NULL)
+ if (source == NULL)
return NULL;
- format = cairo_image_surface_get_format (surface);
- width = cairo_image_surface_get_width (surface);
- height = cairo_image_surface_get_height (surface);
+ format = cairo_image_surface_get_format (source);
+ width = cairo_image_surface_get_width (source);
+ height = cairo_image_surface_get_height (source);
stride = cairo_format_stride_for_width (format, width);
pixels = g_try_malloc (stride * height);
if (pixels == NULL)
@@ -135,6 +140,18 @@ _cairo_image_surface_copy (cairo_surface_t *surface)
return NULL;
}
+ source_stride = cairo_image_surface_get_stride (source);
+ destination_stride = cairo_image_surface_get_stride (result);
+ p_source = cairo_image_surface_get_data (source);
+ p_destination = cairo_image_surface_get_data (result);
+ row_size = width * 4;
+ while (height-- > 0) {
+ memcpy (p_destination, p_source, row_size);
+
+ p_source += source_stride;
+ p_destination += destination_stride;
+ }
+
return result;
}
@@ -258,6 +275,15 @@ _cairo_image_surface_create_from_pixbuf (GdkPixbuf *pixbuf)
cairo_surface_t *
+_cairo_image_surface_create_compatible (cairo_surface_t *surface)
+{
+ return cairo_image_surface_create (cairo_image_surface_get_format (surface),
+ cairo_image_surface_get_width (surface),
+ cairo_image_surface_get_height (surface));
+}
+
+
+cairo_surface_t *
_cairo_image_surface_scale_to (cairo_surface_t *surface,
int width,
int height,
diff --git a/gthumb/cairo-utils.h b/gthumb/cairo-utils.h
index b97b813..8f01308 100644
--- a/gthumb/cairo-utils.h
+++ b/gthumb/cairo-utils.h
@@ -99,6 +99,10 @@
} \
} G_STMT_END
+
+#define interpolate_value(original, reference, distance) (CLAMP (((distance) * (reference)) + ((1.0 - (distance)) * (original)), 0, 255))
+
+
/* types */
typedef struct {
@@ -138,6 +142,7 @@ cairo_surface_t * _cairo_image_surface_copy_subsurface (cairo_surface_t *
int width,
int height);
cairo_surface_t * _cairo_image_surface_create_from_pixbuf (GdkPixbuf *pixbuf);
+cairo_surface_t * _cairo_image_surface_create_compatible (cairo_surface_t *surface);
cairo_surface_t * _cairo_image_surface_scale_to (cairo_surface_t *surface,
int width,
int height,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]