Browse code

drawtext: add shadow support.

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Signed-off-by: Anton Khirnov <anton@khirnov.net>

Michael Niedermayer authored on 2011/02/22 09:41:52
Showing 1 changed files
... ...
@@ -55,13 +55,17 @@ typedef struct {
55 55
     char *textfile;                 ///< file with text to be drawn
56 56
     unsigned int x;                 ///< x position to start drawing text
57 57
     unsigned int y;                 ///< y position to start drawing text
58
+    int shadowx, shadowy;
58 59
     unsigned int fontsize;          ///< font size to use
59 60
     char *fontcolor_string;         ///< font color as string
60 61
     char *boxcolor_string;          ///< box color as string
62
+    char *shadowcolor_string;       ///< shadow color as string
61 63
     uint8_t fontcolor[4];           ///< foreground color
62 64
     uint8_t boxcolor[4];            ///< background color
65
+    uint8_t shadowcolor[4];         ///< shadow color
63 66
     uint8_t fontcolor_rgba[4];      ///< foreground color in RGBA
64 67
     uint8_t boxcolor_rgba[4];       ///< background color in RGBA
68
+    uint8_t shadowcolor_rgba[4];    ///< shadow color in RGBA
65 69
 
66 70
     short int draw_box;             ///< draw box around text - true or false
67 71
     int use_kerning;                ///< font kerning is used - true/false
... ...
@@ -85,10 +89,13 @@ static const AVOption drawtext_options[]= {
85 85
 {"textfile", "set text file",        OFFSET(textfile),         FF_OPT_TYPE_STRING, 0,  CHAR_MIN, CHAR_MAX },
86 86
 {"fontcolor","set foreground color", OFFSET(fontcolor_string), FF_OPT_TYPE_STRING, 0,  CHAR_MIN, CHAR_MAX },
87 87
 {"boxcolor", "set box color",        OFFSET(boxcolor_string),  FF_OPT_TYPE_STRING, 0,  CHAR_MIN, CHAR_MAX },
88
+{"shadowcolor", "set shadow color",  OFFSET(shadowcolor_string),  FF_OPT_TYPE_STRING, 0,  CHAR_MIN, CHAR_MAX },
88 89
 {"box",      "set box",              OFFSET(draw_box),         FF_OPT_TYPE_INT,    0,         0,        1 },
89 90
 {"fontsize", "set font size",        OFFSET(fontsize),         FF_OPT_TYPE_INT,   16,         1,       72 },
90 91
 {"x",        "set x",                OFFSET(x),                FF_OPT_TYPE_INT,    0,         0,  INT_MAX },
91 92
 {"y",        "set y",                OFFSET(y),                FF_OPT_TYPE_INT,    0,         0,  INT_MAX },
93
+{"shadowx",  "set x",                OFFSET(shadowx),          FF_OPT_TYPE_INT,    0,   INT_MIN,  INT_MAX },
94
+{"shadowy",  "set y",                OFFSET(shadowy),          FF_OPT_TYPE_INT,    0,   INT_MIN,  INT_MAX },
92 95
 {"tabsize",  "set tab size",         OFFSET(tabsize),          FF_OPT_TYPE_INT,    4,         0,  INT_MAX },
93 96
 
94 97
 /* FT_LOAD_* flags */
... ...
@@ -217,6 +224,7 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
217 217
     av_opt_set_defaults2(dtext, 0, 0);
218 218
     dtext->fontcolor_string = av_strdup("black");
219 219
     dtext->boxcolor_string = av_strdup("white");
220
+    dtext->shadowcolor_string = av_strdup("black");
220 221
 
221 222
     if ((err = (av_set_options_string(dtext, args, "=", ":"))) < 0) {
222 223
         av_log(ctx, AV_LOG_ERROR, "Error parsing options string: '%s'\n", args);
... ...
@@ -269,6 +277,12 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
269 269
         return err;
270 270
     }
271 271
 
272
+    if ((err = av_parse_color(dtext->shadowcolor_rgba, dtext->shadowcolor_string, -1, ctx))) {
273
+        av_log(ctx, AV_LOG_ERROR,
274
+               "Invalid shadow color '%s'\n", dtext->shadowcolor_string);
275
+        return err;
276
+    }
277
+
272 278
     if ((err = FT_Init_FreeType(&(dtext->library)))) {
273 279
         av_log(ctx, AV_LOG_ERROR,
274 280
                "Could not load FreeType: %s\n", FT_ERRMSG(err));
... ...
@@ -338,6 +352,7 @@ static av_cold void uninit(AVFilterContext *ctx)
338 338
     av_freep(&dtext->fontcolor_string);
339 339
     av_freep(&dtext->boxcolor_string);
340 340
     av_freep(&dtext->positions);
341
+    av_freep(&dtext->shadowcolor_string);
341 342
     av_tree_enumerate(dtext->glyphs, NULL, NULL, glyph_enu_free);
342 343
     av_tree_destroy(dtext->glyphs);
343 344
     dtext->glyphs = 0;
... ...
@@ -373,6 +388,11 @@ static int config_input(AVFilterLink *inlink)
373 373
         dtext->fontcolor[1] = RGB_TO_U_CCIR(rgba[0], rgba[1], rgba[2], 0);
374 374
         dtext->fontcolor[2] = RGB_TO_V_CCIR(rgba[0], rgba[1], rgba[2], 0);
375 375
         dtext->fontcolor[3] = rgba[3];
376
+        rgba = dtext->shadowcolor_rgba;
377
+        dtext->shadowcolor[0] = RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]);
378
+        dtext->shadowcolor[1] = RGB_TO_U_CCIR(rgba[0], rgba[1], rgba[2], 0);
379
+        dtext->shadowcolor[2] = RGB_TO_V_CCIR(rgba[0], rgba[1], rgba[2], 0);
380
+        dtext->shadowcolor[3] = rgba[3];
376 381
     }
377 382
 
378 383
     return 0;
... ...
@@ -495,7 +515,7 @@ static inline int is_newline(uint32_t c)
495 495
 }
496 496
 
497 497
 static int draw_glyphs(DrawTextContext *dtext, AVFilterBufferRef *picref,
498
-                        int width, int height)
498
+                       int width, int height, const uint8_t rgbcolor[4], const uint8_t yuvcolor[4], int x, int y)
499 499
 {
500 500
     char *text = dtext->text;
501 501
     uint32_t code = 0;
... ...
@@ -520,12 +540,12 @@ static int draw_glyphs(DrawTextContext *dtext, AVFilterBufferRef *picref,
520 520
 
521 521
         if (dtext->is_packed_rgb) {
522 522
             draw_glyph_rgb(picref, &glyph->bitmap,
523
-                           dtext->positions[i].x, dtext->positions[i].y, width, height,
524
-                           dtext->pixel_step[0], dtext->fontcolor_rgba, dtext->rgba_map);
523
+                           dtext->positions[i].x+x, dtext->positions[i].y+y, width, height,
524
+                           dtext->pixel_step[0], rgbcolor, dtext->rgba_map);
525 525
         } else {
526 526
             draw_glyph_yuv(picref, &glyph->bitmap,
527
-                           dtext->positions[i].x, dtext->positions[i].y, width, height,
528
-                           dtext->fontcolor, dtext->hsub, dtext->vsub);
527
+                           dtext->positions[i].x+x, dtext->positions[i].y+y, width, height,
528
+                           yuvcolor, dtext->hsub, dtext->vsub);
529 529
         }
530 530
     }
531 531
 
... ...
@@ -643,7 +663,14 @@ static int draw_text(AVFilterContext *ctx, AVFilterBufferRef *picref,
643 643
                 dtext->box_line, dtext->pixel_step, dtext->boxcolor,
644 644
                 dtext->hsub, dtext->vsub, dtext->is_packed_rgb, dtext->rgba_map);
645 645
 
646
-    if ((ret = draw_glyphs(dtext, picref, width, height)) < 0)
646
+    if (dtext->shadowx || dtext->shadowy) {
647
+        if ((ret = draw_glyphs(dtext, picref, width, height, dtext->shadowcolor_rgba,
648
+                               dtext->shadowcolor, dtext->shadowx, dtext->shadowy)) < 0)
649
+            return ret;
650
+    }
651
+
652
+    if ((ret = draw_glyphs(dtext, picref, width, height, dtext->fontcolor_rgba,
653
+                           dtext->fontcolor, 0, 0)) < 0)
647 654
         return ret;
648 655
 
649 656
     return 0;