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 */
}
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;
}
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,
+ ¶ms.b))
+ params.b = 1.0 / 3.0;
+ if (!options
+ || !gst_structure_get_double (options, GST_RESAMPLER_OPT_CUBIC_C,
+ ¶ms.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;
* 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
*
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:
*
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;
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;