Browse code

lavfi/curves: add support for master component.

Clément Bœsch authored on 2013/04/15 17:53:54
Showing 2 changed files
... ...
@@ -2330,6 +2330,11 @@ Available presets are:
2330 2330
 @item vintage
2331 2331
 @end table
2332 2332
 Default is @code{none}.
2333
+@item master, m
2334
+Set the master key points. These points will define a second pass mapping. It
2335
+is sometimes called a "luminance" or "value" mapping. It can be used with
2336
+@option{r}, @option{g}, @option{b} or @option{all} since it acts like a
2337
+post-processing LUT.
2333 2338
 @item red, r
2334 2339
 Set the key points for the red component.
2335 2340
 @item green, g
... ...
@@ -2337,7 +2342,7 @@ Set the key points for the green component.
2337 2337
 @item blue, b
2338 2338
 Set the key points for the blue component.
2339 2339
 @item all
2340
-Set the key points for all components.
2340
+Set the key points for all components (not including master).
2341 2341
 Can be used in addition to the other key points component
2342 2342
 options. In this case, the unset component(s) will fallback on this
2343 2343
 @option{all} setting.
... ...
@@ -51,9 +51,9 @@ enum preset {
51 51
 typedef struct {
52 52
     const AVClass *class;
53 53
     enum preset preset;
54
-    char *comp_points_str[NB_COMP];
54
+    char *comp_points_str[NB_COMP + 1];
55 55
     char *comp_points_str_all;
56
-    uint8_t graph[NB_COMP][256];
56
+    uint8_t graph[NB_COMP + 1][256];
57 57
 } CurvesContext;
58 58
 
59 59
 #define OFFSET(x) offsetof(CurvesContext, x)
... ...
@@ -71,6 +71,8 @@ static const AVOption curves_options[] = {
71 71
         { "negative",           NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_NEGATIVE},             INT_MIN, INT_MAX, FLAGS, "preset_name" },
72 72
         { "strong_contrast",    NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_STRONG_CONTRAST},      INT_MIN, INT_MAX, FLAGS, "preset_name" },
73 73
         { "vintage",            NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_VINTAGE},              INT_MIN, INT_MAX, FLAGS, "preset_name" },
74
+    { "master","set master points coordinates",OFFSET(comp_points_str[NB_COMP]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
75
+    { "m",     "set master points coordinates",OFFSET(comp_points_str[NB_COMP]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
74 76
     { "red",   "set red points coordinates",   OFFSET(comp_points_str[0]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
75 77
     { "r",     "set red points coordinates",   OFFSET(comp_points_str[0]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
76 78
     { "green", "set green points coordinates", OFFSET(comp_points_str[1]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
... ...
@@ -87,7 +89,7 @@ static const struct {
87 87
     const char *r;
88 88
     const char *g;
89 89
     const char *b;
90
-    const char *all;
90
+    const char *master;
91 91
 } curves_presets[] = {
92 92
     [PRESET_COLOR_NEGATIVE] = {
93 93
         "0/1 0.129/1 0.466/0.498 0.725/0 1/0",
... ...
@@ -99,13 +101,13 @@ static const struct {
99 99
         "0.25/0.188 0.38/0.501 0.745/0.815 1/0.815",
100 100
         "0.231/0.094 0.709/0.874",
101 101
     },
102
-    [PRESET_DARKER]             = { .all = "0.5/0.4" },
103
-    [PRESET_INCREASE_CONTRAST]  = { .all = "0.149/0.066 0.831/0.905 0.905/0.98" },
104
-    [PRESET_LIGHTER]            = { .all = "0.4/0.5" },
105
-    [PRESET_LINEAR_CONTRAST]    = { .all = "0.305/0.286 0.694/0.713" },
106
-    [PRESET_MEDIUM_CONTRAST]    = { .all = "0.286/0.219 0.639/0.643" },
107
-    [PRESET_NEGATIVE]           = { .all = "0/1 1/0" },
108
-    [PRESET_STRONG_CONTRAST]    = { .all = "0.301/0.196 0.592/0.6 0.686/0.737" },
102
+    [PRESET_DARKER]             = { .master = "0.5/0.4" },
103
+    [PRESET_INCREASE_CONTRAST]  = { .master = "0.149/0.066 0.831/0.905 0.905/0.98" },
104
+    [PRESET_LIGHTER]            = { .master = "0.4/0.5" },
105
+    [PRESET_LINEAR_CONTRAST]    = { .master = "0.305/0.286 0.694/0.713" },
106
+    [PRESET_MEDIUM_CONTRAST]    = { .master = "0.286/0.219 0.639/0.643" },
107
+    [PRESET_NEGATIVE]           = { .master = "0/1 1/0" },
108
+    [PRESET_STRONG_CONTRAST]    = { .master = "0.301/0.196 0.592/0.6 0.686/0.737" },
109 109
     [PRESET_VINTAGE] = {
110 110
         "0/0.11 0.42/0.51 1/0.95",
111 111
         "0.50/0.48",
... ...
@@ -299,12 +301,12 @@ static av_cold int init(AVFilterContext *ctx)
299 299
 {
300 300
     int i, j, ret;
301 301
     CurvesContext *curves = ctx->priv;
302
-    struct keypoint *comp_points[NB_COMP] = {0};
302
+    struct keypoint *comp_points[NB_COMP + 1] = {0};
303 303
     char **pts = curves->comp_points_str;
304 304
     const char *allp = curves->comp_points_str_all;
305 305
 
306
-    if (!allp && curves->preset != PRESET_NONE && curves_presets[curves->preset].all)
307
-        allp = curves_presets[curves->preset].all;
306
+    //if (!allp && curves->preset != PRESET_NONE && curves_presets[curves->preset].all)
307
+    //    allp = curves_presets[curves->preset].all;
308 308
 
309 309
     if (allp) {
310 310
         for (i = 0; i < NB_COMP; i++) {
... ...
@@ -316,14 +318,20 @@ static av_cold int init(AVFilterContext *ctx)
316 316
     }
317 317
 
318 318
     if (curves->preset != PRESET_NONE) {
319
-        if (!pts[0]) pts[0] = av_strdup(curves_presets[curves->preset].r);
320
-        if (!pts[1]) pts[1] = av_strdup(curves_presets[curves->preset].g);
321
-        if (!pts[2]) pts[2] = av_strdup(curves_presets[curves->preset].b);
322
-        if (!pts[0] || !pts[1] || !pts[2])
323
-            return AVERROR(ENOMEM);
319
+#define SET_COMP_IF_NOT_SET(n, name) do {                           \
320
+    if (!pts[n] && curves_presets[curves->preset].name) {           \
321
+        pts[n] = av_strdup(curves_presets[curves->preset].name);    \
322
+        if (!pts[n])                                                \
323
+            return AVERROR(ENOMEM);                                 \
324
+    }                                                               \
325
+} while (0)
326
+        SET_COMP_IF_NOT_SET(0, r);
327
+        SET_COMP_IF_NOT_SET(1, g);
328
+        SET_COMP_IF_NOT_SET(2, b);
329
+        SET_COMP_IF_NOT_SET(3, master);
324 330
     }
325 331
 
326
-    for (i = 0; i < NB_COMP; i++) {
332
+    for (i = 0; i < NB_COMP + 1; i++) {
327 333
         ret = parse_points_str(ctx, comp_points + i, curves->comp_points_str[i]);
328 334
         if (ret < 0)
329 335
             return ret;
... ...
@@ -332,6 +340,12 @@ static av_cold int init(AVFilterContext *ctx)
332 332
             return ret;
333 333
     }
334 334
 
335
+    if (pts[NB_COMP]) {
336
+        for (i = 0; i < NB_COMP; i++)
337
+            for (j = 0; j < 256; j++)
338
+                curves->graph[i][j] = curves->graph[NB_COMP][curves->graph[i][j]];
339
+    }
340
+
335 341
     if (av_log_get_level() >= AV_LOG_VERBOSE) {
336 342
         for (i = 0; i < NB_COMP; i++) {
337 343
             struct keypoint *point = comp_points[i];