lavfi/curves: add support for master component.
authorClément Bœsch <ubitux@gmail.com>
Mon, 15 Apr 2013 08:53:54 +0000 (10:53 +0200)
committerClément Bœsch <ubitux@gmail.com>
Mon, 15 Apr 2013 09:35:06 +0000 (11:35 +0200)
doc/filters.texi
libavfilter/vf_curves.c

index b766985..8df1a88 100644 (file)
@@ -2330,6 +2330,11 @@ Available presets are:
 @item vintage
 @end table
 Default is @code{none}.
+@item master, m
+Set the master key points. These points will define a second pass mapping. It
+is sometimes called a "luminance" or "value" mapping. It can be used with
+@option{r}, @option{g}, @option{b} or @option{all} since it acts like a
+post-processing LUT.
 @item red, r
 Set the key points for the red component.
 @item green, g
@@ -2337,7 +2342,7 @@ Set the key points for the green component.
 @item blue, b
 Set the key points for the blue component.
 @item all
-Set the key points for all components.
+Set the key points for all components (not including master).
 Can be used in addition to the other key points component
 options. In this case, the unset component(s) will fallback on this
 @option{all} setting.
index 2bb1c5e..35a5af3 100644 (file)
@@ -51,9 +51,9 @@ enum preset {
 typedef struct {
     const AVClass *class;
     enum preset preset;
-    char *comp_points_str[NB_COMP];
+    char *comp_points_str[NB_COMP + 1];
     char *comp_points_str_all;
-    uint8_t graph[NB_COMP][256];
+    uint8_t graph[NB_COMP + 1][256];
 } CurvesContext;
 
 #define OFFSET(x) offsetof(CurvesContext, x)
@@ -71,6 +71,8 @@ static const AVOption curves_options[] = {
         { "negative",           NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_NEGATIVE},             INT_MIN, INT_MAX, FLAGS, "preset_name" },
         { "strong_contrast",    NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_STRONG_CONTRAST},      INT_MIN, INT_MAX, FLAGS, "preset_name" },
         { "vintage",            NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_VINTAGE},              INT_MIN, INT_MAX, FLAGS, "preset_name" },
+    { "master","set master points coordinates",OFFSET(comp_points_str[NB_COMP]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
+    { "m",     "set master points coordinates",OFFSET(comp_points_str[NB_COMP]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
     { "red",   "set red points coordinates",   OFFSET(comp_points_str[0]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
     { "r",     "set red points coordinates",   OFFSET(comp_points_str[0]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
     { "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 {
     const char *r;
     const char *g;
     const char *b;
-    const char *all;
+    const char *master;
 } curves_presets[] = {
     [PRESET_COLOR_NEGATIVE] = {
         "0/1 0.129/1 0.466/0.498 0.725/0 1/0",
@@ -99,13 +101,13 @@ static const struct {
         "0.25/0.188 0.38/0.501 0.745/0.815 1/0.815",
         "0.231/0.094 0.709/0.874",
     },
-    [PRESET_DARKER]             = { .all = "0.5/0.4" },
-    [PRESET_INCREASE_CONTRAST]  = { .all = "0.149/0.066 0.831/0.905 0.905/0.98" },
-    [PRESET_LIGHTER]            = { .all = "0.4/0.5" },
-    [PRESET_LINEAR_CONTRAST]    = { .all = "0.305/0.286 0.694/0.713" },
-    [PRESET_MEDIUM_CONTRAST]    = { .all = "0.286/0.219 0.639/0.643" },
-    [PRESET_NEGATIVE]           = { .all = "0/1 1/0" },
-    [PRESET_STRONG_CONTRAST]    = { .all = "0.301/0.196 0.592/0.6 0.686/0.737" },
+    [PRESET_DARKER]             = { .master = "0.5/0.4" },
+    [PRESET_INCREASE_CONTRAST]  = { .master = "0.149/0.066 0.831/0.905 0.905/0.98" },
+    [PRESET_LIGHTER]            = { .master = "0.4/0.5" },
+    [PRESET_LINEAR_CONTRAST]    = { .master = "0.305/0.286 0.694/0.713" },
+    [PRESET_MEDIUM_CONTRAST]    = { .master = "0.286/0.219 0.639/0.643" },
+    [PRESET_NEGATIVE]           = { .master = "0/1 1/0" },
+    [PRESET_STRONG_CONTRAST]    = { .master = "0.301/0.196 0.592/0.6 0.686/0.737" },
     [PRESET_VINTAGE] = {
         "0/0.11 0.42/0.51 1/0.95",
         "0.50/0.48",
@@ -299,12 +301,12 @@ static av_cold int init(AVFilterContext *ctx)
 {
     int i, j, ret;
     CurvesContext *curves = ctx->priv;
-    struct keypoint *comp_points[NB_COMP] = {0};
+    struct keypoint *comp_points[NB_COMP + 1] = {0};
     char **pts = curves->comp_points_str;
     const char *allp = curves->comp_points_str_all;
 
-    if (!allp && curves->preset != PRESET_NONE && curves_presets[curves->preset].all)
-        allp = curves_presets[curves->preset].all;
+    //if (!allp && curves->preset != PRESET_NONE && curves_presets[curves->preset].all)
+    //    allp = curves_presets[curves->preset].all;
 
     if (allp) {
         for (i = 0; i < NB_COMP; i++) {
@@ -316,14 +318,20 @@ static av_cold int init(AVFilterContext *ctx)
     }
 
     if (curves->preset != PRESET_NONE) {
-        if (!pts[0]) pts[0] = av_strdup(curves_presets[curves->preset].r);
-        if (!pts[1]) pts[1] = av_strdup(curves_presets[curves->preset].g);
-        if (!pts[2]) pts[2] = av_strdup(curves_presets[curves->preset].b);
-        if (!pts[0] || !pts[1] || !pts[2])
-            return AVERROR(ENOMEM);
+#define SET_COMP_IF_NOT_SET(n, name) do {                           \
+    if (!pts[n] && curves_presets[curves->preset].name) {           \
+        pts[n] = av_strdup(curves_presets[curves->preset].name);    \
+        if (!pts[n])                                                \
+            return AVERROR(ENOMEM);                                 \
+    }                                                               \
+} while (0)
+        SET_COMP_IF_NOT_SET(0, r);
+        SET_COMP_IF_NOT_SET(1, g);
+        SET_COMP_IF_NOT_SET(2, b);
+        SET_COMP_IF_NOT_SET(3, master);
     }
 
-    for (i = 0; i < NB_COMP; i++) {
+    for (i = 0; i < NB_COMP + 1; i++) {
         ret = parse_points_str(ctx, comp_points + i, curves->comp_points_str[i]);
         if (ret < 0)
             return ret;
@@ -332,6 +340,12 @@ static av_cold int init(AVFilterContext *ctx)
             return ret;
     }
 
+    if (pts[NB_COMP]) {
+        for (i = 0; i < NB_COMP; i++)
+            for (j = 0; j < 256; j++)
+                curves->graph[i][j] = curves->graph[NB_COMP][curves->graph[i][j]];
+    }
+
     if (av_log_get_level() >= AV_LOG_VERBOSE) {
         for (i = 0; i < NB_COMP; i++) {
             struct keypoint *point = comp_points[i];