diff --git a/doc/filters.texi b/doc/filters.texi index 22f9e36a2d..7c6003ac3d 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -18945,6 +18945,7 @@ Set vectorscope mode. It accepts the following values: @table @samp @item gray +@item tint Gray values are displayed on graph, higher brightness means more pixels have same component color value on location in graph. This is the default mode. @@ -19048,6 +19049,11 @@ Set what kind of colorspace to use when drawing graticule. @item 709 @end table Default is auto. + +@item tint0, t0 +@item tint1, t1 +Set color tint for gray/tint vectorscope mode. By default both options are zero. +This means no tint, and output will remain gray. @end table @anchor{vidstabdetect} diff --git a/libavfilter/vf_vectorscope.c b/libavfilter/vf_vectorscope.c index fe1d17503d..7355e5f426 100644 --- a/libavfilter/vf_vectorscope.c +++ b/libavfilter/vf_vectorscope.c @@ -38,7 +38,7 @@ enum GraticuleType { }; enum VectorscopeMode { - GRAY, + TINT, COLOR, COLOR2, COLOR3, @@ -53,6 +53,7 @@ typedef struct VectorscopeContext { int intensity; float fintensity; uint16_t bg_color[4]; + float ftint[2]; int planewidth[4]; int planeheight[4]; int hsub, vsub; @@ -67,6 +68,7 @@ typedef struct VectorscopeContext { float bgopacity; float lthreshold; float hthreshold; + int tint[2]; int tmin; int tmax; int flags; @@ -87,7 +89,8 @@ typedef struct VectorscopeContext { static const AVOption vectorscope_options[] = { { "mode", "set vectorscope mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, MODE_NB-1, FLAGS, "mode"}, { "m", "set vectorscope mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, MODE_NB-1, FLAGS, "mode"}, - { "gray", 0, 0, AV_OPT_TYPE_CONST, {.i64=GRAY}, 0, 0, FLAGS, "mode" }, + { "gray", 0, 0, AV_OPT_TYPE_CONST, {.i64=TINT}, 0, 0, FLAGS, "mode" }, + { "tint", 0, 0, AV_OPT_TYPE_CONST, {.i64=TINT}, 0, 0, FLAGS, "mode" }, { "color", 0, 0, AV_OPT_TYPE_CONST, {.i64=COLOR}, 0, 0, FLAGS, "mode" }, { "color2", 0, 0, AV_OPT_TYPE_CONST, {.i64=COLOR2}, 0, 0, FLAGS, "mode" }, { "color3", 0, 0, AV_OPT_TYPE_CONST, {.i64=COLOR3}, 0, 0, FLAGS, "mode" }, @@ -127,6 +130,10 @@ static const AVOption vectorscope_options[] = { { "auto", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "colorspace" }, { "601", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "colorspace" }, { "709", 0, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "colorspace" }, + { "tint0", "set 1st tint", OFFSET(ftint[0]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS}, + { "t0", "set 1st tint", OFFSET(ftint[0]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS}, + { "tint1", "set 2nd tint", OFFSET(ftint[1]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS}, + { "t1", "set 2nd tint", OFFSET(ftint[1]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS}, { NULL } }; @@ -442,7 +449,7 @@ static void vectorscope16(VectorscopeContext *s, AVFrame *in, AVFrame *out, int switch (s->mode) { case COLOR: case COLOR5: - case GRAY: + case TINT: if (s->is_yuv) { for (i = 0; i < h; i++) { const int iwx = i * slinesizex; @@ -581,7 +588,17 @@ static void vectorscope16(VectorscopeContext *s, AVFrame *in, AVFrame *out, int } } - if (s->mode == COLOR) { + if (s->mode == TINT && (s->tint[0] != mid || + s->tint[1] != mid)) { + for (i = 0; i < out->height; i++) { + for (j = 0; j < out->width; j++) { + if (dpd[i * dlinesize + j]) { + dst[1][i * dlinesize + j] = s->tint[0]; + dst[2][i * dlinesize + j] = s->tint[1]; + } + } + } + } else if (s->mode == COLOR) { for (i = 0; i < out->height; i++) { for (j = 0; j < out->width; j++) { if (!dpd[i * dlinesize + j]) { @@ -636,7 +653,7 @@ static void vectorscope8(VectorscopeContext *s, AVFrame *in, AVFrame *out, int p switch (s->mode) { case COLOR5: case COLOR: - case GRAY: + case TINT: if (s->is_yuv) { for (i = 0; i < h; i++) { const int iwx = i * slinesizex; @@ -775,7 +792,17 @@ static void vectorscope8(VectorscopeContext *s, AVFrame *in, AVFrame *out, int p } } - if (s->mode == COLOR) { + if (s->mode == TINT && (s->tint[0] != 128 || + s->tint[1] != 128)) { + for (i = 0; i < out->height; i++) { + for (j = 0; j < out->width; j++) { + if (dpd[i * dlinesize + j]) { + dst[1][i * dlinesize + j] = s->tint[0]; + dst[2][i * dlinesize + j] = s->tint[1]; + } + } + } + } else if (s->mode == COLOR) { for (i = 0; i < out->height; i++) { for (j = 0; j < out->width; j++) { if (!dpd[i * out->linesize[pd] + j]) { @@ -1483,9 +1510,9 @@ static int config_input(AVFilterLink *inlink) return AVERROR(EINVAL); } - if (s->mode == GRAY && s->is_yuv) + if (s->mode == TINT && s->is_yuv) { s->pd = 0; - else { + } else { if ((s->x == 1 && s->y == 2) || (s->x == 2 && s->y == 1)) s->pd = 0; else if ((s->x == 0 && s->y == 2) || (s->x == 2 && s->y == 0)) @@ -1519,6 +1546,9 @@ static int config_input(AVFilterLink *inlink) s->bg_color[3] = s->bgopacity * (s->size - 1); + s->tint[0] = .5f * (s->ftint[0] + 1.f) * (s->size - 1); + s->tint[1] = .5f * (s->ftint[1] + 1.f) * (s->size - 1); + switch (inlink->format) { case AV_PIX_FMT_GBRP12: case AV_PIX_FMT_GBRP10: @@ -1531,8 +1561,8 @@ static int config_input(AVFilterLink *inlink) break; default: s->bg_color[0] = 0; - s->bg_color[1] = s->size / 2 - 1; - s->bg_color[2] = s->size / 2 - 1; + s->bg_color[1] = s->size / 2; + s->bg_color[2] = s->size / 2; } s->hsub = desc->log2_chroma_w; diff --git a/tests/ref/fate/filter-vectorscope_color b/tests/ref/fate/filter-vectorscope_color index 57875ab418..81d97d4fae 100644 --- a/tests/ref/fate/filter-vectorscope_color +++ b/tests/ref/fate/filter-vectorscope_color @@ -3,6 +3,6 @@ #codec_id 0: rawvideo #dimensions 0: 256x256 #sar 0: 1/1 -0, 0, 0, 1, 196608, 0xf6e3aa30 -0, 1, 1, 1, 196608, 0x5584acf9 -0, 2, 2, 1, 196608, 0xa862775d +0, 0, 0, 1, 196608, 0x7c431d1f +0, 1, 1, 1, 196608, 0xb7e82028 +0, 2, 2, 1, 196608, 0x2feeeb61 diff --git a/tests/ref/fate/filter-vectorscope_color2 b/tests/ref/fate/filter-vectorscope_color2 index 3b2ad90b9c..adbe9e65bc 100644 --- a/tests/ref/fate/filter-vectorscope_color2 +++ b/tests/ref/fate/filter-vectorscope_color2 @@ -3,6 +3,6 @@ #codec_id 0: rawvideo #dimensions 0: 256x256 #sar 0: 1/1 -0, 0, 0, 1, 196608, 0x5e62fae5 -0, 1, 1, 1, 196608, 0x4c27fcbf -0, 2, 2, 1, 196608, 0xb7531088 +0, 0, 0, 1, 196608, 0xdad38823 +0, 1, 1, 1, 196608, 0xeb8589bd +0, 2, 2, 1, 196608, 0x31a79c93 diff --git a/tests/ref/fate/filter-vectorscope_color3 b/tests/ref/fate/filter-vectorscope_color3 index 4baecca921..2b6a6b08fb 100644 --- a/tests/ref/fate/filter-vectorscope_color3 +++ b/tests/ref/fate/filter-vectorscope_color3 @@ -3,6 +3,6 @@ #codec_id 0: rawvideo #dimensions 0: 256x256 #sar 0: 1/1 -0, 0, 0, 1, 196608, 0x83df8770 -0, 1, 1, 1, 196608, 0xa6a674a7 -0, 2, 2, 1, 196608, 0x11757143 +0, 0, 0, 1, 196608, 0x005f14ae +0, 1, 1, 1, 196608, 0x461301a5 +0, 2, 2, 1, 196608, 0x8bbafd4e diff --git a/tests/ref/fate/filter-vectorscope_color4 b/tests/ref/fate/filter-vectorscope_color4 index 21d6762ff2..fcc21b7857 100644 --- a/tests/ref/fate/filter-vectorscope_color4 +++ b/tests/ref/fate/filter-vectorscope_color4 @@ -3,6 +3,6 @@ #codec_id 0: rawvideo #dimensions 0: 256x256 #sar 0: 1/1 -0, 0, 0, 1, 196608, 0x326953c4 -0, 1, 1, 1, 196608, 0x870e1dcc -0, 2, 2, 1, 196608, 0x87cb8800 +0, 0, 0, 1, 196608, 0xaedae0f3 +0, 1, 1, 1, 196608, 0x267baabb +0, 2, 2, 1, 196608, 0x021f141a diff --git a/tests/ref/fate/filter-vectorscope_gray b/tests/ref/fate/filter-vectorscope_gray index a81fbf8f87..78fb1d70c3 100644 --- a/tests/ref/fate/filter-vectorscope_gray +++ b/tests/ref/fate/filter-vectorscope_gray @@ -3,6 +3,6 @@ #codec_id 0: rawvideo #dimensions 0: 256x256 #sar 0: 1/1 -0, 0, 0, 1, 196608, 0x79ba71e2 -0, 1, 1, 1, 196608, 0x909271e2 -0, 2, 2, 1, 196608, 0x143971e2 +0, 0, 0, 1, 196608, 0xf62bff11 +0, 1, 1, 1, 196608, 0x2ffffed1 +0, 2, 2, 1, 196608, 0x8e7efded diff --git a/tests/ref/fate/filter-vectorscope_xy b/tests/ref/fate/filter-vectorscope_xy index 83b719468c..6ab64e1f19 100644 --- a/tests/ref/fate/filter-vectorscope_xy +++ b/tests/ref/fate/filter-vectorscope_xy @@ -3,6 +3,6 @@ #codec_id 0: rawvideo #dimensions 0: 256x256 #sar 0: 1/1 -0, 0, 0, 1, 196608, 0xa2899af1 -0, 1, 1, 1, 196608, 0x26409af1 -0, 2, 2, 1, 196608, 0xf5209af1 +0, 0, 0, 1, 196608, 0xd2bfcc40 +0, 1, 1, 1, 196608, 0x2851cb74 +0, 2, 2, 1, 196608, 0x48efcc64