Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Signed-off-by: Anton Khirnov <anton@khirnov.net>
... | ... |
@@ -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; |