History

avfilter/vf_colorkey: add >8 depth support

Paul B Mahol committed 4 years ago

Commit c3f5f1b1 parent 9d20f641 file · +107 −85Browse files

Showing the changes to libavfilter (1 of 1 file). Show all

Unified · Split

libavfilter/vf_colorkey.c+107−85
@@ -23,6 +23,7 @@ · 22 unmodified lines
2323 #include "libavutil/opt.h"
2424 #include "libavutil/imgutils.h"
2525 #include "avfilter.h"
26+#include "drawutils.h"
2627 #include "formats.h"
2728 #include "internal.h"
2829 #include "video.h"
@@ -31,105 +32,120 @@ typedef struct ColorkeyContext { · 2 unmodified lines
3132 const AVClass *class;
3233
3334 /* color offsets rgba */
34− int co[4];
35+ uint8_t co[4];
3536
3637 uint8_t colorkey_rgba[4];
3738 float similarity;
3839 float blend;
40+ double scale;
41+ int depth;
42+ int max;
3943
4044 int (*do_slice)(AVFilterContext *ctx, void *arg,
4145 int jobnr, int nb_jobs);
4246 } ColorkeyContext;
4347
44−static uint8_t do_colorkey_pixel(ColorkeyContext *ctx, uint8_t r, uint8_t g, uint8_t b)
48+static int do_colorkey_pixel(const uint8_t *colorkey_rgba, int r, int g, int b,
49+ float similarity, float blend, int max, double scale)
4550 {
46− int dr = (int)r - ctx->colorkey_rgba[0];
47− int dg = (int)g - ctx->colorkey_rgba[1];
48− int db = (int)b - ctx->colorkey_rgba[2];
51+ double dr, dg, db, diff;
4952
50− double diff = sqrt((dr * dr + dg * dg + db * db) / (255.0 * 255.0 * 3.0));
53+ dr = r * scale - colorkey_rgba[0];
54+ dg = g * scale - colorkey_rgba[1];
55+ db = b * scale - colorkey_rgba[2];
5156
52− if (ctx->blend > 0.0001) {
53− return av_clipd((diff - ctx->similarity) / ctx->blend, 0.0, 1.0) * 255.0;
57+ diff = sqrt((dr * dr + dg * dg + db * db) / (255.0 * 255.0 * 3.0));
58+
59+ if (blend > 0.0001) {
60+ return av_clipd((diff - similarity) / blend, 0.0, 1.0) * max;
5461 } else {
55− return (diff > ctx->similarity) ? 255 : 0;
62+ return (diff > similarity) ? max : 0;
5663 }
5764 }
5865
59−static int do_colorkey_slice(AVFilterContext *avctx, void *arg, int jobnr, int nb_jobs)
60−{
61− AVFrame *frame = arg;
62−
63− const int slice_start = (frame->height * jobnr) / nb_jobs;
64− const int slice_end = (frame->height * (jobnr + 1)) / nb_jobs;
65−
66− ColorkeyContext *ctx = avctx->priv;
67−
68− int o, x, y;
69−
70− for (y = slice_start; y < slice_end; ++y) {
71− for (x = 0; x < frame->width; ++x) {
72− o = frame->linesize[0] * y + x * 4;
73−
74− frame->data[0][o + ctx->co[3]] =
75− do_colorkey_pixel(ctx,
76− frame->data[0][o + ctx->co[0]],
77− frame->data[0][o + ctx->co[1]],
78− frame->data[0][o + ctx->co[2]]);
79− }
80− }
81−
82− return 0;
66+#define COLORKEY_SLICE(name, type) \
67+static int do_colorkey_slice##name(AVFilterContext *avctx, \
68+ void *arg, \
69+ int jobnr, int nb_jobs) \
70+{ \
71+ AVFrame *frame = arg; \
72+ const int slice_start = (frame->height * jobnr) / nb_jobs; \
73+ const int slice_end = (frame->height * (jobnr + 1)) / nb_jobs; \
74+ ColorkeyContext *ctx = avctx->priv; \
75+ const float similarity = ctx->similarity; \
76+ const float blend = ctx->blend; \
77+ const uint8_t *colorkey_rgba = ctx->colorkey_rgba; \
78+ const uint8_t *co = ctx->co; \
79+ const double scale = ctx->scale; \
80+ const int max = ctx->max; \
81+ \
82+ for (int y = slice_start; y < slice_end; y++) { \
83+ type *dst = (type *)(frame->data[0] + y * frame->linesize[0]);\
84+ \
85+ for (int x = 0; x < frame->width; x++) { \
86+ const int o = x * 4; \
87+ \
88+ dst[o + co[3]] = do_colorkey_pixel(colorkey_rgba, \
89+ dst[o + co[0]], \
90+ dst[o + co[1]], \
91+ dst[o + co[2]], \
92+ similarity, blend, max, scale); \
93+ } \
94+ } \
95+ \
96+ return 0; \
8397 }
8498
85−static int do_colorhold_slice(AVFilterContext *avctx, void *arg, int jobnr, int nb_jobs)
86−{
87− AVFrame *frame = arg;
88−
89− const int slice_start = (frame->height * jobnr) / nb_jobs;
90− const int slice_end = (frame->height * (jobnr + 1)) / nb_jobs;
91−
92− ColorkeyContext *ctx = avctx->priv;
93−
94− int x, y;
95−
96− for (y = slice_start; y < slice_end; ++y) {
97− for (x = 0; x < frame->width; ++x) {
98− int o, t, r, g, b;
99−
100− o = frame->linesize[0] * y + x * 4;
101− r = frame->data[0][o + ctx->co[0]];
102− g = frame->data[0][o + ctx->co[1]];
103− b = frame->data[0][o + ctx->co[2]];
104−
105− t = do_colorkey_pixel(ctx, r, g, b);
106−
107− if (t > 0) {
108− int a = (r + g + b) / 3;
109− int rt = 255 - t;
110−
111− frame->data[0][o + ctx->co[0]] = (a * t + r * rt + 127) >> 8;
112− frame->data[0][o + ctx->co[1]] = (a * t + g * rt + 127) >> 8;
113− frame->data[0][o + ctx->co[2]] = (a * t + b * rt + 127) >> 8;
114− }
115− }
116− }
117−
118− return 0;
99+COLORKEY_SLICE(8, uint8_t)
100+COLORKEY_SLICE(16, uint16_t)
101+
102+#define COLORHOLD_SLICE(name, type, htype) \
103+static int do_colorhold_slice##name(AVFilterContext *avctx, void *arg, \
104+ int jobnr, int nb_jobs) \
105+{ \
106+ AVFrame *frame = arg; \
107+ const int slice_start = (frame->height * jobnr) / nb_jobs; \
108+ const int slice_end = (frame->height * (jobnr + 1)) / nb_jobs; \
109+ ColorkeyContext *ctx = avctx->priv; \
110+ const int depth = ctx->depth; \
111+ const int max = ctx->max; \
112+ const int half = max / 2; \
113+ const uint8_t *co = ctx->co; \
114+ const uint8_t *colorkey_rgba = ctx->colorkey_rgba; \
115+ const float similarity = ctx->similarity; \
116+ const float blend = ctx->blend; \
117+ const double scale = ctx->scale; \
118+ \
119+ for (int y = slice_start; y < slice_end; ++y) { \
120+ type *dst = (type *)(frame->data[0] + y * frame->linesize[0]); \
121+ \
122+ for (int x = 0; x < frame->width; ++x) { \
123+ int o, t, r, g, b; \
124+ \
125+ o = x * 4; \
126+ r = dst[o + co[0]]; \
127+ g = dst[o + co[1]]; \
128+ b = dst[o + co[2]]; \
129+ \
130+ t = do_colorkey_pixel(colorkey_rgba, r, g, b, \
131+ similarity, blend, max, scale); \
132+ \
133+ if (t > 0) { \
134+ htype a = (r + g + b) / 3; \
135+ htype rt = max - t; \
136+ \
137+ dst[o + co[0]] = (a * t + r * rt + half) >> depth; \
138+ dst[o + co[1]] = (a * t + g * rt + half) >> depth; \
139+ dst[o + co[2]] = (a * t + b * rt + half) >> depth; \
140+ } \
141+ } \
142+ } \
143+ \
144+ return 0; \
119145 }
120146
121−static av_cold int init_filter(AVFilterContext *avctx)
122−{
123− ColorkeyContext *ctx = avctx->priv;
124−
125− if (!strcmp(avctx->filter->name, "colorkey")) {
126− ctx->do_slice = do_colorkey_slice;
127− } else {
128− ctx->do_slice = do_colorhold_slice;
129− }
130−
131− return 0;
132−}
147+COLORHOLD_SLICE(8, uint8_t, int)
148+COLORHOLD_SLICE(16, uint16_t, int64_t)
133149
134150 static int filter_frame(AVFilterLink *link, AVFrame *frame)
135151 {
@@ -148,15 +164,21 @@ static av_cold int config_output(AVFilterLink *outlink) · 12 unmodified lines
148164 {
149165 AVFilterContext *avctx = outlink->src;
150166 ColorkeyContext *ctx = avctx->priv;
151− const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format);
152− int i;
167+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->inputs[0]->format);
153168
169+ ctx->depth = desc->comp[0].depth;
170+ ctx->max = (1 << ctx->depth) - 1;
171+ ctx->scale = 255.0 / ctx->max;
154172 outlink->w = avctx->inputs[0]->w;
155173 outlink->h = avctx->inputs[0]->h;
156174 outlink->time_base = avctx->inputs[0]->time_base;
175+ ff_fill_rgba_map(ctx->co, outlink->format);
157176
158− for (i = 0; i < 4; ++i)
159− ctx->co[i] = desc->comp[i].offset;
177+ if (!strcmp(avctx->filter->name, "colorkey")) {
178+ ctx->do_slice = ctx->max == 255 ? do_colorkey_slice8 : do_colorkey_slice16;
179+ } else {
180+ ctx->do_slice = ctx->max == 255 ? do_colorhold_slice8 : do_colorhold_slice16;
181+ }
160182
161183 return 0;
162184 }
@@ -166,6 +188,8 @@ static const enum AVPixelFormat pixel_fmts[] = { · 3 unmodified lines
166188 AV_PIX_FMT_RGBA,
167189 AV_PIX_FMT_ABGR,
168190 AV_PIX_FMT_BGRA,
191+ AV_PIX_FMT_RGBA64,
192+ AV_PIX_FMT_BGRA64,
169193 AV_PIX_FMT_NONE
170194 };
171195
@@ -205,7 +229,6 @@ const AVFilter ff_vf_colorkey = { · 33 unmodified lines
205229 .description = NULL_IF_CONFIG_SMALL("Turns a certain color into transparency. Operates on RGB colors."),
206230 .priv_size = sizeof(ColorkeyContext),
207231 .priv_class = &colorkey_class,
208− .init = init_filter,
209232 FILTER_INPUTS(colorkey_inputs),
210233 FILTER_OUTPUTS(colorkey_outputs),
211234 FILTER_PIXFMTS_ARRAY(pixel_fmts),
@@ -230,7 +253,6 @@ const AVFilter ff_vf_colorhold = { · 18 unmodified lines
230253 .description = NULL_IF_CONFIG_SMALL("Turns a certain color range into gray. Operates on RGB colors."),
231254 .priv_size = sizeof(ColorkeyContext),
232255 .priv_class = &colorhold_class,
233− .init = init_filter,
234256 FILTER_INPUTS(colorkey_inputs),
235257 FILTER_OUTPUTS(colorkey_outputs),
236258 FILTER_PIXFMTS_ARRAY(pixel_fmts),

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t