From 9b2c57bef5e2f3f61a5fd708ba7d5351f5b3f386 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Sat, 11 Apr 2015 19:04:25 +0200 Subject: drawtext: Add an alpha option And document both `draw` and `alpha`. Signed-off-by: Luca Barbato --- libavfilter/vf_drawtext.c | 48 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 10 deletions(-) (limited to 'libavfilter') diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c index 82e805b394..97d44c61f9 100644 --- a/libavfilter/vf_drawtext.c +++ b/libavfilter/vf_drawtext.c @@ -152,6 +152,9 @@ typedef struct DrawTextContext { char *d_expr; AVExpr *d_pexpr; int draw; ///< set to zero to prevent drawing + char *a_expr; + AVExpr *a_pexpr; + int alpha; AVLFG prng; ///< random } DrawTextContext; @@ -176,6 +179,7 @@ static const AVOption drawtext_options[]= { { "shadowy", NULL, OFFSET(shadowy), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS }, { "tabsize", NULL, OFFSET(tabsize), AV_OPT_TYPE_INT, { .i64 = 4 }, 0, INT_MAX, FLAGS }, { "draw", "if false do not draw", OFFSET(d_expr), AV_OPT_TYPE_STRING, { .str = "1" }, .flags = FLAGS }, + { "alpha", "apply alpha while rendering", OFFSET(a_expr), AV_OPT_TYPE_STRING, { .str = "1" }, .flags = FLAGS }, { "fix_bounds", "if true, check and fix text coords to avoid clipping", OFFSET(fix_bounds), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, FLAGS }, @@ -678,6 +682,8 @@ static int config_input(AVFilterLink *inlink) (ret = av_expr_parse(&s->y_pexpr, s->y_expr, var_names, NULL, NULL, fun2_names, fun2, 0, ctx)) < 0 || (ret = av_expr_parse(&s->d_pexpr, s->d_expr, var_names, + NULL, NULL, fun2_names, fun2, 0, ctx)) < 0 || + (ret = av_expr_parse(&s->a_pexpr, s->a_expr, var_names, NULL, NULL, fun2_names, fun2, 0, ctx)) < 0) return AVERROR(EINVAL); @@ -713,7 +719,7 @@ static int config_input(AVFilterLink *inlink) #define SET_PIXEL_YUV(frame, yuva_color, val, x, y, hsub, vsub) { \ luma_pos = ((x) ) + ((y) ) * frame->linesize[0]; \ - alpha = yuva_color[3] * (val) * 129; \ + alpha = yuva_color[3] * alpha_mul * (val) * 129 / 255; \ frame->data[0][luma_pos] = (alpha * yuva_color[0] + (255*255*129 - alpha) * frame->data[0][luma_pos] ) >> 23; \ if (((x) & ((1<<(hsub)) - 1)) == 0 && ((y) & ((1<<(vsub)) - 1)) == 0) {\ chroma_pos1 = ((x) >> (hsub)) + ((y) >> (vsub)) * frame->linesize[1]; \ @@ -725,7 +731,8 @@ static int config_input(AVFilterLink *inlink) static inline int draw_glyph_yuv(AVFrame *frame, FT_Bitmap *bitmap, unsigned int x, unsigned int y, unsigned int width, unsigned int height, - const uint8_t yuva_color[4], int hsub, int vsub) + const uint8_t yuva_color[4], int hsub, int vsub, + int alpha_mul) { int r, c, alpha; unsigned int luma_pos, chroma_pos1, chroma_pos2; @@ -747,7 +754,7 @@ static inline int draw_glyph_yuv(AVFrame *frame, FT_Bitmap *bitmap, unsigned int #define SET_PIXEL_RGB(frame, rgba_color, val, x, y, pixel_step, r_off, g_off, b_off, a_off) { \ p = frame->data[0] + (x) * pixel_step + ((y) * frame->linesize[0]); \ - alpha = rgba_color[3] * (val) * 129; \ + alpha = rgba_color[3] * alpha_mul * (val) * 129 / 255; \ *(p+r_off) = (alpha * rgba_color[0] + (255*255*129 - alpha) * *(p+r_off)) >> 23; \ *(p+g_off) = (alpha * rgba_color[1] + (255*255*129 - alpha) * *(p+g_off)) >> 23; \ *(p+b_off) = (alpha * rgba_color[2] + (255*255*129 - alpha) * *(p+b_off)) >> 23; \ @@ -756,7 +763,8 @@ static inline int draw_glyph_yuv(AVFrame *frame, FT_Bitmap *bitmap, unsigned int static inline int draw_glyph_rgb(AVFrame *frame, FT_Bitmap *bitmap, unsigned int x, unsigned int y, unsigned int width, unsigned int height, int pixel_step, - const uint8_t rgba_color[4], const uint8_t rgba_map[4]) + const uint8_t rgba_color[4], const uint8_t rgba_map[4], + int alpha_mul) { int r, c, alpha; uint8_t *p; @@ -780,11 +788,12 @@ static inline int draw_glyph_rgb(AVFrame *frame, FT_Bitmap *bitmap, static inline void drawbox(AVFrame *frame, unsigned int x, unsigned int y, unsigned int width, unsigned int height, uint8_t *line[4], int pixel_step[4], uint8_t color[4], - int hsub, int vsub, int is_rgba_packed, uint8_t rgba_map[4]) + int hsub, int vsub, int is_rgba_packed, uint8_t rgba_map[4], + int alpha_mul) { int i, j, alpha; - if (color[3] != 0xFF) { + if (color[3] != 0xFF || alpha_mul != 0xFF) { if (is_rgba_packed) { uint8_t *p; for (j = 0; j < height; j++) @@ -805,7 +814,9 @@ static inline void drawbox(AVFrame *frame, unsigned int x, unsigned int y, } static int draw_glyphs(DrawTextContext *s, AVFrame *frame, - int width, int height, const uint8_t rgbcolor[4], const uint8_t yuvcolor[4], int x, int y) + int width, int height, + const uint8_t rgbcolor[4], const uint8_t yuvcolor[4], + int x, int y) { char *text = HAVE_LOCALTIME_R ? s->expanded_text : s->text; uint32_t code = 0; @@ -831,11 +842,11 @@ static int draw_glyphs(DrawTextContext *s, AVFrame *frame, if (s->is_packed_rgb) { draw_glyph_rgb(frame, &glyph->bitmap, s->positions[i].x+x, s->positions[i].y+y, width, height, - s->pixel_step[0], rgbcolor, s->rgba_map); + s->pixel_step[0], rgbcolor, s->rgba_map, s->alpha); } else { draw_glyph_yuv(frame, &glyph->bitmap, s->positions[i].x+x, s->positions[i].y+y, width, height, - yuvcolor, s->hsub, s->vsub); + yuvcolor, s->hsub, s->vsub, s->alpha); } } @@ -853,7 +864,7 @@ static int draw_text(AVFilterContext *ctx, AVFrame *frame, drawbox(frame, s->x, s->y, s->w, s->h, s->box_line, s->pixel_step, s->boxcolor, s->hsub, s->vsub, s->is_packed_rgb, - s->rgba_map); + s->rgba_map, s->alpha); if (s->shadowx || s->shadowy) { if ((ret = draw_glyphs(s, frame, width, height, @@ -889,6 +900,21 @@ static inline int normalize_double(int *n, double d) return ret; } +static void update_alpha(DrawTextContext *s) +{ + double alpha = av_expr_eval(s->a_pexpr, s->var_values, &s->prng); + + if (isnan(alpha)) + return; + + if (alpha >= 1.0) + s->alpha = 255; + else if (alpha <= 0) + s->alpha = 0; + else + s->alpha = 256 * alpha; +} + static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { AVFilterContext *ctx = inlink->dst; @@ -912,6 +938,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) s->draw = av_expr_eval(s->d_pexpr, s->var_values, &s->prng); + update_alpha(s); + normalize_double(&s->x, s->var_values[VAR_X]); normalize_double(&s->y, s->var_values[VAR_Y]); -- cgit v1.2.3