[gthumb] cairo scale: fixed lanczos interpolation, added mitchell-netravali
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gthumb] cairo scale: fixed lanczos interpolation, added mitchell-netravali
- Date: Thu, 5 Sep 2013 18:38:24 +0000 (UTC)
commit 05bcda3f7ead13b46b669849b461eea2894d8f64
Author: Paolo Bacchilega <paobac src gnome org>
Date: Thu Sep 5 20:30:00 2013 +0200
cairo scale: fixed lanczos interpolation, added mitchell-netravali
extensions/file_tools/gth-file-tool-resize.c | 2 +-
gthumb/cairo-scale.c | 117 ++++++++++++++++++--------
gthumb/cairo-scale.h | 6 +-
3 files changed, 85 insertions(+), 40 deletions(-)
---
diff --git a/extensions/file_tools/gth-file-tool-resize.c b/extensions/file_tools/gth-file-tool-resize.c
index 0ce4eb0..ada52d2 100644
--- a/extensions/file_tools/gth-file-tool-resize.c
+++ b/extensions/file_tools/gth-file-tool-resize.c
@@ -671,7 +671,7 @@ gth_file_tool_resize_get_options (GthFileTool *base)
gtk_combo_box_set_active (GTK_COMBO_BOX (self->priv->ratio_combobox),
g_settings_get_enum (self->priv->settings, PREF_RESIZE_ASPECT_RATIO));
- gth_image_viewer_set_zoom_quality (GTH_IMAGE_VIEWER (viewer), GTH_ZOOM_QUALITY_LOW);
+ gth_image_viewer_set_zoom_quality (GTH_IMAGE_VIEWER (viewer), GTH_ZOOM_QUALITY_HIGH);
return options;
}
diff --git a/gthumb/cairo-scale.c b/gthumb/cairo-scale.c
index e267514..9f293b9 100644
--- a/gthumb/cairo-scale.c
+++ b/gthumb/cairo-scale.c
@@ -32,7 +32,7 @@
#define EPSILON ((ScaleReal) 1.0e-16)
-typedef float ScaleReal;
+typedef double ScaleReal;
typedef ScaleReal (*weight_func_t) (ScaleReal distance);
@@ -202,7 +202,7 @@ sinc_fast (ScaleReal x)
{
if (x > 4.0) {
const ScaleReal alpha = G_PI * x;
- return sin (alpha) / alpha;
+ return sin ((double) alpha) / alpha;
}
{
@@ -213,33 +213,60 @@ sinc_fast (ScaleReal x)
const ScaleReal xx = x*x;
/*
- * Maximum absolute relative error 6.3e-6 < 1/2^17.
+ * Maximum absolute relative error 1.2e-12 < 1/2^39.
*/
- const ScaleReal c0 = 0.173610016489197553621906385078711564924e-2L;
- const ScaleReal c1 = -0.384186115075660162081071290162149315834e-3L;
- const ScaleReal c2 = 0.393684603287860108352720146121813443561e-4L;
- const ScaleReal c3 = -0.248947210682259168029030370205389323899e-5L;
- const ScaleReal c4 = 0.107791837839662283066379987646635416692e-6L;
- const ScaleReal c5 = -0.324874073895735800961260474028013982211e-8L;
- const ScaleReal c6 = 0.628155216606695311524920882748052490116e-10L;
- const ScaleReal c7 = -0.586110644039348333520104379959307242711e-12L;
- const ScaleReal 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;
+ const ScaleReal c0 = 0.173611111110910715186413700076827593074e-2L;
+ const ScaleReal c1 = -0.289105544717893415815859968653611245425e-3L;
+ const ScaleReal c2 = 0.206952161241815727624413291940849294025e-4L;
+ const ScaleReal c3 = -0.834446180169727178193268528095341741698e-6L;
+ const ScaleReal c4 = 0.207010104171026718629622453275917944941e-7L;
+ const ScaleReal c5 = -0.319724784938507108101517564300855542655e-9L;
+ const ScaleReal c6 = 0.288101675249103266147006509214934493930e-11L;
+ const ScaleReal c7 = -0.118218971804934245819960233886876537953e-13L;
+ const ScaleReal p = c0+xx*(c1+xx*(c2+xx*(c3+xx*(c4+xx*(c5+xx*(c6+xx*c7))))));
+ const ScaleReal d0 = 1.0L;
+ const ScaleReal d1 = 0.547981619622284827495856984100563583948e-1L;
+ const ScaleReal d2 = 0.134226268835357312626304688047086921806e-2L;
+ const ScaleReal d3 = 0.178994697503371051002463656833597608689e-4L;
+ const ScaleReal d4 = 0.114633394140438168641246022557689759090e-6L;
+ const ScaleReal q = d0+xx*(d1+xx*(d2+xx*(d3+xx*d4)));
+
+ return ((xx-1.0)*(xx-4.0)*(xx-9.0)*(xx-16.0)/q*p);
}
}
+static ScaleReal inline
+mitchell_netravali (ScaleReal x)
+{
+ ScaleReal xx;
+
+ if (x >= 2.0)
+ return 0.0;
+
+ xx = x * x;
+ if ((x >= 0.0) && (x < 1.0))
+ x = (21 * xx * x) - (36 * xx) + 16;
+ else /* (x >= 1.0) && (x < 2.0) */
+ x = (-7 * xx * x) + (36 * xx) - (60 * x) + 32;
+
+ return x / 18.0;
+}
+
+
static struct {
weight_func_t weight_func;
ScaleReal support;
}
const filters[N_SCALE_FILTERS] = {
- { box, .0 },
- { box, .5 },
- { triangle, 1.0 },
- { cubic, 2.0 },
- { sinc_fast, 3.0 }
+ { box, .0 },
+ { box, .5 },
+ { triangle, 1.0 },
+ { cubic, 2.0 },
+ { sinc_fast, 2.0 },
+ { sinc_fast, 3.0 },
+ { mitchell_netravali, 2.0 }
};
@@ -256,19 +283,26 @@ typedef struct {
} resize_filter_t;
+static void
+resize_filter_set_type (resize_filter_t *resize_filter,
+ scale_filter_t filter_type)
+{
+ resize_filter->weight_func = filters[filter_type].weight_func;
+ resize_filter->support = filters[filter_type].support;
+}
+
+
static resize_filter_t *
-resize_filter_create (scale_filter_t filter_type,
- GthAsyncTask *task)
+resize_filter_create (GthAsyncTask *task)
{
resize_filter_t *resize_filter;
resize_filter = g_new (resize_filter_t, 1);
- 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;
+ resize_filter_set_type (resize_filter, SCALE_FILTER_TRIANGLE);
return resize_filter;
}
@@ -285,12 +319,20 @@ static ScaleReal inline
resize_filter_get_weight (resize_filter_t *resize_filter,
ScaleReal distance)
{
- ScaleReal scale = 1.0;
+ ScaleReal window = 1.0;
- if (resize_filter->weight_func == sinc_fast)
- scale = resize_filter->weight_func (fabs (distance));
+ if (resize_filter->weight_func == sinc_fast) {
+ ScaleReal x = fabs (distance);
- return scale * resize_filter->weight_func (fabs (distance));
+ if (x == 0)
+ window = 1.0;
+ else if ((x > 0) && (x < resize_filter->support))
+ window = resize_filter->weight_func (x / resize_filter->support);
+ else
+ window = 0.0;
+ }
+
+ return window * resize_filter->weight_func (fabs (distance));
}
@@ -332,8 +374,10 @@ horizontal_scale_transpose (cairo_surface_t *image,
scale = MAX ((ScaleReal) 1.0 / scale_factor + EPSILON, 1.0);
support = scale * resize_filter_get_support (resize_filter);
- if (support < 0.5)
+ if (support < 0.5) {
support = 0.5;
+ scale = 1.0;
+ }
image_width = cairo_image_surface_get_width (image);
scaled_width = cairo_image_surface_get_width (scaled);
@@ -364,11 +408,9 @@ horizontal_scale_transpose (cairo_surface_t *image,
gth_async_task_set_data (resize_filter->task, NULL, NULL, &progress);
}
- bisect = ((ScaleReal) y + 0.5) / scale + EPSILON;
- start = bisect - support + 0.5;
- start = CLAMP (start, 0, image_width - 1);
- stop = bisect + support + 0.5;
- stop = CLAMP (stop, 0, image_width - 1);
+ bisect = ((ScaleReal) y + 0.5) / scale_factor + EPSILON;
+ start = MAX (bisect - support + 0.5, 0);
+ stop = MIN (bisect + support + 0.5, (ScaleReal) image_width);
density = 0.0;
for (n = 0; n < stop - start; n++) {
@@ -432,10 +474,10 @@ horizontal_scale_transpose (cairo_surface_t *image,
p_src_pixel += 4;
}
- p_dest_pixel[CAIRO_RED] = CLAMP_PIXEL (r+0.5);
- p_dest_pixel[CAIRO_GREEN] = CLAMP_PIXEL (g+0.5);
- p_dest_pixel[CAIRO_BLUE] = CLAMP_PIXEL (b+0.5);
- p_dest_pixel[CAIRO_ALPHA] = CLAMP_PIXEL (a+0.5);
+ p_dest_pixel[CAIRO_RED] = CLAMP_PIXEL (r + 0.5);
+ p_dest_pixel[CAIRO_GREEN] = CLAMP_PIXEL (g + 0.5);
+ p_dest_pixel[CAIRO_BLUE] = CLAMP_PIXEL (b + 0.5);
+ p_dest_pixel[CAIRO_ALPHA] = CLAMP_PIXEL (a + 0.5);
#endif /* HAVE_VECTOR_OPERATIONS */
@@ -486,7 +528,8 @@ _cairo_image_surface_scale (cairo_surface_t *image,
g_once_init_leave (&coefficients_initialization, 1);
}
- resize_filter = resize_filter_create (filter, task);
+ resize_filter = resize_filter_create (task);
+ resize_filter_set_type (resize_filter, filter);
resize_filter->total_lines = scaled_width + scaled_height;
resize_filter->processed_lines = 0;
diff --git a/gthumb/cairo-scale.h b/gthumb/cairo-scale.h
index 1533ebc..dd85c0a 100644
--- a/gthumb/cairo-scale.h
+++ b/gthumb/cairo-scale.h
@@ -36,11 +36,13 @@ typedef enum /*< skip >*/ {
SCALE_FILTER_BOX,
SCALE_FILTER_TRIANGLE,
SCALE_FILTER_CUBIC,
- SCALE_FILTER_LANCZOS_3,
+ SCALE_FILTER_LANCZOS2,
+ SCALE_FILTER_LANCZOS3,
+ SCALE_FILTER_MITCHELL_NETRAVALI,
N_SCALE_FILTERS,
SCALE_FILTER_FAST = SCALE_FILTER_POINT,
- SCALE_FILTER_BEST = SCALE_FILTER_LANCZOS_3,
+ SCALE_FILTER_BEST = SCALE_FILTER_LANCZOS3,
SCALE_FILTER_GOOD = SCALE_FILTER_TRIANGLE
} scale_filter_t;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]