[FFmpeg-devel] [PATCH 2/2] lavfi/drawtext: add option for drawing border around text
Ramiro Polla
ramiro.polla at gmail.com
Sat Jan 18 07:03:37 CET 2014
On Fri, Jan 10, 2014 at 6:46 AM, Stefano Sabatini <stefasab at gmail.com> wrote:
> On date Friday 2014-01-10 04:36:36 -0200, Ramiro Polla encoded:
>>
>
>> From 56ca123357def67b281a28143a9faa52ecad603b Mon Sep 17 00:00:00 2001
>> From: Ramiro Polla <ramiro.polla at gmail.com>
>> Date: Fri, 10 Jan 2014 04:30:09 -0200
>> Subject: [PATCH 2/2] lavfi/drawtext: add option for drawing border around
>> text
>>
>
>> ---
>> doc/filters.texi | 10 +++++++++
>> libavfilter/vf_drawtext.c | 50 +++++++++++++++++++++++++++++++++++++++------
>> 2 files changed, 54 insertions(+), 6 deletions(-)
>
> Reminder: missing micro bump
done
>> diff --git a/doc/filters.texi b/doc/filters.texi
>> index c896edb..f32a969 100644
>> --- a/doc/filters.texi
>> +++ b/doc/filters.texi
>> @@ -3548,6 +3548,16 @@ option, check the "Color" section in the ffmpeg-utils manual.
>>
>> The default value of @var{boxcolor} is "white".
>>
>
>> + at item borderw
>> +The width of the border to be drawn around the text using @var{bordercolor}.
>> +The default value of @var{borderw} is 0.
>
> Set the width ...
>
>
>> + at item bordercolor
>> +The color to be used for drawing border around text. For the syntax of this
>> +option, check the "Color" section in the ffmpeg-utils manual.
>
> Set the color ...
>
> (the other options should be fixed as well).
Done for the ones added in this patch.
>> +
>> +The default value of @var{bordercolor} is "black".
>> +
>> @item expansion
>> Select how the @var{text} is expanded. Can be either @code{none},
>> @code{strftime} (deprecated) or
>> diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c
>> index 2dd95ce..7e92dd6 100644
>> --- a/libavfilter/vf_drawtext.c
>> +++ b/libavfilter/vf_drawtext.c
>> @@ -50,6 +50,7 @@
>> #include <ft2build.h>
>> #include FT_FREETYPE_H
>> #include FT_GLYPH_H
>> +#include FT_STROKER_H
>> #if CONFIG_FONTCONFIG
>> #include <fontconfig/fontconfig.h>
>> #endif
>> @@ -134,6 +135,7 @@ typedef struct {
>> int max_glyph_w; ///< max glyph width
>> int max_glyph_h; ///< max glyph height
>> int shadowx, shadowy;
>> + int borderw; ///< border width
>> unsigned int fontsize; ///< font size to use
>>
>> short int draw_box; ///< draw box around text - true or false
>> @@ -144,10 +146,12 @@ typedef struct {
>> FFDrawContext dc;
>> FFDrawColor fontcolor; ///< foreground color
>> FFDrawColor shadowcolor; ///< shadow color
>> + FFDrawColor bordercolor; ///< border color
>> FFDrawColor boxcolor; ///< background color
>>
>> FT_Library library; ///< freetype font library handle
>> FT_Face face; ///< freetype font face handle
>> + FT_Stroker stroker; ///< freetype stroker handle
>> struct AVTreeNode *glyphs; ///< rendered glyphs, stored using the UTF-32 char code
>> char *x_expr; ///< expression for x position
>> char *y_expr; ///< expression for y position
>> @@ -179,12 +183,14 @@ static const AVOption drawtext_options[]= {
>> {"fontcolor", "set foreground color", OFFSET(fontcolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, CHAR_MIN, CHAR_MAX, FLAGS},
>> {"boxcolor", "set box color", OFFSET(boxcolor.rgba), AV_OPT_TYPE_COLOR, {.str="white"}, CHAR_MIN, CHAR_MAX, FLAGS},
>> {"shadowcolor", "set shadow color", OFFSET(shadowcolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, CHAR_MIN, CHAR_MAX, FLAGS},
>> + {"bordercolor", "set border color", OFFSET(bordercolor.rgba), AV_OPT_TYPE_COLOR, {.str="black"}, CHAR_MIN, CHAR_MAX, FLAGS},
>> {"box", "set box", OFFSET(draw_box), AV_OPT_TYPE_INT, {.i64=0}, 0, 1 , FLAGS},
>> {"fontsize", "set font size", OFFSET(fontsize), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX , FLAGS},
>> {"x", "set x expression", OFFSET(x_expr), AV_OPT_TYPE_STRING, {.str="0"}, CHAR_MIN, CHAR_MAX, FLAGS},
>> {"y", "set y expression", OFFSET(y_expr), AV_OPT_TYPE_STRING, {.str="0"}, CHAR_MIN, CHAR_MAX, FLAGS},
>> {"shadowx", "set x", OFFSET(shadowx), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX , FLAGS},
>> {"shadowy", "set y", OFFSET(shadowy), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX , FLAGS},
>> + {"borderw", "set border width", OFFSET(borderw), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX , FLAGS},
>> {"tabsize", "set tab size", OFFSET(tabsize), AV_OPT_TYPE_INT, {.i64=4}, 0, INT_MAX , FLAGS},
>> {"basetime", "set base time", OFFSET(basetime), AV_OPT_TYPE_INT64, {.i64=AV_NOPTS_VALUE}, INT64_MIN, INT64_MAX , FLAGS},
>> #if FF_API_DRAWTEXT_OLD_TIMELINE
>> @@ -245,6 +251,7 @@ typedef struct {
>> FT_Glyph *glyph;
>> uint32_t code;
>> FT_Bitmap bitmap; ///< array holding bitmaps of font
>> + FT_Bitmap border_bitmap; ///< array holding bitmaps of font border
>> FT_BBox bbox;
>> int advance;
>> int bitmap_left;
>> @@ -285,6 +292,13 @@ static int load_glyph(AVFilterContext *ctx, Glyph **glyph_ptr, uint32_t code)
>> ret = AVERROR(EINVAL);
>> goto error;
>> }
>
>> + if (s->borderw) {
>> + FT_Glyph border_glyph = *glyph->glyph;
>> + FT_Glyph_StrokeBorder(&border_glyph, s->stroker, 0, 0);
>> + FT_Glyph_To_Bitmap(&border_glyph, FT_RENDER_MODE_NORMAL, 0, 1);
>> + bitmapglyph = (FT_BitmapGlyph) border_glyph;
>> + glyph->border_bitmap = bitmapglyph->bitmap;
>> + }
>
> Probably you want to add some error checks.
done
>> if (FT_Glyph_To_Bitmap(glyph->glyph, FT_RENDER_MODE_NORMAL, 0, 1)) {
>> ret = AVERROR(EINVAL);
>> goto error;
>> @@ -490,6 +504,16 @@ static av_cold int init(AVFilterContext *ctx)
>> return AVERROR(EINVAL);
>> }
>>
>> + if (s->borderw) {
>> + err = FT_Stroker_New(s->library, &s->stroker);
>> + if (err) {
>> + av_log(ctx, AV_LOG_ERROR, "Coult not init FT stroker\n");
>
>> + return AVERROR(EINVAL);
>
> AVERROR_EXTERNAL
done
>> + }
>> + FT_Stroker_Set(s->stroker, s->borderw << 6, FT_STROKER_LINECAP_ROUND,
>> + FT_STROKER_LINEJOIN_ROUND, 0);
>> + }
>> +
>> s->use_kerning = FT_HAS_KERNING(s->face);
>>
>> /* load the fallback glyph with code 0 */
>> @@ -546,6 +570,7 @@ static av_cold void uninit(AVFilterContext *ctx)
>> s->glyphs = NULL;
>>
>> FT_Done_Face(s->face);
>> + FT_Stroker_Done(s->stroker);
>> FT_Done_FreeType(s->library);
>>
>> av_bprint_finalize(&s->expanded_text, NULL);
>> @@ -565,6 +590,7 @@ static int config_input(AVFilterLink *inlink)
>> ff_draw_init(&s->dc, inlink->format, 0);
>> ff_draw_color(&s->dc, &s->fontcolor, s->fontcolor.rgba);
>> ff_draw_color(&s->dc, &s->shadowcolor, s->shadowcolor.rgba);
>> + ff_draw_color(&s->dc, &s->bordercolor, s->bordercolor.rgba);
>> ff_draw_color(&s->dc, &s->boxcolor, s->boxcolor.rgba);
>>
>> s->var_values[VAR_w] = s->var_values[VAR_W] = s->var_values[VAR_MAIN_W] = inlink->w;
>> @@ -812,7 +838,8 @@ static int expand_text(AVFilterContext *ctx)
>> }
>>
>> static int draw_glyphs(DrawTextContext *s, AVFrame *frame,
>> - int width, int height, const uint8_t rgbcolor[4], FFDrawColor *color, int x, int y)
>> + int width, int height, const uint8_t rgbcolor[4],
>> + FFDrawColor *color, int x, int y, int border)
>> {
>> char *text = s->expanded_text.str;
>> uint32_t code = 0;
>> @@ -821,6 +848,7 @@ static int draw_glyphs(DrawTextContext *s, AVFrame *frame,
>> Glyph *glyph = NULL;
>>
>> for (i = 0, p = text; *p; i++) {
>> + FT_Bitmap bitmap;
>> Glyph dummy = { 0 };
>> GET_UTF8(code, *p++, continue;);
>>
>> @@ -831,6 +859,11 @@ static int draw_glyphs(DrawTextContext *s, AVFrame *frame,
>> dummy.code = code;
>> glyph = av_tree_find(s->glyphs, &dummy, (void *)glyph_cmp, NULL);
>>
>
>> + if (border)
>> + bitmap = glyph->border_bitmap;
>> + else
>> + bitmap = glyph->bitmap;
>
> nit++: bitmap = border ? ...;
done
> [...]
>
> Should be fine otherwise if works as expected.
One more change in this patch is in draw_glyphs(), borderw is
subtracted from the position while drawing the border. The border was
not correct around the text in the previous patch.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0002-lavfi-drawtext-add-option-for-drawing-border-around-.patch
Type: text/x-patch
Size: 9932 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20140118/33a417da/attachment.bin>
More information about the ffmpeg-devel
mailing list