[FFmpeg-cvslog] avfilter/vf_pseudocolor: add cool preset

Paul B Mahol git at videolan.org
Thu Jul 20 00:36:14 EEST 2023


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Wed Jul 19 22:48:54 2023 +0200| [5d8879208cd76e76ae5d093b207787979bea0cb1] | committer: Paul B Mahol

avfilter/vf_pseudocolor: add cool preset

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=5d8879208cd76e76ae5d093b207787979bea0cb1
---

 doc/filters.texi             |  1 +
 libavfilter/vf_pseudocolor.c | 58 +++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 55 insertions(+), 4 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index e5325c7410..c6d331d12a 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -19706,6 +19706,7 @@ Available LUTs:
 @item preferred
 @item total
 @item spectral
+ at item cool
 @end table
 
 @item opacity
diff --git a/libavfilter/vf_pseudocolor.c b/libavfilter/vf_pseudocolor.c
index 89dc2f0901..8475d4f4df 100644
--- a/libavfilter/vf_pseudocolor.c
+++ b/libavfilter/vf_pseudocolor.c
@@ -68,6 +68,7 @@ enum Curves {
     CIVIDIS,
     SOLAR,
     SPECTRAL,
+    COOL,
     NB_CURVES,
 };
 
@@ -87,6 +88,7 @@ enum Presets {
     PRESET_PREFERRED,
     PRESET_TOTAL,
     PRESET_SPECTRAL,
+    PRESET_COOL,
     NB_PRESETS,
 };
 
@@ -96,6 +98,7 @@ typedef struct Curve {
     double coef[3][8];
     double offset[3];
     curve_fun fun[3];
+    int yuv;
 } Curve;
 
 typedef struct Fill {
@@ -137,6 +140,16 @@ static double solarfun(double x)
     return 0.5 * sin(x) + 0.5;
 }
 
+static double coolfunu(double x)
+{
+    return 0.25 * sin(2.0 * x * M_PI - M_PI) + 0.5;
+}
+
+static double coolfunv(double x)
+{
+    return 0.25 * sin(2.0 * x * M_PI) + 0.5;
+}
+
 static const Curve curves[] =
 {
     [MAGMA] = {{
@@ -181,6 +194,14 @@ static const Curve curves[] =
         {  1.2526e-15,  -1.2203e-12,   4.7013e-10,  -8.9360e-08,   8.3839e-06,  -3.6642e-04, 1.4784e-02,  -9.8075e-03 },
         {  1.4755e-15,  -1.6765e-12,   7.3188e-10,  -1.5522e-07,   1.6406e-05,  -7.7883e-04, 1.4502e-02,   2.1597e-01 },
     }, .fun = { limit, limit, limit }, },
+    [COOL] = {{
+        { 0, 0, 0, 0, 0, 0, 1./256, 0 },
+        { 0, 0, 0, 0, 0, 0, 1./256, 0 },
+        { 0, 0, 0, 0, 0, 0, 1./256, 0 },
+    },
+    .offset = { 0., 0., 0 },
+    .yuv = 1,
+    .fun = { coolfunu, limit, coolfunv }, },
 };
 
 static const Preset presets[] =
@@ -200,6 +221,7 @@ static const Preset presets[] =
     [PRESET_HIGHLIGHTS] = { 3, highlights_range, NULL,     highlights_fills },
     [PRESET_SOLAR]   = { 1, &full_range, &curves[SOLAR],   NULL },
     [PRESET_SPECTRAL]= { 1, &full_range, &curves[SPECTRAL],NULL },
+    [PRESET_COOL]    = { 1, &full_range, &curves[COOL],    NULL },
 };
 
 typedef struct PseudoColorContext {
@@ -255,6 +277,7 @@ static const AVOption pseudocolor_options[] = {
     { "preferred",  NULL,                  0,                        AV_OPT_TYPE_CONST,  {.i64=PRESET_PREFERRED},.flags=FLAGS,"preset" },
     { "total",      NULL,                  0,                        AV_OPT_TYPE_CONST,  {.i64=PRESET_TOTAL},   .flags=FLAGS, "preset" },
     { "spectral",   NULL,                  0,                        AV_OPT_TYPE_CONST,  {.i64=PRESET_SPECTRAL},.flags = FLAGS, "preset" },
+    { "cool",       NULL,                  0,                        AV_OPT_TYPE_CONST,  {.i64=PRESET_COOL},    .flags = FLAGS, "preset" },
     { "opacity", "set pseudocolor opacity",OFFSET(opacity),          AV_OPT_TYPE_FLOAT,  {.dbl=1}, 0, 1, .flags = FLAGS },
     { NULL }
 };
@@ -571,6 +594,19 @@ static void pseudocolor_filter_16_11d(int max, int width, int height,
 ((0.50000*224.0/255.0) * r1 - (0.45415*224.0/255.0) * g1 - \
    (0.04585*224.0/255.0) * b1 + max * 0.5)
 
+#define Wr 0.2126
+#define Wb 0.0722
+#define Wg (1 - Wr - Wb)
+#define Umax 0.436
+#define Vmax 0.615
+
+#define YUV_BT709_TO_R(y, u, v, max) \
+    ((y + v * (1 - Wr) / Vmax) * max)
+#define YUV_BT709_TO_G(y, u, v, max) \
+    ((y - (u * Wb * (1 - Wb) / (Umax * Wg)) - (v * Wr * (1 - Wr) / (Vmax * Wg))) * max)
+#define YUV_BT709_TO_B(y, u, v, max) \
+    ((y + u * (1 - Wb) / Umax) * max)
+
 static double poly_eval(const double *const poly, double x, curve_fun fun)
 {
     double res = 0.;
@@ -696,11 +732,17 @@ static int config_input(AVFilterLink *inlink)
                     const double lf = i / (double)s->max * 256.;
                     double r, g, b;
 
-                    g = poly_eval(curve.coef[1], lf + curve.offset[1], curve.fun[1]) * s->max;
-                    b = poly_eval(curve.coef[2], lf + curve.offset[2], curve.fun[2]) * s->max;
-                    r = poly_eval(curve.coef[0], lf + curve.offset[0], curve.fun[0]) * s->max;
+                    g = poly_eval(curve.coef[1], lf + curve.offset[1], curve.fun[1]);
+                    b = poly_eval(curve.coef[2], lf + curve.offset[2], curve.fun[2]);
+                    r = poly_eval(curve.coef[0], lf + curve.offset[0], curve.fun[0]);
+
+                    if (!curve.yuv || !rgb) {
+                        g *= s->max;
+                        b *= s->max;
+                        r *= s->max;
+                    }
 
-                    if (!rgb) {
+                    if (!rgb && !curve.yuv) {
                         double y = RGB_TO_Y_BT709(r, g, b);
                         double u = RGB_TO_U_BT709(r, g, b, s->max);
                         double v = RGB_TO_V_BT709(r, g, b, s->max);
@@ -708,6 +750,14 @@ static int config_input(AVFilterLink *inlink)
                         r = v;
                         g = y;
                         b = u;
+                    } else if (rgb && curve.yuv) {
+                        double y = g;
+                        double u = b - 0.5;
+                        double v = r - 0.5;
+
+                        r = av_clipd(YUV_BT709_TO_R(y, u, v, s->max), 0, s->max);
+                        g = av_clipd(YUV_BT709_TO_G(y, u, v, s->max), 0, s->max);
+                        b = av_clipd(YUV_BT709_TO_B(y, u, v, s->max), 0, s->max);
                     }
 
                     s->lut[0][i] = g;



More information about the ffmpeg-cvslog mailing list