lavfi/curves: add plot option
authorClément Bœsch <u@pkh.me>
Thu, 21 Jul 2016 23:17:44 +0000 (01:17 +0200)
committerClément Bœsch <u@pkh.me>
Sun, 24 Jul 2016 10:18:30 +0000 (12:18 +0200)
doc/filters.texi
libavfilter/vf_curves.c

index 03da9b0..5a64853 100644 (file)
@@ -5750,6 +5750,8 @@ options. In this case, the unset component(s) will fallback on this
 @option{all} setting.
 @item psfile
 Specify a Photoshop curves file (@code{.acv}) to import the settings from.
+@item plot
+Save Gnuplot script of the curves in specified file.
 @end table
 
 To avoid some filtergraph syntax conflicts, each key points list need to be
@@ -5796,6 +5798,14 @@ Use a Photoshop preset and redefine the points of the green component:
 @example
 curves=psfile='MyCurvesPresets/purple.acv':green='0/0 0.45/0.53 1/1'
 @end example
+
+@item
+Check out the curves of the @code{cross_process} profile using @command{ffmpeg}
+and @command{gnuplot}:
+@example
+ffmpeg -f lavfi -i color -vf curves=cross_process:plot=/tmp/curves.plt -frames:v 1 -f null -
+gnuplot -p /tmp/curves.plt
+@end example
 @end itemize
 
 @section datascope
index 7128fbe..84df448 100644 (file)
@@ -67,6 +67,7 @@ typedef struct {
     char *psfile;
     uint8_t rgba_map[4];
     int step;
+    char *plot_filename;
 } CurvesContext;
 
 typedef struct ThreadData {
@@ -98,6 +99,7 @@ static const AVOption curves_options[] = {
     { "b",     "set blue points coordinates",  OFFSET(comp_points_str[2]), 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 },
     { "psfile", "set Photoshop curves file name", OFFSET(psfile), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
+    { "plot", "save Gnuplot script of the curves in specified file", OFFSET(plot_filename), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
     { NULL }
 };
 
@@ -377,6 +379,65 @@ end:
     return ret;
 }
 
+static int dump_curves(const char *fname, uint8_t graph[NB_COMP + 1][256],
+                       struct keypoint *comp_points[NB_COMP + 1])
+{
+    int i;
+    AVBPrint buf;
+    static const char * const colors[] = { "red", "green", "blue", "#404040", };
+    FILE *f = av_fopen_utf8(fname, "w");
+
+    av_assert0(FF_ARRAY_ELEMS(colors) == NB_COMP + 1);
+
+    if (!f) {
+        int ret = AVERROR(errno);
+        av_log(NULL, AV_LOG_ERROR, "Cannot open file '%s' for writing: %s\n",
+               fname, av_err2str(ret));
+        return ret;
+    }
+
+    av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED);
+
+    av_bprintf(&buf, "set xtics 0.1\n");
+    av_bprintf(&buf, "set ytics 0.1\n");
+    av_bprintf(&buf, "set size square\n");
+    av_bprintf(&buf, "set grid\n");
+
+    for (i = 0; i < FF_ARRAY_ELEMS(colors); i++) {
+        av_bprintf(&buf, "%s'-' using 1:2 with lines lc '%s' title ''",
+                   i ? ", " : "plot ", colors[i]);
+        if (comp_points[i])
+            av_bprintf(&buf, ", '-' using 1:2 with points pointtype 3 lc '%s' title ''",
+                    colors[i]);
+    }
+    av_bprintf(&buf, "\n");
+
+    for (i = 0; i < FF_ARRAY_ELEMS(colors); i++) {
+        int x;
+
+        /* plot generated values */
+        for (x = 0; x < 256; x++)
+            av_bprintf(&buf, "%f %f\n", x/255., graph[i][x]/255.);
+        av_bprintf(&buf, "e\n");
+
+        /* plot user knots */
+        if (comp_points[i]) {
+            const struct keypoint *point = comp_points[i];
+
+            while (point) {
+                av_bprintf(&buf, "%f %f\n", point->x, point->y);
+                point = point->next;
+            }
+            av_bprintf(&buf, "e\n");
+        }
+    }
+
+    fwrite(buf.str, 1, buf.len, f);
+    fclose(f);
+    av_bprint_finalize(&buf, NULL);
+    return 0;
+}
+
 static av_cold int init(AVFilterContext *ctx)
 {
     int i, j, ret;
@@ -448,6 +509,9 @@ static av_cold int init(AVFilterContext *ctx)
         }
     }
 
+    if (curves->plot_filename)
+        dump_curves(curves->plot_filename, curves->graph, comp_points);
+
     for (i = 0; i < NB_COMP + 1; i++) {
         struct keypoint *point = comp_points[i];
         while (point) {