[FFmpeg-devel] [PATCH] lavfi/hue: allow changing brightness

Stefano Sabatini stefasab at gmail.com
Thu Aug 22 12:34:24 CEST 2013


On date Wednesday 2013-08-21 18:01:23 +0000, Paul B Mahol encoded:
> Signed-off-by: Paul B Mahol <onemda at gmail.com>
> ---
>  doc/filters.texi     |  4 +++
>  libavfilter/vf_hue.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++------
>  2 files changed, 66 insertions(+), 7 deletions(-)
> 
> diff --git a/doc/filters.texi b/doc/filters.texi
> index 19d9784..a9808a1 100644
> --- a/doc/filters.texi
> +++ b/doc/filters.texi
> @@ -4715,6 +4715,10 @@ defaults to "1".
>  @item H
>  Specify the hue angle as a number of radians. It accepts an
>  expression, and defaults to "0".
> +
> + at item b
> +Specify the brightness in the [-10,10] range. It accepts an expression and
> +defaults to "0".
>  @end table

Missing command section update.

>  
>  @option{h} and @option{H} are mutually exclusive, and can't be
> diff --git a/libavfilter/vf_hue.c b/libavfilter/vf_hue.c
> index d066c40..e5017fb 100644
> --- a/libavfilter/vf_hue.c
> +++ b/libavfilter/vf_hue.c
> @@ -68,11 +68,15 @@ typedef struct {
>      float    saturation;
>      char     *saturation_expr;
>      AVExpr   *saturation_pexpr;
> +    float    brightness;
> +    char     *brightness_expr;
> +    AVExpr   *brightness_pexpr;
>      int      hsub;
>      int      vsub;
>      int32_t hue_sin;
>      int32_t hue_cos;
>      double   var_values[VAR_NB];
> +    uint8_t  lut_l[256];
>      uint8_t  lut_u[256][256];
>      uint8_t  lut_v[256][256];
>  } HueContext;
> @@ -86,6 +90,8 @@ static const AVOption hue_options[] = {
>        { .str = "1" }, .flags = FLAGS },
>      { "H", "set the hue angle radians expression", OFFSET(hue_expr), AV_OPT_TYPE_STRING,
>        { .str = NULL }, .flags = FLAGS },
> +    { "b", "set the brightness expression", OFFSET(brightness_expr), AV_OPT_TYPE_STRING,
> +      { .str = "0" }, .flags = FLAGS },
>      { NULL }
>  };
>  
> @@ -102,6 +108,16 @@ static inline void compute_sin_and_cos(HueContext *hue)
>      hue->hue_cos = rint(cos(hue->hue) * (1 << 16) * hue->saturation);
>  }
>  
> +static inline void create_luma_lut(HueContext *h)
> +{
> +    const float b = h->brightness;
> +    int i;
> +
> +    for (i = 0; i < 256; i++) {
> +        h->lut_l[i] = av_clip_uint8(i + b * 25.5);
> +    }
> +}
> +
>  static inline void create_chrominance_lut(HueContext *h, const int32_t c,
>                                            const int32_t s)
>  {
> @@ -181,14 +197,15 @@ static av_cold int init(AVFilterContext *ctx)
>          if (ret < 0)                                                    \
>              return ret;                                                 \
>      } while (0)
> +    SET_EXPR(brightness, "b");
>      SET_EXPR(saturation, "s");
>      SET_EXPR(hue_deg,    "h");
>      SET_EXPR(hue,        "H");
>  #undef SET_EXPR
>  
>      av_log(ctx, AV_LOG_VERBOSE,
> -           "H_expr:%s h_deg_expr:%s s_expr:%s\n",
> -           hue->hue_expr, hue->hue_deg_expr, hue->saturation_expr);
> +           "H_expr:%s h_deg_expr:%s s_expr:%s b_expr:%s\n",
> +           hue->hue_expr, hue->hue_deg_expr, hue->saturation_expr, hue->brightness_expr);
>      compute_sin_and_cos(hue);
>  
>      return 0;
> @@ -198,6 +215,7 @@ static av_cold void uninit(AVFilterContext *ctx)
>  {
>      HueContext *hue = ctx->priv;
>  
> +    av_expr_free(hue->brightness_pexpr);
>      av_expr_free(hue->hue_deg_pexpr);
>      av_expr_free(hue->hue_pexpr);
>      av_expr_free(hue->saturation_pexpr);
> @@ -235,6 +253,22 @@ static int config_props(AVFilterLink *inlink)
>      return 0;
>  }
>  
> +static void apply_luma_lut(HueContext *s,
> +                           uint8_t *ldst, const int dst_linesize,
> +                           uint8_t *lsrc, const int src_linesize,
> +                           int w, int h)
> +{
> +    int i;
> +
> +    while (h--) {
> +        for (i = 0; i < w; i++)
> +            ldst[i] = s->lut_l[lsrc[i]];
> +
> +        lsrc += src_linesize;
> +        ldst += dst_linesize;
> +    }
> +}
> +
>  static void apply_lut(HueContext *s,
>                        uint8_t *udst, uint8_t *vdst, const int dst_linesize,
>                        uint8_t *usrc, uint8_t *vsrc, const int src_linesize,
> @@ -267,6 +301,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpic)
>      AVFilterLink *outlink = inlink->dst->outputs[0];
>      AVFrame *outpic;
>      const int32_t old_hue_sin = hue->hue_sin, old_hue_cos = hue->hue_cos;
> +    const float old_brightness = hue->brightness;
>      int direct = 0;
>  
>      if (av_frame_is_writable(inpic)) {
> @@ -296,6 +331,17 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpic)
>          }
>      }
>  
> +    if (hue->brightness_expr) {
> +        hue->brightness = av_expr_eval(hue->brightness_pexpr, hue->var_values, NULL);
> +
> +        if (hue->brightness < -10 || hue->brightness > 10) {
> +            hue->brightness = av_clipf(hue->brightness, -10, 10);
> +            av_log(inlink->dst, AV_LOG_WARNING,
> +                   "Brightness value not in range [%d,%d]: clipping value to %0.1f\n",
> +                   -10, 10, hue->brightness);
> +        }
> +    }
> +
>      if (hue->hue_deg_expr) {
>          hue->hue_deg = av_expr_eval(hue->hue_deg_pexpr, hue->var_values, NULL);
>          hue->hue = hue->hue_deg * M_PI / 180;
> @@ -305,18 +351,22 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpic)
>      }
>  
>      av_log(inlink->dst, AV_LOG_DEBUG,
> -           "H:%0.1f*PI h:%0.1f s:%0.f t:%0.1f n:%d\n",
> -           hue->hue/M_PI, hue->hue_deg, hue->saturation,
> +           "H:%0.1f*PI h:%0.1f s:%0.f b:%0.f t:%0.1f n:%d\n",
> +           hue->hue/M_PI, hue->hue_deg, hue->saturation, hue->brightness,
>             hue->var_values[VAR_T], (int)hue->var_values[VAR_N]);
>  
>      compute_sin_and_cos(hue);
>      if (old_hue_sin != hue->hue_sin || old_hue_cos != hue->hue_cos)
>          create_chrominance_lut(hue, hue->hue_cos, hue->hue_sin);
>  
> +    if (old_brightness != hue->brightness && hue->brightness)
> +        create_luma_lut(hue);
> +
>      if (!direct) {
> -        av_image_copy_plane(outpic->data[0], outpic->linesize[0],
> -                            inpic->data[0],  inpic->linesize[0],
> -                            inlink->w, inlink->h);
> +        if (!hue->brightness)
> +            av_image_copy_plane(outpic->data[0], outpic->linesize[0],
> +                                inpic->data[0],  inpic->linesize[0],
> +                                inlink->w, inlink->h);
>          if (inpic->data[3])
>              av_image_copy_plane(outpic->data[3], outpic->linesize[3],
>                                  inpic->data[3],  inpic->linesize[3],
> @@ -327,6 +377,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpic)
>                inpic->data[1],  inpic->data[2],  inpic->linesize[1],
>                FF_CEIL_RSHIFT(inlink->w, hue->hsub),
>                FF_CEIL_RSHIFT(inlink->h, hue->vsub));
> +    if (hue->brightness)
> +        apply_luma_lut(hue, outpic->data[0], outpic->linesize[0],
> +                       inpic->data[0], inpic->linesize[0], inlink->w, inlink->h);
>  
>      if (!direct)
>          av_frame_free(&inpic);
> @@ -355,6 +408,8 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar
>          av_freep(&hue->hue_deg_expr);
>      } else if (!strcmp(cmd, "s")) {
>          SET_EXPR(saturation, "s");
> +    } else if (!strcmp(cmd, "b")) {
> +        SET_EXPR(brightness, "b");
>      } else
>          return AVERROR(ENOSYS);

LGTM otherwise if tested, thanks.
-- 
FFmpeg = Faithful and Fantastic Multimedia Programmable Extravagant Geek


More information about the ffmpeg-devel mailing list