[FFmpeg-devel,1/2] avfilter/vf_geq: allow user to set interpolation method

Submitted by Paul B Mahol on Oct. 11, 2019, 4:29 p.m.

Details

Message ID 20191011162946.8644-1-onemda@gmail.com
State New
Headers show

Commit Message

Paul B Mahol Oct. 11, 2019, 4:29 p.m.
Signed-off-by: Paul B Mahol <onemda@gmail.com>
---
 doc/filters.texi     |  8 ++++++++
 libavfilter/vf_geq.c | 27 +++++++++++++++++++++++++++
 2 files changed, 35 insertions(+)

Comments

Michael Niedermayer Oct. 12, 2019, 11:58 a.m.
On Fri, Oct 11, 2019 at 06:29:45PM +0200, Paul B Mahol wrote:
> Signed-off-by: Paul B Mahol <onemda@gmail.com>
> ---
>  doc/filters.texi     |  8 ++++++++
>  libavfilter/vf_geq.c | 27 +++++++++++++++++++++++++++
>  2 files changed, 35 insertions(+)
> 
> diff --git a/doc/filters.texi b/doc/filters.texi
> index 55a8ebae56..6f9ebf6085 100644
> --- a/doc/filters.texi
> +++ b/doc/filters.texi
> @@ -11019,6 +11019,14 @@ red/green/blue component. Return 0 if there is no such component.
>  @item alpha(x, y)
>  Return the value of the pixel at location (@var{x},@var{y}) of the alpha
>  plane. Return 0 if there is no such plane.
> +
> +@item interpolation
> +Set one of interpolation methods:
> +@table @option
> +@item nearest, n
> +@item bilinear, b
> +@end table
> +Default is bilinear.
>  @end table
>  
>  For functions, if @var{x} and @var{y} are outside the area, the value will be
> diff --git a/libavfilter/vf_geq.c b/libavfilter/vf_geq.c
> index 91eb9685f9..b7932f0b04 100644
> --- a/libavfilter/vf_geq.c
> +++ b/libavfilter/vf_geq.c
> @@ -33,6 +33,12 @@
>  #include "libavutil/pixdesc.h"
>  #include "internal.h"
>  
> +enum InterpolationMethods {
> +    INTERP_NEAREST,
> +    INTERP_BILINEAR,
> +    NB_INTERP
> +};
> +
>  static const char *const var_names[] = {   "X",   "Y",   "W",   "H",   "N",   "SW",   "SH",   "T",        NULL };
>  enum                                   { VAR_X, VAR_Y, VAR_W, VAR_H, VAR_N, VAR_SW, VAR_SH, VAR_T, VAR_VARS_NB };
>  
> @@ -46,6 +52,7 @@ typedef struct GEQContext {
>      double values[VAR_VARS_NB]; ///< expression values
>      int hsub, vsub;             ///< chroma subsampling
>      int planes;                 ///< number of planes
> +    int interpolation;
>      int is_rgb;
>      int bps;
>  } GEQContext;
> @@ -70,6 +77,12 @@ static const AVOption geq_options[] = {
>      { "g",          "set green expression",       OFFSET(expr_str[G]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
>      { "blue_expr",  "set blue expression",        OFFSET(expr_str[B]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
>      { "b",          "set blue expression",        OFFSET(expr_str[B]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
> +    { "interpolation","set interpolation method", OFFSET(interpolation), AV_OPT_TYPE_INT, {.i64=INTERP_BILINEAR}, 0, NB_INTERP-1, FLAGS, "interp" },
> +    { "i",          "set interpolation method",   OFFSET(interpolation), AV_OPT_TYPE_INT, {.i64=INTERP_BILINEAR}, 0, NB_INTERP-1, FLAGS, "interp" },
> +    { "nearest",    "nearest interpolation",      0,                   AV_OPT_TYPE_CONST, {.i64=INTERP_NEAREST},  0, 0, FLAGS, "interp" },
> +    { "n",          "nearest interpolation",      0,                   AV_OPT_TYPE_CONST, {.i64=INTERP_NEAREST},  0, 0, FLAGS, "interp" },
> +    { "bilinear",   "bilinear interpolation",     0,                   AV_OPT_TYPE_CONST, {.i64=INTERP_BILINEAR}, 0, 0, FLAGS, "interp" },
> +    { "b",          "bilinear interpolation",     0,                   AV_OPT_TYPE_CONST, {.i64=INTERP_BILINEAR}, 0, 0, FLAGS, "interp" },
>      {NULL},
>  };
>  
> @@ -88,6 +101,7 @@ static inline double getpix(void *priv, double x, double y, int plane)
>      if (!src)
>          return 0;
>  
> +    if (geq->interpolation == INTERP_BILINEAR) {
>      xi = x = av_clipf(x, 0, w - 2);
>      yi = y = av_clipf(y, 0, h - 2);
>  

> @@ -104,6 +118,19 @@ static inline double getpix(void *priv, double x, double y, int plane)
>          return (1-y)*((1-x)*src[xi +  yi    * linesize] + x*src[xi + 1 +  yi    * linesize])
>                +   y *((1-x)*src[xi + (yi+1) * linesize] + x*src[xi + 1 + (yi+1) * linesize]);
>      }
> +    } else {
> +        xi = av_clipf(x, 0, w - 1);
> +        yi = av_clipf(y, 0, h - 1);

this should not drop precission to float
also possibly lrint() or something may be better than truncation for
nearest neighbor depending on definition of "nearest"

LGTM otherwise

Thanks


[...]

Patch hide | download patch | download mbox

diff --git a/doc/filters.texi b/doc/filters.texi
index 55a8ebae56..6f9ebf6085 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -11019,6 +11019,14 @@  red/green/blue component. Return 0 if there is no such component.
 @item alpha(x, y)
 Return the value of the pixel at location (@var{x},@var{y}) of the alpha
 plane. Return 0 if there is no such plane.
+
+@item interpolation
+Set one of interpolation methods:
+@table @option
+@item nearest, n
+@item bilinear, b
+@end table
+Default is bilinear.
 @end table
 
 For functions, if @var{x} and @var{y} are outside the area, the value will be
diff --git a/libavfilter/vf_geq.c b/libavfilter/vf_geq.c
index 91eb9685f9..b7932f0b04 100644
--- a/libavfilter/vf_geq.c
+++ b/libavfilter/vf_geq.c
@@ -33,6 +33,12 @@ 
 #include "libavutil/pixdesc.h"
 #include "internal.h"
 
+enum InterpolationMethods {
+    INTERP_NEAREST,
+    INTERP_BILINEAR,
+    NB_INTERP
+};
+
 static const char *const var_names[] = {   "X",   "Y",   "W",   "H",   "N",   "SW",   "SH",   "T",        NULL };
 enum                                   { VAR_X, VAR_Y, VAR_W, VAR_H, VAR_N, VAR_SW, VAR_SH, VAR_T, VAR_VARS_NB };
 
@@ -46,6 +52,7 @@  typedef struct GEQContext {
     double values[VAR_VARS_NB]; ///< expression values
     int hsub, vsub;             ///< chroma subsampling
     int planes;                 ///< number of planes
+    int interpolation;
     int is_rgb;
     int bps;
 } GEQContext;
@@ -70,6 +77,12 @@  static const AVOption geq_options[] = {
     { "g",          "set green expression",       OFFSET(expr_str[G]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
     { "blue_expr",  "set blue expression",        OFFSET(expr_str[B]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
     { "b",          "set blue expression",        OFFSET(expr_str[B]), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
+    { "interpolation","set interpolation method", OFFSET(interpolation), AV_OPT_TYPE_INT, {.i64=INTERP_BILINEAR}, 0, NB_INTERP-1, FLAGS, "interp" },
+    { "i",          "set interpolation method",   OFFSET(interpolation), AV_OPT_TYPE_INT, {.i64=INTERP_BILINEAR}, 0, NB_INTERP-1, FLAGS, "interp" },
+    { "nearest",    "nearest interpolation",      0,                   AV_OPT_TYPE_CONST, {.i64=INTERP_NEAREST},  0, 0, FLAGS, "interp" },
+    { "n",          "nearest interpolation",      0,                   AV_OPT_TYPE_CONST, {.i64=INTERP_NEAREST},  0, 0, FLAGS, "interp" },
+    { "bilinear",   "bilinear interpolation",     0,                   AV_OPT_TYPE_CONST, {.i64=INTERP_BILINEAR}, 0, 0, FLAGS, "interp" },
+    { "b",          "bilinear interpolation",     0,                   AV_OPT_TYPE_CONST, {.i64=INTERP_BILINEAR}, 0, 0, FLAGS, "interp" },
     {NULL},
 };
 
@@ -88,6 +101,7 @@  static inline double getpix(void *priv, double x, double y, int plane)
     if (!src)
         return 0;
 
+    if (geq->interpolation == INTERP_BILINEAR) {
     xi = x = av_clipf(x, 0, w - 2);
     yi = y = av_clipf(y, 0, h - 2);
 
@@ -104,6 +118,19 @@  static inline double getpix(void *priv, double x, double y, int plane)
         return (1-y)*((1-x)*src[xi +  yi    * linesize] + x*src[xi + 1 +  yi    * linesize])
               +   y *((1-x)*src[xi + (yi+1) * linesize] + x*src[xi + 1 + (yi+1) * linesize]);
     }
+    } else {
+        xi = av_clipf(x, 0, w - 1);
+        yi = av_clipf(y, 0, h - 1);
+
+        if (geq->bps > 8) {
+            const uint16_t *src16 = (const uint16_t*)src;
+            linesize /= 2;
+
+            return src16[xi + yi * linesize];
+        } else {
+            return src[xi + yi * linesize];
+        }
+    }
 }
 
 //TODO: cubic interpolate