[FFmpeg-devel] [PATCH] avfilter/vf_colorkey: Add colorkey video filter

Michael Niedermayer michaelni at gmx.at
Sun Apr 19 20:46:17 CEST 2015


On Sun, Apr 19, 2015 at 06:15:48PM +0200, Timo Rothenpieler wrote:
> ---
>  Changelog                 |   1 +
>  MAINTAINERS               |   1 +
>  doc/filters.texi          |  39 ++++++++
>  libavfilter/Makefile      |   1 +
>  libavfilter/allfilters.c  |   1 +
>  libavfilter/vf_colorkey.c | 226 ++++++++++++++++++++++++++++++++++++++++++++++
>  6 files changed, 269 insertions(+)
>  create mode 100644 libavfilter/vf_colorkey.c
> 
> diff --git a/Changelog b/Changelog
> index 2e30b24..e99d1e9 100644
> --- a/Changelog
> +++ b/Changelog
> @@ -17,6 +17,7 @@ version <next>:
>  - WebM Live Chunk Muxer
>  - nvenc level and tier options
>  - chorus filter
> +- colorkey video filter
>  
>  
>  version 2.6:
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 598c0b3..18f6ba3 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -352,6 +352,7 @@ Filters:
>    avf_showcqt.c                         Muhammad Faiz
>    vf_blend.c                            Paul B Mahol
>    vf_colorbalance.c                     Paul B Mahol
> +  vf_colorkey.c                         Timo Rothenpieler
>    vf_dejudder.c                         Nicholas Robbins
>    vf_delogo.c                           Jean Delvare (CC <khali at linux-fr.org>)
>    vf_drawbox.c/drawgrid                 Andrey Utkin
> diff --git a/doc/filters.texi b/doc/filters.texi
> index 0f2e720..79c0753 100644
> --- a/doc/filters.texi
> +++ b/doc/filters.texi
> @@ -3026,6 +3026,45 @@ colorbalance=rs=.3
>  @end example
>  @end itemize
>  
> + at section colorkey
> +RGB colorspace color keying.
> +
> +The filter accepts the following options:
> +
> + at table @option
> + at item color
> +The color which will be replaced with transparency.
> +
> + at item similarity
> +Similarity percentage with the key color.
> +
> +0.01 matches only the exact key color, while 1.0 matches everything.
> +
> + at item blend
> +Blend percentage.
> +
> +0.0 makes pixels either fully transparent, or not transparent at all.
> +
> +Higher values result in semi-transparent pixels, with a higher transparency
> +the more similar the pixels color is to the key color.
> + at end table
> +
> + at subsection Examples
> +
> + at itemize
> + at item
> +Make every green pixel in the input image transparent:
> + at example
> +ffmpeg -i input.png -vf colorkey=green out.png
> + at end example
> +
> + at item
> +Make every red pixel in the input image transparent, with a high similarity tolerance:
> + at example
> +ffmpeg -i input.png -vf colorkey=0xFF0000:0.3 out.png
> + at end example
> + at end itemize
> +
>  @section colorlevels
>  
>  Adjust video input frames using levels.
> diff --git a/libavfilter/Makefile b/libavfilter/Makefile
> index 48cee50..60e6b52 100644
> --- a/libavfilter/Makefile
> +++ b/libavfilter/Makefile
> @@ -102,6 +102,7 @@ OBJS-$(CONFIG_BOXBLUR_FILTER)                += vf_boxblur.o
>  OBJS-$(CONFIG_CODECVIEW_FILTER)              += vf_codecview.o
>  OBJS-$(CONFIG_COLORBALANCE_FILTER)           += vf_colorbalance.o
>  OBJS-$(CONFIG_COLORCHANNELMIXER_FILTER)      += vf_colorchannelmixer.o
> +OBJS-$(CONFIG_COLORKEY_FILTER)               += vf_colorkey.o
>  OBJS-$(CONFIG_COLORLEVELS_FILTER)            += vf_colorlevels.o
>  OBJS-$(CONFIG_COLORMATRIX_FILTER)            += vf_colormatrix.o
>  OBJS-$(CONFIG_COPY_FILTER)                   += vf_copy.o
> diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
> index 7961dca..2eeec7f 100644
> --- a/libavfilter/allfilters.c
> +++ b/libavfilter/allfilters.c
> @@ -118,6 +118,7 @@ void avfilter_register_all(void)
>      REGISTER_FILTER(CODECVIEW,      codecview,      vf);
>      REGISTER_FILTER(COLORBALANCE,   colorbalance,   vf);
>      REGISTER_FILTER(COLORCHANNELMIXER, colorchannelmixer, vf);
> +    REGISTER_FILTER(COLORKEY,       colorkey,       vf);
>      REGISTER_FILTER(COLORLEVELS,    colorlevels,    vf);
>      REGISTER_FILTER(COLORMATRIX,    colormatrix,    vf);
>      REGISTER_FILTER(COPY,           copy,           vf);
> diff --git a/libavfilter/vf_colorkey.c b/libavfilter/vf_colorkey.c
> new file mode 100644
> index 0000000..b5180cf
> --- /dev/null
> +++ b/libavfilter/vf_colorkey.c
> @@ -0,0 +1,226 @@
> +/*
> + * Copyright (c) 2015 Timo Rothenpieler <timo at rothenpieler.org>
> + *
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * FFmpeg is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +#include "libavutil/opt.h"
> +#include "avfilter.h"
> +#include "formats.h"
> +#include "internal.h"
> +#include "video.h"
> +
> +typedef struct ColorkeyContext {
> +    const AVClass *class;
> +
> +    uint8_t colorkey_rgba[4];
> +    float cf[3];
> +
> +    float similarity;
> +    float blend;
> +} ColorkeyContext;
> +
> +static inline int convert_format(int fmt)
> +{
> +    switch(fmt) {
> +    case AV_PIX_FMT_0RGB:
> +        return AV_PIX_FMT_ARGB;
> +    case AV_PIX_FMT_0BGR:
> +        return AV_PIX_FMT_ABGR;
> +    case AV_PIX_FMT_BGR0:
> +        return AV_PIX_FMT_BGRA;
> +    case AV_PIX_FMT_RGB0:
> +        return AV_PIX_FMT_RGBA;
> +    default:
> +        return fmt;
> +    }
> +}
> +
> +static inline int offset_r(int fmt)
> +{
> +    switch(fmt) {
> +    case AV_PIX_FMT_ARGB:
> +        return 1;
> +    case AV_PIX_FMT_ABGR:
> +        return 3;
> +    case AV_PIX_FMT_BGRA:
> +        return 2;
> +    case AV_PIX_FMT_RGBA:
> +    default:
> +        return 0;
> +    }
> +}
> +
> +static inline int offset_g(int fmt)
> +{
> +    switch(fmt) {
> +    case AV_PIX_FMT_ARGB:
> +        return 2;
> +    case AV_PIX_FMT_ABGR:
> +        return 2;
> +    case AV_PIX_FMT_BGRA:
> +        return 1;
> +    case AV_PIX_FMT_RGBA:
> +    default:
> +        return 1;
> +    }
> +}
> +
> +static inline int offset_b(int fmt)
> +{
> +    switch(fmt) {
> +    case AV_PIX_FMT_ARGB:
> +        return 3;
> +    case AV_PIX_FMT_ABGR:
> +        return 1;
> +    case AV_PIX_FMT_BGRA:
> +        return 0;
> +    case AV_PIX_FMT_RGBA:
> +    default:
> +        return 2;
> +    }
> +}
> +
> +static inline int offset_a(int fmt)
> +{
> +    switch(fmt) {
> +    case AV_PIX_FMT_ARGB:
> +        return 0;
> +    case AV_PIX_FMT_ABGR:
> +        return 0;
> +    case AV_PIX_FMT_BGRA:
> +        return 3;
> +    case AV_PIX_FMT_RGBA:
> +    default:
> +        return 3;
> +    }
> +}
> +
> +#define SATURATE(val) (FFMAX(FFMIN((val), 1.0), 0.0))
> +
> +static uint8_t do_colorkey_pixel(ColorkeyContext *ctx, uint8_t r, uint8_t g, uint8_t b)
> +{
> +    float diff_r = r / 255.0 - ctx->cf[0];
> +    float diff_g = g / 255.0 - ctx->cf[1];
> +    float diff_b = b / 255.0 - ctx->cf[2];
> +
> +    float diff = sqrt(diff_r * diff_r + diff_g * diff_g + diff_b * diff_b);
> +
> +    return SATURATE(FFMAX(diff - ctx->similarity, 0.0) / ctx->blend) * 255.0;
> +}
> +
> +static void do_colorkey(ColorkeyContext *ctx, AVFrame *frame)
> +{
> +    int o_r, o_g, o_b, o_a;
> +    int o, x, y;
> +
> +    frame->format = convert_format(frame->format);
> +
> +    o_r = offset_r(frame->format);
> +    o_g = offset_g(frame->format);
> +    o_b = offset_b(frame->format);
> +    o_a = offset_a(frame->format);
> +
> +    for (x = 0; x < 3; ++x)
> +        ctx->cf[x] = ctx->colorkey_rgba[x] / 255.0;
> +
> +    for (y = 0; y < frame->height; ++y) {
> +        for (x = 0; x < frame->width; ++x) {
> +            o = frame->linesize[0] * y + x * 4;
> +
> +            frame->data[0][o + o_a] =
> +                do_colorkey_pixel(ctx,
> +                                  frame->data[0][o + o_r],
> +                                  frame->data[0][o + o_g],
> +                                  frame->data[0][o + o_b]);
> +        }
> +    }
> +}
> +

> +static AVFrame *get_video_buffer(AVFilterLink *link, int w, int h)
> +{
> +    AVFrame *picref = ff_default_get_video_buffer(link, w, h);
> +    do_colorkey(link->dst->priv, picref);
> +    return picref;
> +}

this looks wrong, you should not need this


> +
> +static int filter_frame(AVFilterLink *link, AVFrame *inpicref)
> +{
> +    do_colorkey(link->dst->priv, inpicref);
> +    return ff_filter_frame(link->dst->outputs[0], inpicref);
> +}

the input may or may not be writable


[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

What does censorship reveal? It reveals fear. -- Julian Assange
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20150419/83662891/attachment.asc>


More information about the ffmpeg-devel mailing list