Browse code

lavfi/curves: add support for Photoshop curves files (.acv).

Clément Bœsch authored on 2013/04/15 10:49:36
Showing 3 changed files
... ...
@@ -2346,6 +2346,8 @@ Set the key points for all components (not including master).
2346 2346
 Can be used in addition to the other key points component
2347 2347
 options. In this case, the unset component(s) will fallback on this
2348 2348
 @option{all} setting.
2349
+@item psfile
2350
+Specify a Photoshop curves file (@code{.asv}) to import the settings from.
2349 2351
 @end table
2350 2352
 
2351 2353
 To avoid some filtergraph syntax conflicts, each key points list need to be
... ...
@@ -30,7 +30,7 @@
30 30
 
31 31
 #define LIBAVFILTER_VERSION_MAJOR  3
32 32
 #define LIBAVFILTER_VERSION_MINOR  56
33
-#define LIBAVFILTER_VERSION_MICRO 100
33
+#define LIBAVFILTER_VERSION_MICRO 101
34 34
 
35 35
 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
36 36
                                                LIBAVFILTER_VERSION_MINOR, \
... ...
@@ -19,7 +19,10 @@
19 19
  */
20 20
 
21 21
 #include "libavutil/opt.h"
22
+#include "libavutil/bprint.h"
22 23
 #include "libavutil/eval.h"
24
+#include "libavutil/file.h"
25
+#include "libavutil/intreadwrite.h"
23 26
 #include "libavutil/avassert.h"
24 27
 #include "avfilter.h"
25 28
 #include "formats.h"
... ...
@@ -54,6 +57,7 @@ typedef struct {
54 54
     char *comp_points_str[NB_COMP + 1];
55 55
     char *comp_points_str_all;
56 56
     uint8_t graph[NB_COMP + 1][256];
57
+    char *psfile;
57 58
 } CurvesContext;
58 59
 
59 60
 #define OFFSET(x) offsetof(CurvesContext, x)
... ...
@@ -80,6 +84,7 @@ static const AVOption curves_options[] = {
80 80
     { "blue",  "set blue points coordinates",  OFFSET(comp_points_str[2]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
81 81
     { "b",     "set blue points coordinates",  OFFSET(comp_points_str[2]), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
82 82
     { "all",   "set points coordinates for all components", OFFSET(comp_points_str_all), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
83
+    { "psfile", "set Photoshop curves file name", OFFSET(psfile), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS },
83 84
     { NULL }
84 85
 };
85 86
 
... ...
@@ -297,6 +302,60 @@ end:
297 297
     return ret;
298 298
 }
299 299
 
300
+static int parse_psfile(AVFilterContext *ctx, const char *fname)
301
+{
302
+    CurvesContext *curves = ctx->priv;
303
+    uint8_t *buf;
304
+    size_t size;
305
+    int i, ret, av_unused(version), nb_curves;
306
+    AVBPrint ptstr;
307
+    static const int comp_ids[] = {3, 0, 1, 2};
308
+
309
+    av_bprint_init(&ptstr, 0, AV_BPRINT_SIZE_AUTOMATIC);
310
+
311
+    ret = av_file_map(fname, &buf, &size, 0, NULL);
312
+    if (ret < 0)
313
+        return ret;
314
+
315
+#define READ16(dst) do {                \
316
+    if (size < 2)                       \
317
+        return AVERROR_INVALIDDATA;     \
318
+    dst = AV_RB16(buf);                 \
319
+    buf  += 2;                          \
320
+    size -= 2;                          \
321
+} while (0)
322
+
323
+    READ16(version);
324
+    READ16(nb_curves);
325
+    for (i = 0; i < FFMIN(nb_curves, FF_ARRAY_ELEMS(comp_ids)); i++) {
326
+        int nb_points, n;
327
+        av_bprint_clear(&ptstr);
328
+        READ16(nb_points);
329
+        for (n = 0; n < nb_points; n++) {
330
+            int y, x;
331
+            READ16(y);
332
+            READ16(x);
333
+            av_bprintf(&ptstr, "%f/%f ", x / 255., y / 255.);
334
+        }
335
+        if (*ptstr.str) {
336
+            char **pts = &curves->comp_points_str[comp_ids[i]];
337
+            if (!*pts) {
338
+                *pts = av_strdup(ptstr.str);
339
+                av_log(ctx, AV_LOG_DEBUG, "curves %d (intid=%d) [%d points]: [%s]\n",
340
+                       i, comp_ids[i], nb_points, *pts);
341
+                if (!*pts) {
342
+                    ret = AVERROR(ENOMEM);
343
+                    goto end;
344
+                }
345
+            }
346
+        }
347
+    }
348
+end:
349
+    av_bprint_finalize(&ptstr, NULL);
350
+    av_file_unmap(buf, size);
351
+    return ret;
352
+}
353
+
300 354
 static av_cold int init(AVFilterContext *ctx)
301 355
 {
302 356
     int i, j, ret;
... ...
@@ -317,6 +376,12 @@ static av_cold int init(AVFilterContext *ctx)
317 317
         }
318 318
     }
319 319
 
320
+    if (curves->psfile) {
321
+        ret = parse_psfile(ctx, curves->psfile);
322
+        if (ret < 0)
323
+            return ret;
324
+    }
325
+
320 326
     if (curves->preset != PRESET_NONE) {
321 327
 #define SET_COMP_IF_NOT_SET(n, name) do {                           \
322 328
     if (!pts[n] && curves_presets[curves->preset].name) {           \