resampler: add parameters to cubic filter
authorWim Taymans <wtaymans@redhat.com>
Sun, 26 Oct 2014 04:58:56 +0000 (05:58 +0100)
committerWim Taymans <wtaymans@redhat.com>
Wed, 29 Oct 2014 15:26:10 +0000 (16:26 +0100)
Improve cubic filter and add parameters. Switch to mitchell filter
by default.

gst-libs/gst/video/resampler.c
gst-libs/gst/video/resampler.h
gst-libs/gst/video/video-converter.c

index 54cbde4..2fdf295 100644 (file)
@@ -38,6 +38,8 @@ struct _ResamplerParams
 
     gdouble (*get_tap) (ResamplerParams * params, gint l, gint xi, gdouble x);
 
+  /* for cubic */
+  gdouble b, c;
   /* used by lanczos */
   gdouble ex, fx, dx;
   /* extra params */
@@ -91,33 +93,43 @@ get_linear_tap (ResamplerParams * params, gint l, gint xi, gdouble x)
 }
 
 static gdouble
-bicubic (gdouble s)
+bicubic (gdouble s, gdouble b, gdouble c)
 {
+  gdouble s2, s3;
+
   s = fabs (s);
+  s2 = s * s;
+  s3 = s2 * s;
 
   if (s <= 1.0)
-    return 3.0 * (s * s * s) / 2.0 - 5.0 * (s * s) / 2.0 + 1.0;
+    return ((12.0 - 9.0 * b - 6.0 * c) * s3 +
+        (-18.0 + 12.0 * b + 6.0 * c) * s2 + (6.0 - 2.0 * b)) / 6.0;
   else if (s <= 2.0)
-    return -1.0 * (s * s * s) / 2.0 + 5.0 * (s * s) / 2.0 - 4.0 * s + 2.0;
+    return ((-b - 6.0 * c) * s3 +
+        (6.0 * b + 30.0 * c) * s2 +
+        (-12.0 * b - 48.0 * c) * s + (8.0 * b + 24.0 * c)) / 6.0;
   else
     return 0.0;
 }
 
 static gdouble
-get_bicubic_tap (ResamplerParams * params, gint l, gint xi, gdouble x)
+get_cubic_tap (ResamplerParams * params, gint l, gint xi, gdouble x)
 {
-  gdouble a, res;
+  gdouble a, b, c, res;
 
   a = x - (xi + 1);
 
+  b = params->b;
+  c = params->c;
+
   if (l == 0)
-    res = bicubic (1.0 + a);
+    res = bicubic (1.0 + a, b, c);
   else if (l == 1)
-    res = bicubic (a);
+    res = bicubic (a, b, c);
   else if (l == 2)
-    res = bicubic (1.0 - a);
+    res = bicubic (1.0 - a, b, c);
   else
-    res = bicubic (2.0 - a);
+    res = bicubic (2.0 - a, b, c);
 
   return res;
 }
@@ -277,9 +289,17 @@ gst_resampler_init (GstResampler * resampler,
       if (n_taps == 0)
         n_taps = 2;
       break;
-    case GST_RESAMPLER_METHOD_BICUBIC:
+    case GST_RESAMPLER_METHOD_CUBIC:
+      if (!options
+          || !gst_structure_get_double (options, GST_RESAMPLER_OPT_CUBIC_B,
+              &params.b))
+        params.b = 1.0 / 3.0;
+      if (!options
+          || !gst_structure_get_double (options, GST_RESAMPLER_OPT_CUBIC_C,
+              &params.c))
+        params.c = 1.0 / 3.0;
       n_taps = 4;
-      params.get_tap = get_bicubic_tap;
+      params.get_tap = get_cubic_tap;
       break;
     case GST_RESAMPLER_METHOD_SINC:
       params.get_tap = get_sinc_tap;
index e11096e..1d525d2 100644 (file)
@@ -32,7 +32,7 @@ typedef struct _GstResampler GstResampler;
  *    upsampling and drops when downsampling
  * @GST_RESAMPLER_METHOD_LINEAR: Uses linear interpolation to reconstruct
  *    missing samples and averaging to downsample
- * @GST_RESAMPLER_METHOD_BICUBIC: Uses bicubic interpolation
+ * @GST_RESAMPLER_METHOD_CUBIC: Uses cubic interpolation
  * @GST_RESAMPLER_METHOD_SINC: Uses sinc interpolation
  * @GST_RESAMPLER_METHOD_LANCZOS: Uses lanczos interpolation
  *
@@ -43,12 +43,43 @@ typedef struct _GstResampler GstResampler;
 typedef enum {
   GST_RESAMPLER_METHOD_NEAREST,
   GST_RESAMPLER_METHOD_LINEAR,
-  GST_RESAMPLER_METHOD_BICUBIC,
+  GST_RESAMPLER_METHOD_CUBIC,
   GST_RESAMPLER_METHOD_SINC,
   GST_RESAMPLER_METHOD_LANCZOS,
 } GstResamplerMethod;
 
 /**
+ * GST_RESAMPLER_OPT_CUBIC_B:
+ *
+ * G_TYPE_DOUBLE, B parameter of the cubic filter. The B
+ * parameter controls the bluriness. Values between 0.0 and
+ * 2.0 are accepted. 1/3 is the default.
+ *
+ * Below are some values of popular filters:
+ *                    B       C
+ * Hermite           0.0     0.0
+ * Spline            1.0     0.0
+ * Catmull-Rom       0.0     1/2
+ * Mitchell          1/3     1/3
+ * Robidoux          0.3782  0.3109
+ * Robidoux
+ *  Sharp            0.2620  0.3690
+ * Robidoux
+ *  Soft             0.6796  0.1602
+ */
+#define GST_RESAMPLER_OPT_CUBIC_B      "GstResampler.cubic-b"
+/**
+ * GST_RESAMPLER_OPT_CUBIC_C:
+ *
+ * G_TYPE_DOUBLE, C parameter of the cubic filter. The C
+ * parameter controls the Keys alpha value. Values between 0.0 and
+ * 2.0 are accepted. 1/3 is the default.
+ *
+ * See #GST_RESAMPLER_OPT_CUBIC_B for some more common values
+ */
+#define GST_RESAMPLER_OPT_CUBIC_C      "GstResampler.cubic-c"
+
+/**
  * GST_RESAMPLER_OPT_ENVELOPE:
  *
  * G_TYPE_DOUBLE, specifies the size of filter envelope for
index 87158c7..2728a79 100644 (file)
@@ -312,7 +312,7 @@ chain_hscale (GstVideoConverter * convert, GstLineCacheNeedLineFunc need_line)
   if (!gst_structure_get_enum (convert->config,
           GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD, GST_TYPE_RESAMPLER_METHOD,
           &method))
-    method = GST_RESAMPLER_METHOD_LINEAR;
+    method = GST_RESAMPLER_METHOD_CUBIC;
   if (!gst_structure_get_uint (convert->config,
           GST_VIDEO_CONVERTER_OPT_RESAMPLER_TAPS, &taps))
     taps = 0;
@@ -341,7 +341,7 @@ chain_vscale (GstVideoConverter * convert, GstLineCacheNeedLineFunc need_line)
   if (!gst_structure_get_enum (convert->config,
           GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD, GST_TYPE_RESAMPLER_METHOD,
           &method))
-    method = GST_RESAMPLER_METHOD_LINEAR;
+    method = GST_RESAMPLER_METHOD_CUBIC;
   if (!gst_structure_get_uint (convert->config,
           GST_VIDEO_CONVERTER_OPT_RESAMPLER_TAPS, &taps))
     taps = 0;