[gthumb] cairo scale: moved cairo-scale.[ch] in gthumb
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gthumb] cairo scale: moved cairo-scale.[ch] in gthumb
- Date: Sun, 19 Aug 2012 08:37:26 +0000 (UTC)
commit 3d073ff3056b2dbd2c3865221eb6ea74119965d7
Author: Paolo Bacchilega <paobac src gnome org>
Date: Fri Aug 17 18:05:51 2012 +0200
cairo scale: moved cairo-scale.[ch] in gthumb
and use it instead of _cairo_image_curface_scale_to that uses the cairo
bilinear filter.
extensions/cairo_io/cairo-io-jpeg.c | 2 +-
extensions/file_tools/Makefile.am | 2 -
extensions/file_tools/gth-file-tool-resize.c | 4 +-
extensions/file_tools/gth-image-line-tool.c | 2 +-
extensions/file_tools/gth-image-rotator.c | 2 +-
gthumb/Makefile.am | 2 +
{extensions/file_tools => gthumb}/cairo-scale.c | 194 ++++++++++++++---------
{extensions/file_tools => gthumb}/cairo-scale.h | 31 +++-
gthumb/cairo-utils.c | 23 ---
gthumb/cairo-utils.h | 6 +-
gthumb/gth-image-navigator.c | 11 +-
11 files changed, 157 insertions(+), 122 deletions(-)
---
diff --git a/extensions/cairo_io/cairo-io-jpeg.c b/extensions/cairo_io/cairo-io-jpeg.c
index acf15fa..a23e2cc 100644
--- a/extensions/cairo_io/cairo-io-jpeg.c
+++ b/extensions/cairo_io/cairo-io-jpeg.c
@@ -497,7 +497,7 @@ _cairo_image_surface_create_from_jpeg (GthFileData *file_data,
width = destination_width;
height = destination_height;
scale_keeping_ratio (&width, &height, requested_size, requested_size, TRUE);
- scaled = _cairo_image_surface_scale_to (surface, width, height, CAIRO_FILTER_BILINEAR);
+ scaled = _cairo_image_surface_scale (surface, width, height, SCALE_FILTER_BEST, NULL);
cairo_surface_destroy (surface);
surface = scaled;
diff --git a/extensions/file_tools/Makefile.am b/extensions/file_tools/Makefile.am
index 0c60238..feab2a1 100644
--- a/extensions/file_tools/Makefile.am
+++ b/extensions/file_tools/Makefile.am
@@ -10,7 +10,6 @@ ENUM_TYPES = \
HEADER_FILES = \
cairo-blur.h \
cairo-rotate.h \
- cairo-scale.h \
gth-file-tool-adjust-colors.h \
gth-file-tool-crop.h \
gth-file-tool-desaturate.h \
@@ -59,7 +58,6 @@ libfile_tools_la_SOURCES = \
callbacks.h \
cairo-blur.c \
cairo-rotate.c \
- cairo-scale.c \
gth-file-tool-adjust-colors.c \
gth-file-tool-crop.c \
gth-file-tool-desaturate.c \
diff --git a/extensions/file_tools/gth-file-tool-resize.c b/extensions/file_tools/gth-file-tool-resize.c
index f7bec9c..369e197 100644
--- a/extensions/file_tools/gth-file-tool-resize.c
+++ b/extensions/file_tools/gth-file-tool-resize.c
@@ -24,7 +24,6 @@
#include <gthumb.h>
#include <extensions/image_viewer/gth-image-viewer-page.h>
#include <extensions/image_viewer/preferences.h>
-#include "cairo-scale.h"
#include "gth-file-tool-resize.h"
#include "preferences.h"
@@ -128,7 +127,8 @@ update_pixbuf_size (GthFileToolResize *self)
self->priv->new_image = _cairo_image_surface_scale (self->priv->original_image,
self->priv->new_width,
self->priv->new_height,
- self->priv->high_quality);
+ (self->priv->high_quality ? SCALE_FILTER_BEST : SCALE_FILTER_FAST),
+ NULL);
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), self->priv->new_image, FALSE);
diff --git a/extensions/file_tools/gth-image-line-tool.c b/extensions/file_tools/gth-image-line-tool.c
index 6a77052..09f532f 100644
--- a/extensions/file_tools/gth-image-line-tool.c
+++ b/extensions/file_tools/gth-image-line-tool.c
@@ -147,7 +147,7 @@ update_image_surface (GthImageLineTool *self)
gtk_widget_get_allocation (GTK_WIDGET (self->priv->viewer), &allocation);
max_size = MAX (allocation.width, allocation.height) / G_SQRT2 + 2;
if (scale_keeping_ratio (&width, &height, max_size, max_size, FALSE))
- preview_image = _cairo_image_surface_scale_to (image, width, height, CAIRO_FILTER_BILINEAR);
+ preview_image = _cairo_image_surface_scale (image, width, height, SCALE_FILTER_BEST, NULL);
else
preview_image = cairo_surface_reference (image);
diff --git a/extensions/file_tools/gth-image-rotator.c b/extensions/file_tools/gth-image-rotator.c
index 4fdc78b..0d9c752 100644
--- a/extensions/file_tools/gth-image-rotator.c
+++ b/extensions/file_tools/gth-image-rotator.c
@@ -239,7 +239,7 @@ update_image_surface (GthImageRotator *self)
gtk_widget_get_allocation (GTK_WIDGET (self->priv->viewer), &allocation);
max_size = MAX (allocation.width, allocation.height) / G_SQRT2 + 2;
if (scale_keeping_ratio (&width, &height, max_size, max_size, FALSE))
- preview_image = _cairo_image_surface_scale_to (image, width, height, CAIRO_FILTER_BILINEAR);
+ preview_image = _cairo_image_surface_scale (image, width, height, SCALE_FILTER_BEST, NULL);
else
preview_image = cairo_surface_reference (image);
diff --git a/gthumb/Makefile.am b/gthumb/Makefile.am
index 4e279f0..213ca02 100644
--- a/gthumb/Makefile.am
+++ b/gthumb/Makefile.am
@@ -24,6 +24,7 @@ PUBLIC_BUILT_HEADER_FILES = \
PUBLIC_HEADER_FILES = \
$(PUBLIC_BUILT_HEADER_FILES) \
+ cairo-scale.h \
cairo-utils.h \
dom.h \
egg-macros.h \
@@ -146,6 +147,7 @@ gthumb_SOURCES = \
$(EXTERNAL) \
$(PUBLIC_HEADER_FILES) \
$(PRIVATE_HEADER_FILES) \
+ cairo-scale.c \
cairo-utils.c \
dlg-location.c \
dlg-personalize-filters.c \
diff --git a/extensions/file_tools/cairo-scale.c b/gthumb/cairo-scale.c
similarity index 70%
rename from extensions/file_tools/cairo-scale.c
rename to gthumb/cairo-scale.c
index 566a085..3ca59f0 100644
--- a/extensions/file_tools/cairo-scale.c
+++ b/gthumb/cairo-scale.c
@@ -19,14 +19,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
+#include <string.h>
#include <math.h>
-#include <gthumb.h>
+#include <cairo.h>
+#include "cairo-utils.h"
#include "cairo-scale.h"
-/* -- _cairo_image_surface_scale_nearest -- */
-
-
typedef long gfixed;
#define GINT_TO_FIXED(x) ((gfixed) ((x) << 16))
#define GDOUBLE_TO_FIXED(x) ((gfixed) ((x) * (1 << 16) + 0.5))
@@ -40,7 +40,13 @@ typedef long gfixed;
#define gfixed_div(x, y) (((x) << 16) / (y))
-cairo_surface_t *
+#if 0
+
+
+/* -- _cairo_image_surface_scale_nearest -- */
+
+
+static cairo_surface_t *
_cairo_image_surface_scale_nearest (cairo_surface_t *image,
int new_width,
int new_height)
@@ -110,7 +116,14 @@ _cairo_image_surface_scale_nearest (cairo_surface_t *image,
}
-/* -- _cairo_image_surface_scale_filter -- */
+#endif
+
+
+/* -- _cairo_image_surface_scale_filter --
+ *
+ * Based on code from ImageMagick/magick/resize.c
+ *
+ * */
#define EPSILON ((double) 1.0e-16)
@@ -119,15 +132,6 @@ _cairo_image_surface_scale_nearest (cairo_surface_t *image,
typedef double (*weight_func_t) (double distance);
-typedef enum {
- FILTER_POINT = 0,
- FILTER_BOX,
- FILTER_TRIANGLE,
- FILTER_QUADRATIC,
- N_FILTERS
-} filter_type_t;
-
-
static double
box (double x)
{
@@ -143,16 +147,35 @@ triangle (double x)
static double
-quadratic (double x)
+sinc_fast (double x)
{
- /*
- * 2rd order (quadratic) B-Spline approximation of Gaussian.
- */
- if (x < 0.5)
- return 0.75 - x * x;
- if (x < 1.5)
- return 0.5 * (x - 1.5) * (x - 1.5);
- return 0.0;
+ if (x > 4.0) {
+ const double alpha = G_PI * x;
+ return sin (alpha) / alpha;
+ }
+
+ {
+ /*
+ * The approximations only depend on x^2 (sinc is an even function).
+ */
+
+ const double xx = x*x;
+
+ /*
+ * Maximum absolute relative error 6.3e-6 < 1/2^17.
+ */
+ const double c0 = 0.173610016489197553621906385078711564924e-2L;
+ const double c1 = -0.384186115075660162081071290162149315834e-3L;
+ const double c2 = 0.393684603287860108352720146121813443561e-4L;
+ const double c3 = -0.248947210682259168029030370205389323899e-5L;
+ const double c4 = 0.107791837839662283066379987646635416692e-6L;
+ const double c5 = -0.324874073895735800961260474028013982211e-8L;
+ const double c6 = 0.628155216606695311524920882748052490116e-10L;
+ const double c7 = -0.586110644039348333520104379959307242711e-12L;
+ const double p = c0+xx*(c1+xx*(c2+xx*(c3+xx*(c4+xx*(c5+xx*(c6+xx*c7))))));
+
+ return (xx-1.0)*(xx-4.0)*(xx-9.0)*(xx-16.0)*p;
+ }
}
@@ -160,11 +183,11 @@ static struct {
weight_func_t weight_func;
double support;
}
-const filters[N_FILTERS] = {
+const filters[N_SCALE_FILTERS] = {
{ box, .0 },
{ box, .5 },
{ triangle, 1.0 },
- { quadratic, 1.5 }
+ { sinc_fast, 3.0 }
};
@@ -172,19 +195,28 @@ const filters[N_FILTERS] = {
typedef struct {
- weight_func_t weight_func;
- double support;
+ weight_func_t weight_func;
+ double support;
+ GthAsyncTask *task;
+ gulong total_lines;
+ gulong processed_lines;
+ gboolean cancelled;
} resize_filter_t;
static resize_filter_t *
-resize_filter_create (filter_type_t filter)
+resize_filter_create (scale_filter_t filter_type,
+ GthAsyncTask *task)
{
resize_filter_t *resize_filter;
resize_filter = g_slice_new (resize_filter_t);
- resize_filter->weight_func = filters[filter].weight_func;
- resize_filter->support = filters[filter].support;
+ resize_filter->weight_func = filters[filter_type].weight_func;
+ resize_filter->support = filters[filter_type].support;
+ resize_filter->task = task;
+ resize_filter->total_lines = 0;
+ resize_filter->processed_lines = 0;
+ resize_filter->cancelled = FALSE;
return resize_filter;
}
@@ -201,7 +233,12 @@ static double inline
resize_filter_get_weight (resize_filter_t *resize_filter,
double distance)
{
- return resize_filter->weight_func (fabs (distance));
+ double scale = 1.0;
+
+ if (resize_filter->weight_func == sinc_fast)
+ scale = resize_filter->weight_func (fabs (distance));
+
+ return scale * resize_filter->weight_func (fabs (distance));
}
@@ -229,15 +266,18 @@ horizontal_scale_transpose (cairo_surface_t *image,
double scale_factor,
resize_filter_t *resize_filter)
{
- double scale;
- double support;
- int y;
- guchar *p_src;
- guchar *p_dest;
- int src_rowstride;
- int dest_rowstride;
- double *weights;
- gfixed *fixed_weights;
+ double scale;
+ double support;
+ int y;
+ guchar *p_src;
+ guchar *p_dest;
+ int src_rowstride;
+ int dest_rowstride;
+ double *weights;
+ gfixed *fixed_weights;
+
+ if (resize_filter->cancelled)
+ return;
cairo_surface_flush (scaled);
@@ -256,7 +296,7 @@ horizontal_scale_transpose (cairo_surface_t *image,
fixed_weights = g_new (gfixed, 2.0 * support + 3.0);
scale = reciprocal (scale);
- for (y = 0; y < cairo_image_surface_get_height (scaled); y++) {
+ for (y = 0; ! resize_filter->cancelled && (y < cairo_image_surface_get_height (scaled)); y++) {
guchar *p_src_row;
guchar *p_dest_pixel;
double bisect;
@@ -267,6 +307,11 @@ horizontal_scale_transpose (cairo_surface_t *image,
int x;
int i;
+ if (resize_filter->task != NULL) {
+ double progress = (double) resize_filter->processed_lines++ / resize_filter->total_lines;
+ gth_async_task_set_data (resize_filter->task, NULL, NULL, &progress);
+ }
+
bisect = (y + 0.5) / scale_factor + EPSILON;
start = MAX (bisect - support + 0.5, 0.0);
stop = MIN (bisect + support + 0.5, cairo_image_surface_get_width (image));
@@ -278,8 +323,10 @@ horizontal_scale_transpose (cairo_surface_t *image,
}
density = reciprocal (density);
- for (i = 0; i < n; i++)
- fixed_weights[i] = GDOUBLE_TO_FIXED (weights[i] * density);
+ for (i = 0; i < n; i++) {
+ double w = weights[i] * density;
+ fixed_weights[i] = GDOUBLE_TO_FIXED (w);
+ }
p_src_row = p_src;
p_dest_pixel = p_dest + (y * dest_rowstride);
@@ -288,6 +335,12 @@ horizontal_scale_transpose (cairo_surface_t *image,
gfixed r, g, b, a;
gfixed w;
+ if (resize_filter->task != NULL) {
+ gth_async_task_get_data (resize_filter->task, NULL, &resize_filter->cancelled, NULL);
+ if (resize_filter->cancelled)
+ break;
+ }
+
p_src_pixel = p_src_row + (start * 4);
r = g = b = a = GFIXED_0;
@@ -323,11 +376,12 @@ horizontal_scale_transpose (cairo_surface_t *image,
}
-cairo_surface_t *
+static cairo_surface_t *
_cairo_image_surface_scale_filter (cairo_surface_t *image,
int new_width,
int new_height,
- filter_type_t filter)
+ scale_filter_t filter,
+ GthAsyncTask *task)
{
int src_width;
int src_height;
@@ -350,7 +404,10 @@ _cairo_image_surface_scale_filter (cairo_surface_t *image,
if (scaled == NULL)
return NULL;
- resize_filter = resize_filter_create (filter);
+ resize_filter = resize_filter_create (filter, task);
+ resize_filter->total_lines = new_width + new_height;
+ resize_filter->processed_lines = 0;
+
x_factor = (double) new_width / src_width;
y_factor = (double) new_height / src_height;
tmp = cairo_surface_create_similar_image (image,
@@ -360,6 +417,12 @@ _cairo_image_surface_scale_filter (cairo_surface_t *image,
horizontal_scale_transpose (image, tmp, x_factor, resize_filter);
horizontal_scale_transpose (tmp, scaled, y_factor, resize_filter);
+ /* FIXME
+ if (resize_filter->task != NULL) {
+ gboolean terminated = TRUE;
+ gth_async_task_set_data (resize_filter->task, &terminated, NULL, NULL);
+ }*/
+
resize_filter_destroy (resize_filter);
cairo_surface_destroy (tmp);
@@ -368,32 +431,15 @@ _cairo_image_surface_scale_filter (cairo_surface_t *image,
cairo_surface_t *
-_cairo_image_surface_scale (cairo_surface_t *image,
- int scaled_width,
- int scaled_height,
- gboolean high_quality)
+_cairo_image_surface_scale (cairo_surface_t *image,
+ int scaled_width,
+ int scaled_height,
+ scale_filter_t filter,
+ GthAsyncTask *task)
{
-#if 0
-
- GdkPixbuf *p;
- GdkPixbuf *scaled_p;
- cairo_surface_t *scaled;
-
- p = _gdk_pixbuf_new_from_cairo_surface (image);
- scaled_p = _gdk_pixbuf_scale_simple_safe (p, scaled_width, scaled_height, high_quality ? GDK_INTERP_BILINEAR : GDK_INTERP_NEAREST);
- scaled = _cairo_image_surface_create_from_pixbuf (scaled_p);
-
- g_object_unref (scaled_p);
- g_object_unref (p);
-
- return scaled;
-
-#else
-
- if (high_quality)
- return _cairo_image_surface_scale_filter (image, scaled_width, scaled_height, FILTER_TRIANGLE);
- else
- return _cairo_image_surface_scale_nearest (image, scaled_width, scaled_height);
-
-#endif
+ return _cairo_image_surface_scale_filter (image,
+ scaled_width,
+ scaled_height,
+ filter,
+ task);
}
diff --git a/extensions/file_tools/cairo-scale.h b/gthumb/cairo-scale.h
similarity index 64%
rename from extensions/file_tools/cairo-scale.h
rename to gthumb/cairo-scale.h
index 3e6563c..e8fa062 100644
--- a/extensions/file_tools/cairo-scale.h
+++ b/gthumb/cairo-scale.h
@@ -19,19 +19,34 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef CAIRO_ROTATE_H
-#define CAIRO_ROTATE_H
+#ifndef CAIRO_SCALE_H
+#define CAIRO_SCALE_H
#include <glib.h>
-#include <gdk/gdk.h>
+#include "gth-async-task.h"
G_BEGIN_DECLS
-cairo_surface_t * _cairo_image_surface_scale (cairo_surface_t *image,
- int width,
- int height,
- gboolean high_quality);
+
+typedef enum /*< skip >*/ {
+ SCALE_FILTER_POINT = 0,
+ SCALE_FILTER_BOX,
+ SCALE_FILTER_TRIANGLE,
+ SCALE_FILTER_LANCZOS,
+ N_SCALE_FILTERS,
+
+ SCALE_FILTER_FAST = SCALE_FILTER_POINT,
+ SCALE_FILTER_GOOD = SCALE_FILTER_BOX,
+ SCALE_FILTER_BEST = SCALE_FILTER_LANCZOS
+} scale_filter_t;
+
+
+cairo_surface_t * _cairo_image_surface_scale (cairo_surface_t *image,
+ int width,
+ int height,
+ scale_filter_t quality,
+ GthAsyncTask *task);
G_END_DECLS
-#endif /* CAIRO_ROTATE_H */
+#endif /* CAIRO_SCALE_H */
diff --git a/gthumb/cairo-utils.c b/gthumb/cairo-utils.c
index d5ec6c5..9aa7360 100644
--- a/gthumb/cairo-utils.c
+++ b/gthumb/cairo-utils.c
@@ -340,29 +340,6 @@ _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,
- cairo_filter_t filter)
-{
- cairo_surface_t *scaled;
- cairo_t *cr;
-
- scaled = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
- cr = cairo_create (scaled);
- cairo_scale (cr, (double) width / cairo_image_surface_get_width (surface), (double) height / cairo_image_surface_get_height (surface));
- cairo_set_source_surface (cr, surface, 0, 0);
- cairo_pattern_set_filter (cairo_get_source (cr), filter);
- cairo_rectangle (cr, 0, 0, cairo_image_surface_get_width (surface), cairo_image_surface_get_height (surface));
- cairo_fill (cr);
-
- cairo_destroy (cr);
-
- return scaled;
-}
-
-
void
_cairo_image_surface_transform_get_steps (cairo_format_t format,
int width,
diff --git a/gthumb/cairo-utils.h b/gthumb/cairo-utils.h
index 2da4e63..0acbc1f 100644
--- a/gthumb/cairo-utils.h
+++ b/gthumb/cairo-utils.h
@@ -160,10 +160,6 @@ cairo_surface_t * _cairo_image_surface_copy_subsurface (cairo_surface_t
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,
- cairo_filter_t filter);
void _cairo_image_surface_transform_get_steps (cairo_format_t format,
int width,
int height,
@@ -210,7 +206,7 @@ void _cairo_draw_slide (cairo_t
double image_height,
GdkColor *frame_color,
gboolean draw_inner_border);
-void _cairo_paint_grid (cairo_t *cr,
+void _cairo_paint_grid (cairo_t *cr,
cairo_rectangle_int_t *rectangle,
GthGridType grid_type);
diff --git a/gthumb/gth-image-navigator.c b/gthumb/gth-image-navigator.c
index 2065971..01fedab 100644
--- a/gthumb/gth-image-navigator.c
+++ b/gthumb/gth-image-navigator.c
@@ -22,7 +22,7 @@
#include <config.h>
#include <math.h>
#include <gdk/gdkkeysyms.h>
-#include "cairo-utils.h"
+#include "cairo-scale.h"
#include "gth-image-navigator.h"
#include "gth-image-viewer.h"
#include "gtk-utils.h"
@@ -393,10 +393,11 @@ update_popup_geometry (NavigatorPopup *nav_popup)
nav_popup->popup_height = MAX ((int) floor (nav_popup->zoom_factor * zoomed_height + 0.5), 1);
cairo_surface_destroy (nav_popup->image);
- nav_popup->image = _cairo_image_surface_scale_to (gth_image_viewer_get_current_image (nav_popup->viewer),
- nav_popup->popup_width,
- nav_popup->popup_height,
- CAIRO_FILTER_GOOD);
+ nav_popup->image = _cairo_image_surface_scale (gth_image_viewer_get_current_image (nav_popup->viewer),
+ nav_popup->popup_width,
+ nav_popup->popup_height,
+ SCALE_FILTER_GOOD,
+ NULL);
/* visible area size */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]