[FFmpeg-devel] [PATCH] doc/filters: add more curves examples

Clément Bœsch ubitux at gmail.com
Mon Mar 25 01:23:27 CET 2013


On Sun, Mar 24, 2013 at 03:17:42PM -0800, Lou Logan wrote:
> These examples are similar to the default curves presets found in
> Adobe Photoshop CS6.
> 
> Only tested on lena.pnm.
> 
> Patch attached.

> From f8d6c0e7baf27a573b77f0f63c7c39d751899bd5 Mon Sep 17 00:00:00 2001
> From: Lou Logan <lou at lrcd.com>
> Date: Sun, 24 Mar 2013 15:11:41 -0800
> Subject: [PATCH] doc/filters: add more curves examples
> 
> These examples are similar to the default curves presets found in
> Adobe Photoshop CS6.
> ---
>  doc/filters.texi | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 54 insertions(+)
> 
[...]

I'd propose the attached patch instead. What do you think?

Please check I didn't copy/paste fail anything...

-- 
Clément B.
-------------- next part --------------
From 6a7736c9a030c6c8179b9796a428702c62ad0611 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= <ubitux at gmail.com>
Date: Mon, 25 Mar 2013 01:19:17 +0100
Subject: [PATCH] lavfi/curves: add presets support.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Except for the vintage preset, the values are defined by Lou Logan based
on the ones found in Adobe Photoshop CS6.

Signed-off-by: Clément Bœsch <ubitux at gmail.com>
Signed-off-by: Lou Logan <lou at lrcd.com>
---
 doc/filters.texi        | 22 +++++++++++++++
 libavfilter/vf_curves.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++
 tests/fate/filter.mak   |  2 +-
 3 files changed, 96 insertions(+), 1 deletion(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index f96a10a..38f62d7 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -2340,6 +2340,22 @@ Set the key points for the red component.
 Set the key points for the green component.
 @item blue, b
 Set the key points for the blue component.
+ at item preset
+Select one of the available color preset. This option can not be used in
+addition to the @option{r}, @option{g}, @option{b} parameters.
+Available presets are:
+ at table @samp
+ at item color_negative
+ at item cross_process
+ at item darker
+ at item increase_contrast
+ at item lighter
+ at item linear_contrast
+ at item medium_contrast
+ at item negative
+ at item vintage
+ at end table
+Default is unset.
 @end table
 
 To avoid some filtergraph syntax conflicts, each key points list need to be
@@ -2368,6 +2384,12 @@ Here we obtain the following coordinates for each components:
 @item blue
 @code{(0;0.22) (0.49;0.44) (1;0.80)}
 @end table
+
+ at item
+The previous example can also be achieved with the associated pre-defined preset:
+ at example
+curves=preset=vintage
+ at end example
 @end itemize
 
 @section decimate
diff --git a/libavfilter/vf_curves.c b/libavfilter/vf_curves.c
index 7fee90a..20f08fc 100644
--- a/libavfilter/vf_curves.c
+++ b/libavfilter/vf_curves.c
@@ -35,6 +35,7 @@ struct keypoint {
 
 typedef struct {
     const AVClass *class;
+    char *preset;
     char *comp_points_str[NB_COMP];
     uint8_t graph[NB_COMP][256];
 } CurvesContext;
@@ -48,11 +49,56 @@ 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 },
     { NULL }
 };
 
 AVFILTER_DEFINE_CLASS(curves);
 
+static const struct {
+    const char *name;
+    const char *r;
+    const char *g;
+    const char *b;
+} curves_presets[] = { {
+        "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",
+        "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",
+        "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",
+        "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",
+        "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",
+    },{
+        "vintage",
+        "0/0.11 .42/.51 1/0.95",
+        "0.50/0.48",
+        "0/0.22 .49/.44 1/0.8",
+    }
+};
+
 static struct keypoint *make_point(double x, double y, struct keypoint *next)
 {
     struct keypoint *point = av_mallocz(sizeof(*point));
@@ -247,6 +293,33 @@ static av_cold int init(AVFilterContext *ctx, const char *args)
     if ((ret = av_set_options_string(curves, args, "=", ":")) < 0)
         return ret;
 
+    if (curves->preset) {
+        char **pts = curves->comp_points_str;
+        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);
+        }
+    }
+
     for (i = 0; i < NB_COMP; i++) {
         ret = parse_points_str(ctx, comp_points + i, curves->comp_points_str[i]);
         if (ret < 0)
diff --git a/tests/fate/filter.mak b/tests/fate/filter.mak
index e8b5c76..23724b1 100644
--- a/tests/fate/filter.mak
+++ b/tests/fate/filter.mak
@@ -48,7 +48,7 @@ FATE_HQDN3D += fate-filter-hqdn3d
 fate-filter-hqdn3d: CMD = framecrc -idct simple -i $(SAMPLES)/smjpeg/scenwin.mjpg -vf perms=random,hqdn3d -an
 FATE_FILTER-$(call ALLYES, SMJPEG_DEMUXER MJPEG_DECODER PERMS_FILTER HQDN3D_FILTER) += $(FATE_HQDN3D)
 
-fate-filter-curves: CMD = framecrc -i $(SAMPLES)/utvideo/utvideo_rgb_median.avi -vf "perms=random,curves=r=0/0.11 at .42/.51 at 1/0.95:g=0.50/0.48:b=0/0.22 at .49/.44 at 1/0.8"
+fate-filter-curves: CMD = framecrc -i $(SAMPLES)/utvideo/utvideo_rgb_median.avi -vf perms=random,curves=preset=vintage
 FATE_FILTER-$(call ALLYES, UTVIDEO_DECODER AVI_DEMUXER PERMS_FILTER CURVES_FILTER) += fate-filter-curves
 
 FATE_GRADFUN += fate-filter-gradfun
-- 
1.8.2

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 490 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20130325/f5e580ce/attachment.asc>


More information about the ffmpeg-devel mailing list