Statistics
| Branch: | Revision:

ffmpeg / libavfilter / parseutils.c @ 2722dd6e

History | View | Annotate | Download (12.5 KB)

1
/*
2
 * copyright (c) 2009 Stefano Sabatini
3
 * This file is part of FFmpeg.
4
 *
5
 * FFmpeg is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
7
 * License as published by the Free Software Foundation; either
8
 * version 2.1 of the License, or (at your option) any later version.
9
 *
10
 * FFmpeg is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Lesser General Public
16
 * License along with FFmpeg; if not, write to the Free Software
17
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
 */
19

    
20
/**
21
 * @file
22
 * parsing utils
23
 */
24

    
25
#include <strings.h>
26
#include "libavutil/avutil.h"
27
#include "libavutil/avstring.h"
28
#include "libavutil/random_seed.h"
29
#include "parseutils.h"
30

    
31
typedef struct {
32
    const char *name;            ///< a string representing the name of the color
33
    uint8_t     rgb_color[3];    ///< RGB values for the color
34
} ColorEntry;
35

    
36
static ColorEntry color_table[] = {
37
    { "AliceBlue",            { 0xF0, 0xF8, 0xFF } },
38
    { "AntiqueWhite",         { 0xFA, 0xEB, 0xD7 } },
39
    { "Aqua",                 { 0x00, 0xFF, 0xFF } },
40
    { "Aquamarine",           { 0x7F, 0xFF, 0xD4 } },
41
    { "Azure",                { 0xF0, 0xFF, 0xFF } },
42
    { "Beige",                { 0xF5, 0xF5, 0xDC } },
43
    { "Bisque",               { 0xFF, 0xE4, 0xC4 } },
44
    { "Black",                { 0x00, 0x00, 0x00 } },
45
    { "BlanchedAlmond",       { 0xFF, 0xEB, 0xCD } },
46
    { "Blue",                 { 0x00, 0x00, 0xFF } },
47
    { "BlueViolet",           { 0x8A, 0x2B, 0xE2 } },
48
    { "Brown",                { 0xA5, 0x2A, 0x2A } },
49
    { "BurlyWood",            { 0xDE, 0xB8, 0x87 } },
50
    { "CadetBlue",            { 0x5F, 0x9E, 0xA0 } },
51
    { "Chartreuse",           { 0x7F, 0xFF, 0x00 } },
52
    { "Chocolate",            { 0xD2, 0x69, 0x1E } },
53
    { "Coral",                { 0xFF, 0x7F, 0x50 } },
54
    { "CornflowerBlue",       { 0x64, 0x95, 0xED } },
55
    { "Cornsilk",             { 0xFF, 0xF8, 0xDC } },
56
    { "Crimson",              { 0xDC, 0x14, 0x3C } },
57
    { "Cyan",                 { 0x00, 0xFF, 0xFF } },
58
    { "DarkBlue",             { 0x00, 0x00, 0x8B } },
59
    { "DarkCyan",             { 0x00, 0x8B, 0x8B } },
60
    { "DarkGoldenRod",        { 0xB8, 0x86, 0x0B } },
61
    { "DarkGray",             { 0xA9, 0xA9, 0xA9 } },
62
    { "DarkGreen",            { 0x00, 0x64, 0x00 } },
63
    { "DarkKhaki",            { 0xBD, 0xB7, 0x6B } },
64
    { "DarkMagenta",          { 0x8B, 0x00, 0x8B } },
65
    { "DarkOliveGreen",       { 0x55, 0x6B, 0x2F } },
66
    { "Darkorange",           { 0xFF, 0x8C, 0x00 } },
67
    { "DarkOrchid",           { 0x99, 0x32, 0xCC } },
68
    { "DarkRed",              { 0x8B, 0x00, 0x00 } },
69
    { "DarkSalmon",           { 0xE9, 0x96, 0x7A } },
70
    { "DarkSeaGreen",         { 0x8F, 0xBC, 0x8F } },
71
    { "DarkSlateBlue",        { 0x48, 0x3D, 0x8B } },
72
    { "DarkSlateGray",        { 0x2F, 0x4F, 0x4F } },
73
    { "DarkTurquoise",        { 0x00, 0xCE, 0xD1 } },
74
    { "DarkViolet",           { 0x94, 0x00, 0xD3 } },
75
    { "DeepPink",             { 0xFF, 0x14, 0x93 } },
76
    { "DeepSkyBlue",          { 0x00, 0xBF, 0xFF } },
77
    { "DimGray",              { 0x69, 0x69, 0x69 } },
78
    { "DodgerBlue",           { 0x1E, 0x90, 0xFF } },
79
    { "FireBrick",            { 0xB2, 0x22, 0x22 } },
80
    { "FloralWhite",          { 0xFF, 0xFA, 0xF0 } },
81
    { "ForestGreen",          { 0x22, 0x8B, 0x22 } },
82
    { "Fuchsia",              { 0xFF, 0x00, 0xFF } },
83
    { "Gainsboro",            { 0xDC, 0xDC, 0xDC } },
84
    { "GhostWhite",           { 0xF8, 0xF8, 0xFF } },
85
    { "Gold",                 { 0xFF, 0xD7, 0x00 } },
86
    { "GoldenRod",            { 0xDA, 0xA5, 0x20 } },
87
    { "Gray",                 { 0x80, 0x80, 0x80 } },
88
    { "Green",                { 0x00, 0x80, 0x00 } },
89
    { "GreenYellow",          { 0xAD, 0xFF, 0x2F } },
90
    { "HoneyDew",             { 0xF0, 0xFF, 0xF0 } },
91
    { "HotPink",              { 0xFF, 0x69, 0xB4 } },
92
    { "IndianRed",            { 0xCD, 0x5C, 0x5C } },
93
    { "Indigo",               { 0x4B, 0x00, 0x82 } },
94
    { "Ivory",                { 0xFF, 0xFF, 0xF0 } },
95
    { "Khaki",                { 0xF0, 0xE6, 0x8C } },
96
    { "Lavender",             { 0xE6, 0xE6, 0xFA } },
97
    { "LavenderBlush",        { 0xFF, 0xF0, 0xF5 } },
98
    { "LawnGreen",            { 0x7C, 0xFC, 0x00 } },
99
    { "LemonChiffon",         { 0xFF, 0xFA, 0xCD } },
100
    { "LightBlue",            { 0xAD, 0xD8, 0xE6 } },
101
    { "LightCoral",           { 0xF0, 0x80, 0x80 } },
102
    { "LightCyan",            { 0xE0, 0xFF, 0xFF } },
103
    { "LightGoldenRodYellow", { 0xFA, 0xFA, 0xD2 } },
104
    { "LightGrey",            { 0xD3, 0xD3, 0xD3 } },
105
    { "LightGreen",           { 0x90, 0xEE, 0x90 } },
106
    { "LightPink",            { 0xFF, 0xB6, 0xC1 } },
107
    { "LightSalmon",          { 0xFF, 0xA0, 0x7A } },
108
    { "LightSeaGreen",        { 0x20, 0xB2, 0xAA } },
109
    { "LightSkyBlue",         { 0x87, 0xCE, 0xFA } },
110
    { "LightSlateGray",       { 0x77, 0x88, 0x99 } },
111
    { "LightSteelBlue",       { 0xB0, 0xC4, 0xDE } },
112
    { "LightYellow",          { 0xFF, 0xFF, 0xE0 } },
113
    { "Lime",                 { 0x00, 0xFF, 0x00 } },
114
    { "LimeGreen",            { 0x32, 0xCD, 0x32 } },
115
    { "Linen",                { 0xFA, 0xF0, 0xE6 } },
116
    { "Magenta",              { 0xFF, 0x00, 0xFF } },
117
    { "Maroon",               { 0x80, 0x00, 0x00 } },
118
    { "MediumAquaMarine",     { 0x66, 0xCD, 0xAA } },
119
    { "MediumBlue",           { 0x00, 0x00, 0xCD } },
120
    { "MediumOrchid",         { 0xBA, 0x55, 0xD3 } },
121
    { "MediumPurple",         { 0x93, 0x70, 0xD8 } },
122
    { "MediumSeaGreen",       { 0x3C, 0xB3, 0x71 } },
123
    { "MediumSlateBlue",      { 0x7B, 0x68, 0xEE } },
124
    { "MediumSpringGreen",    { 0x00, 0xFA, 0x9A } },
125
    { "MediumTurquoise",      { 0x48, 0xD1, 0xCC } },
126
    { "MediumVioletRed",      { 0xC7, 0x15, 0x85 } },
127
    { "MidnightBlue",         { 0x19, 0x19, 0x70 } },
128
    { "MintCream",            { 0xF5, 0xFF, 0xFA } },
129
    { "MistyRose",            { 0xFF, 0xE4, 0xE1 } },
130
    { "Moccasin",             { 0xFF, 0xE4, 0xB5 } },
131
    { "NavajoWhite",          { 0xFF, 0xDE, 0xAD } },
132
    { "Navy",                 { 0x00, 0x00, 0x80 } },
133
    { "OldLace",              { 0xFD, 0xF5, 0xE6 } },
134
    { "Olive",                { 0x80, 0x80, 0x00 } },
135
    { "OliveDrab",            { 0x6B, 0x8E, 0x23 } },
136
    { "Orange",               { 0xFF, 0xA5, 0x00 } },
137
    { "OrangeRed",            { 0xFF, 0x45, 0x00 } },
138
    { "Orchid",               { 0xDA, 0x70, 0xD6 } },
139
    { "PaleGoldenRod",        { 0xEE, 0xE8, 0xAA } },
140
    { "PaleGreen",            { 0x98, 0xFB, 0x98 } },
141
    { "PaleTurquoise",        { 0xAF, 0xEE, 0xEE } },
142
    { "PaleVioletRed",        { 0xD8, 0x70, 0x93 } },
143
    { "PapayaWhip",           { 0xFF, 0xEF, 0xD5 } },
144
    { "PeachPuff",            { 0xFF, 0xDA, 0xB9 } },
145
    { "Peru",                 { 0xCD, 0x85, 0x3F } },
146
    { "Pink",                 { 0xFF, 0xC0, 0xCB } },
147
    { "Plum",                 { 0xDD, 0xA0, 0xDD } },
148
    { "PowderBlue",           { 0xB0, 0xE0, 0xE6 } },
149
    { "Purple",               { 0x80, 0x00, 0x80 } },
150
    { "Red",                  { 0xFF, 0x00, 0x00 } },
151
    { "RosyBrown",            { 0xBC, 0x8F, 0x8F } },
152
    { "RoyalBlue",            { 0x41, 0x69, 0xE1 } },
153
    { "SaddleBrown",          { 0x8B, 0x45, 0x13 } },
154
    { "Salmon",               { 0xFA, 0x80, 0x72 } },
155
    { "SandyBrown",           { 0xF4, 0xA4, 0x60 } },
156
    { "SeaGreen",             { 0x2E, 0x8B, 0x57 } },
157
    { "SeaShell",             { 0xFF, 0xF5, 0xEE } },
158
    { "Sienna",               { 0xA0, 0x52, 0x2D } },
159
    { "Silver",               { 0xC0, 0xC0, 0xC0 } },
160
    { "SkyBlue",              { 0x87, 0xCE, 0xEB } },
161
    { "SlateBlue",            { 0x6A, 0x5A, 0xCD } },
162
    { "SlateGray",            { 0x70, 0x80, 0x90 } },
163
    { "Snow",                 { 0xFF, 0xFA, 0xFA } },
164
    { "SpringGreen",          { 0x00, 0xFF, 0x7F } },
165
    { "SteelBlue",            { 0x46, 0x82, 0xB4 } },
166
    { "Tan",                  { 0xD2, 0xB4, 0x8C } },
167
    { "Teal",                 { 0x00, 0x80, 0x80 } },
168
    { "Thistle",              { 0xD8, 0xBF, 0xD8 } },
169
    { "Tomato",               { 0xFF, 0x63, 0x47 } },
170
    { "Turquoise",            { 0x40, 0xE0, 0xD0 } },
171
    { "Violet",               { 0xEE, 0x82, 0xEE } },
172
    { "Wheat",                { 0xF5, 0xDE, 0xB3 } },
173
    { "White",                { 0xFF, 0xFF, 0xFF } },
174
    { "WhiteSmoke",           { 0xF5, 0xF5, 0xF5 } },
175
    { "Yellow",               { 0xFF, 0xFF, 0x00 } },
176
    { "YellowGreen",          { 0x9A, 0xCD, 0x32 } },
177
};
178

    
179
static int color_table_compare(const void *lhs, const void *rhs)
180
{
181
    return strcasecmp(lhs, ((const ColorEntry *)rhs)->name);
182
}
183

    
184
#define ALPHA_SEP '@'
185

    
186
int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen,
187
                   void *log_ctx)
188
{
189
    char *tail, color_string2[128];
190
    const ColorEntry *entry;
191
    int len, hex_offset = 0;
192

    
193
    if (color_string[0] == '#') {
194
        hex_offset = 1;
195
    } else if (!strncmp(color_string, "0x", 2))
196
        hex_offset = 2;
197

    
198
    if (slen < 0)
199
        slen = strlen(color_string);
200
    av_strlcpy(color_string2, color_string + hex_offset,
201
               FFMIN(slen-hex_offset+1, sizeof(color_string2)));
202
    if ((tail = strchr(color_string2, ALPHA_SEP)))
203
        *tail++ = 0;
204
    len = strlen(color_string2);
205
    rgba_color[3] = 255;
206

    
207
    if (!strcasecmp(color_string2, "random") || !strcasecmp(color_string2, "bikeshed")) {
208
        int rgba = av_get_random_seed();
209
        rgba_color[0] = rgba >> 24;
210
        rgba_color[1] = rgba >> 16;
211
        rgba_color[2] = rgba >> 8;
212
        rgba_color[3] = rgba;
213
    } else if (hex_offset ||
214
               strspn(color_string2, "0123456789ABCDEFabcdef") == len) {
215
        char *tail;
216
        unsigned int rgba = strtoul(color_string2, &tail, 16);
217

    
218
        if (*tail || (len != 6 && len != 8)) {
219
            av_log(log_ctx, AV_LOG_ERROR, "Invalid 0xRRGGBB[AA] color string: '%s'\n", color_string2);
220
            return AVERROR(EINVAL);
221
        }
222
        if (len == 8) {
223
            rgba_color[3] = rgba;
224
            rgba >>= 8;
225
        }
226
        rgba_color[0] = rgba >> 16;
227
        rgba_color[1] = rgba >> 8;
228
        rgba_color[2] = rgba;
229
    } else {
230
        entry = bsearch(color_string2,
231
                        color_table,
232
                        FF_ARRAY_ELEMS(color_table),
233
                        sizeof(ColorEntry),
234
                        color_table_compare);
235
        if (!entry) {
236
            av_log(log_ctx, AV_LOG_ERROR, "Cannot find color '%s'\n", color_string2);
237
            return AVERROR(EINVAL);
238
        }
239
        memcpy(rgba_color, entry->rgb_color, 3);
240
    }
241

    
242
    if (tail) {
243
        unsigned long int alpha;
244
        const char *alpha_string = tail;
245
        if (!strncmp(alpha_string, "0x", 2)) {
246
            alpha = strtoul(alpha_string, &tail, 16);
247
        } else {
248
            alpha = 255 * strtod(alpha_string, &tail);
249
        }
250

    
251
        if (tail == alpha_string || *tail || alpha > 255) {
252
            av_log(log_ctx, AV_LOG_ERROR, "Invalid alpha value specifier '%s' in '%s'\n",
253
                   alpha_string, color_string);
254
            return AVERROR(EINVAL);
255
        }
256
        rgba_color[3] = alpha;
257
    }
258

    
259
    return 0;
260
}
261

    
262
#ifdef TEST
263

    
264
#undef printf
265

    
266
int main(void)
267
{
268
    int i;
269

    
270
    printf("\nTesting av_parse_color()\n");
271
    {
272
        uint8_t rgba[4];
273
        const char *color_names[] = {
274
            "bikeshed",
275
            "RaNdOm",
276
            "foo",
277
            "red",
278
            "Red ",
279
            "RED",
280
            "Violet",
281
            "Yellow",
282
            "Red",
283
            "0x000000",
284
            "0x0000000",
285
            "0xff000000",
286
            "0x3e34ff",
287
            "0x3e34ffaa",
288
            "0xffXXee",
289
            "0xfoobar",
290
            "0xffffeeeeeeee",
291
            "#ff0000",
292
            "#ffXX00",
293
            "ff0000",
294
            "ffXX00",
295
            "red@foo",
296
            "random@10",
297
            "0xff0000@1.0",
298
            "red@",
299
            "red@0xfff",
300
            "red@0xf",
301
            "red@2",
302
            "red@0.1",
303
            "red@-1",
304
            "red@0.5",
305
            "red@1.0",
306
            "red@256",
307
            "red@10foo",
308
            "red@-1.0",
309
            "red@-0.0",
310
        };
311

    
312
        av_log_set_level(AV_LOG_DEBUG);
313

    
314
        for (i = 0;  i < FF_ARRAY_ELEMS(color_names); i++) {
315
            if (av_parse_color(rgba, color_names[i], -1, NULL) >= 0)
316
                printf("%s -> R(%d) G(%d) B(%d) A(%d)\n", color_names[i], rgba[0], rgba[1], rgba[2], rgba[3]);
317
        }
318
    }
319

    
320
    return 0;
321
}
322

    
323
#endif