summaryrefslogtreecommitdiff
path: root/libavfilter/vsrc_testsrc.c
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2022-04-10 19:12:53 +0200
committerPaul B Mahol <onemda@gmail.com>2022-04-23 11:00:42 +0200
commit16463520d9de05481320303dd49ea5158c715c9f (patch)
tree9395f599d4278f353a45c61e09250642b60b7a21 /libavfilter/vsrc_testsrc.c
parent43ea19fef4ce233510df99f68f85548e834a1995 (diff)
downloadffmpeg-16463520d9de05481320303dd49ea5158c715c9f.tar.gz
avfilter: add colorchart video filter
Diffstat (limited to 'libavfilter/vsrc_testsrc.c')
-rw-r--r--libavfilter/vsrc_testsrc.c153
1 files changed, 153 insertions, 0 deletions
diff --git a/libavfilter/vsrc_testsrc.c b/libavfilter/vsrc_testsrc.c
index f859cf2f48..32f13c0c40 100644
--- a/libavfilter/vsrc_testsrc.c
+++ b/libavfilter/vsrc_testsrc.c
@@ -55,6 +55,7 @@
typedef struct TestSourceContext {
const AVClass *class;
int w, h;
+ int pw, ph;
unsigned int nb_frame;
AVRational time_base, frame_rate;
int64_t pts;
@@ -1885,3 +1886,155 @@ const AVFilter ff_vsrc_colorspectrum = {
};
#endif /* CONFIG_COLORSPECTRUM_FILTER */
+
+#if CONFIG_COLORCHART_FILTER
+
+static const AVOption colorchart_options[] = {
+ COMMON_OPTIONS_NOSIZE
+ { "patch_size", "set the single patch size", OFFSET(pw), AV_OPT_TYPE_IMAGE_SIZE, {.str="64x64"}, 0, 0, FLAGS },
+ { "preset", "set the color checker chart preset", OFFSET(type), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "preset" },
+ { "reference", "reference", 0, AV_OPT_TYPE_CONST,{.i64=0}, 0, 0, FLAGS, "preset" },
+ { "skintones", "skintones", 0, AV_OPT_TYPE_CONST,{.i64=1}, 0, 0, FLAGS, "preset" },
+ { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(colorchart);
+
+static const uint8_t reference_colors[][3] = {
+ { 115, 82, 68 }, // dark skin
+ { 194, 150, 130 }, // light skin
+ { 98, 122, 157 }, // blue sky
+ { 87, 108, 67 }, // foliage
+ { 133, 128, 177 }, // blue flower
+ { 103, 189, 170 }, // bluish green
+
+ { 214, 126, 44 }, // orange
+ { 80, 91, 166 }, // purple red
+ { 193, 90, 99 }, // moderate red
+ { 94, 60, 108 }, // purple
+ { 157, 188, 64 }, // yellow green
+ { 224, 163, 46 }, // orange yellow
+
+ { 56, 61, 150 }, // blue
+ { 70, 148, 73 }, // green
+ { 175, 54, 60 }, // red
+ { 233, 199, 31 }, // yellow
+ { 187, 86, 149 }, // magenta
+ { 8, 133, 161 }, // cyan
+
+ { 243, 243, 242 }, // white
+ { 200, 200, 200 }, // neutral 8
+ { 160, 160, 160 }, // neutral 65
+ { 122, 122, 121 }, // neutral 5
+ { 85, 85, 85 }, // neutral 35
+ { 52, 52, 52 }, // black
+};
+
+static const uint8_t skintones_colors[][3] = {
+ { 54, 38, 43 },
+ { 105, 43, 42 },
+ { 147, 43, 43 },
+ { 77, 41, 42 },
+ { 134, 43, 41 },
+ { 201, 134, 118 },
+
+ { 59, 41, 41 },
+ { 192, 103, 76 },
+ { 208, 156, 141 },
+ { 152, 82, 61 },
+ { 162, 132, 118 },
+ { 212, 171, 150 },
+
+ { 205, 91, 31 },
+ { 164, 100, 55 },
+ { 204, 136, 95 },
+ { 178, 142, 116 },
+ { 210, 152, 108 },
+ { 217, 167, 131 },
+
+ { 206, 166, 126 },
+ { 208, 163, 97 },
+ { 245, 180, 0 },
+ { 212, 184, 125 },
+ { 179, 165, 150 },
+ { 196, 184, 105 },
+};
+
+typedef struct ColorChartPreset {
+ int w, h;
+ const uint8_t (*colors)[3];
+} ColorChartPreset;
+
+static const ColorChartPreset colorchart_presets[] = {
+ { 6, 4, reference_colors, },
+ { 6, 4, skintones_colors, },
+};
+
+static int colorchart_config_props(AVFilterLink *inlink)
+{
+ AVFilterContext *ctx = inlink->src;
+ TestSourceContext *s = ctx->priv;
+
+ av_assert0(ff_draw_init(&s->draw, inlink->format, 0) >= 0);
+ if (av_image_check_size(s->w, s->h, 0, ctx) < 0)
+ return AVERROR(EINVAL);
+ return config_props(inlink);
+}
+
+static void colorchart_fill_picture(AVFilterContext *ctx, AVFrame *frame)
+{
+ TestSourceContext *test = ctx->priv;
+ const int preset = test->type;
+ const int w = colorchart_presets[preset].w;
+ const int h = colorchart_presets[preset].h;
+ const int pw = test->pw;
+ const int ph = test->pw;
+
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++) {
+ uint32_t pc = AV_RB24(colorchart_presets[preset].colors[y * w + x]);
+ FFDrawColor color;
+
+ set_color(test, &color, pc);
+ ff_fill_rectangle(&test->draw, &color, frame->data, frame->linesize,
+ x * pw, y * ph, pw, ph);
+ }
+ }
+}
+
+static av_cold int colorchart_init(AVFilterContext *ctx)
+{
+ TestSourceContext *test = ctx->priv;
+ const int preset = test->type;
+ const int w = colorchart_presets[preset].w;
+ const int h = colorchart_presets[preset].h;
+
+ test->w = w * test->pw;
+ test->h = h * test->ph;
+ test->draw_once = 1;
+ test->fill_picture_fn = colorchart_fill_picture;
+ return init(ctx);
+}
+
+static const AVFilterPad avfilter_vsrc_colorchart_outputs[] = {
+ {
+ .name = "default",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .config_props = colorchart_config_props,
+ },
+};
+
+const AVFilter ff_vsrc_colorchart = {
+ .name = "colorchart",
+ .description = NULL_IF_CONFIG_SMALL("Generate color checker chart."),
+ .priv_size = sizeof(TestSourceContext),
+ .priv_class = &colorchart_class,
+ .init = colorchart_init,
+ .uninit = uninit,
+ .activate = activate,
+ .inputs = NULL,
+ FILTER_OUTPUTS(avfilter_vsrc_colorchart_outputs),
+ FILTER_SINGLE_PIXFMT(AV_PIX_FMT_GBRP),
+};
+
+#endif /* CONFIG_COLORCHART_FILTER */