]> git.sesse.net Git - ffmpeg/blobdiff - libavfilter/vf_curves.c
vf_curves: add option to set all curves at once
[ffmpeg] / libavfilter / vf_curves.c
index 48db0f396f82b473f1759b06b37a8082827c0342..1f4e733c3d05cacf38e35c3b1d74df9f7b5b9d6a 100644 (file)
@@ -33,10 +33,26 @@ struct keypoint {
 
 #define NB_COMP 3
 
+enum preset {
+    PRESET_NONE,
+    PRESET_COLOR_NEGATIVE,
+    PRESET_CROSS_PROCESS,
+    PRESET_DARKER,
+    PRESET_INCREASE_CONTRAST,
+    PRESET_LIGHTER,
+    PRESET_LINEAR_CONTRAST,
+    PRESET_MEDIUM_CONTRAST,
+    PRESET_NEGATIVE,
+    PRESET_STRONG_CONTRAST,
+    PRESET_VINTAGE,
+    NB_PRESETS,
+};
+
 typedef struct {
     const AVClass *class;
-    char *preset;
+    enum preset preset;
     char *comp_points_str[NB_COMP];
+    char *comp_points_str_all;
     uint8_t graph[NB_COMP][256];
 } CurvesContext;
 
@@ -49,55 +65,68 @@ static const AVOption curves_options[] = {
     { "g",     "set green points coordinates", OFFSET(comp_points_str[1]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
     { "blue",  "set blue points coordinates",  OFFSET(comp_points_str[2]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
     { "b",     "set blue points coordinates",  OFFSET(comp_points_str[2]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
-    { "preset", "select a color curves preset", OFFSET(preset), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
+    { "all",   "set points coordinates for all components",   OFFSET(comp_points_str_all),AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
+    { "preset", "select a color curves preset", OFFSET(preset), AV_OPT_TYPE_INT, {.i64=PRESET_NONE}, PRESET_NONE, NB_PRESETS-1, FLAGS, "preset_name" },
+        { "color_negative",     NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_COLOR_NEGATIVE},       INT_MIN, INT_MAX, FLAGS, "preset_name" },
+        { "cross_process",      NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_CROSS_PROCESS},        INT_MIN, INT_MAX, FLAGS, "preset_name" },
+        { "darker",             NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_DARKER},               INT_MIN, INT_MAX, FLAGS, "preset_name" },
+        { "increase_contrast",  NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_INCREASE_CONTRAST},    INT_MIN, INT_MAX, FLAGS, "preset_name" },
+        { "lighter",            NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_LIGHTER},              INT_MIN, INT_MAX, FLAGS, "preset_name" },
+        { "linear_contrast",    NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_LINEAR_CONTRAST},      INT_MIN, INT_MAX, FLAGS, "preset_name" },
+        { "medium_contrast",    NULL, 0, AV_OPT_TYPE_CONST, {.i64=PRESET_MEDIUM_CONTRAST},      INT_MIN, INT_MAX, FLAGS, "preset_name" },
+        { "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" },
     { NULL }
 };
 
 AVFILTER_DEFINE_CLASS(curves);
 
 static const struct {
-    const char *name;
     const char *r;
     const char *g;
     const char *b;
-} curves_presets[] = { {
-        "color_negative",
+} curves_presets[] = {
+    [PRESET_COLOR_NEGATIVE] = {
         "0/1 0.129/1 0.466/0.498 0.725/0 1/0",
         "0/1 0.109/1 0.301/0.498 0.517/0 1/0",
         "0/1 0.098/1 0.235/0.498 0.423/0 1/0",
-    },{
-        "cross_process",
+    },
+    [PRESET_CROSS_PROCESS] = {
         "0.25/0.156 0.501/0.501 0.686/0.745",
         "0.25/0.188 0.38/0.501 0.745/0.815 1/0.815",
         "0.231/0.094 0.709/0.874",
-    },{
-        "darker", "0.5/0.4", "0.5/0.4", "0.5/0.4",
-    },{
-        "increase_contrast",
+    },
+    [PRESET_DARKER] = {
+        "0.5/0.4", "0.5/0.4", "0.5/0.4",
+    },
+    [PRESET_INCREASE_CONTRAST] = {
         "0.149/0.066 0.831/0.905 0.905/0.98",
         "0.149/0.066 0.831/0.905 0.905/0.98",
         "0.149/0.066 0.831/0.905 0.905/0.98",
-    },{
-        "lighter", "0.4/0.5", "0.4/0.5", "0.4/0.5",
-    },{
-        "linear_contrast",
+    },
+    [PRESET_LIGHTER] = {
+        "0.4/0.5", "0.4/0.5", "0.4/0.5",
+    },
+    [PRESET_LINEAR_CONTRAST] = {
         "0.305/0.286 0.694/0.713",
         "0.305/0.286 0.694/0.713",
         "0.305/0.286 0.694/0.713",
-    },{
-        "medium_contrast",
+    },
+    [PRESET_MEDIUM_CONTRAST] = {
         "0.286/0.219 0.639/0.643",
         "0.286/0.219 0.639/0.643",
         "0.286/0.219 0.639/0.643",
-    },{
-        "negative", "0/1 1/0", "0/1 1/0", "0/1 1/0",
-    },{
-        "strong_contrast",
+    },
+    [PRESET_NEGATIVE] = {
+        "0/1 1/0", "0/1 1/0", "0/1 1/0",
+    },
+    [PRESET_STRONG_CONTRAST] = {
         "0.301/0.196 0.592/0.6 0.686/0.737",
         "0.301/0.196 0.592/0.6 0.686/0.737",
         "0.301/0.196 0.592/0.6 0.686/0.737",
-    },{
-        "vintage",
+    },
+    [PRESET_VINTAGE] = {
         "0/0.11 0.42/0.51 1/0.95",
         "0.50/0.48",
         "0/0.22 0.49/0.44 1/0.8",
@@ -291,32 +320,28 @@ static av_cold int init(AVFilterContext *ctx, const char *args)
     int i, j, ret;
     CurvesContext *curves = ctx->priv;
     struct keypoint *comp_points[NB_COMP] = {0};
+    char **pts = curves->comp_points_str;
+
+    if (curves->comp_points_str_all) {
+        for (i = 0; i < NB_COMP; i++) {
+            if (!pts[i])
+                pts[i] = av_strdup(curves->comp_points_str_all);
+            if (!pts[i])
+                return AVERROR(ENOMEM);
+        }
+    }
 
-    if (curves->preset) {
-        char **pts = curves->comp_points_str;
+    if (curves->preset != PRESET_NONE) {
         if (pts[0] || pts[1] || pts[2]) {
             av_log(ctx, AV_LOG_ERROR, "It is not possible to mix a preset "
                    "with explicit points placements\n");
             return AVERROR(EINVAL);
         }
-        for (i = 0; i < FF_ARRAY_ELEMS(curves_presets); i++) {
-            if (!strcmp(curves->preset, curves_presets[i].name)) {
-                pts[0] = av_strdup(curves_presets[i].r);
-                pts[1] = av_strdup(curves_presets[i].g);
-                pts[2] = av_strdup(curves_presets[i].b);
-                if (!pts[0] || !pts[1] || !pts[2])
-                    return AVERROR(ENOMEM);
-                break;
-            }
-        }
-        if (i == FF_ARRAY_ELEMS(curves_presets)) {
-            av_log(ctx, AV_LOG_ERROR, "Preset '%s' not found. Available presets:",
-                   curves->preset);
-            for (i = 0; i < FF_ARRAY_ELEMS(curves_presets); i++)
-                av_log(ctx, AV_LOG_ERROR, " %s", curves_presets[i].name);
-            av_log(ctx, AV_LOG_ERROR, ".\n");
-            return AVERROR(EINVAL);
-        }
+        pts[0] = av_strdup(curves_presets[curves->preset].r);
+        pts[1] = av_strdup(curves_presets[curves->preset].g);
+        pts[2] = av_strdup(curves_presets[curves->preset].b);
+        if (!pts[0] || !pts[1] || !pts[2])
+            return AVERROR(ENOMEM);
     }
 
     for (i = 0; i < NB_COMP; i++) {