[FFmpeg-devel] [PATCH] colorlevels filter

Clément Bœsch ubitux at gmail.com
Thu May 23 13:42:11 CEST 2013


On Tue, May 14, 2013 at 05:19:19PM +0000, Paul B Mahol wrote:
[...]
> +static int filter_frame(AVFilterLink *inlink, AVFrame *in)
> +{
> +    AVFilterContext *ctx = inlink->dst;
> +    ColorLevelsContext *s = ctx->priv;
> +    AVFilterLink *outlink = ctx->outputs[0];
> +    const int step = s->step;
> +    AVFrame *out;
> +    int x, y, i;
> +
> +    if (av_frame_is_writable(in)) {
> +        out = in;
> +    } else {
> +        out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
> +        if (!out) {
> +            av_frame_free(&in);
> +            return AVERROR(ENOMEM);
> +        }
> +        av_frame_copy_props(out, in);
> +    }
> +
> +    switch (s->bpp) {
> +    case 1:
> +        for (i = 0; i < s->nb_comp; i++) {
> +            Range *r = &s->range[i];
> +            const uint8_t offset = s->rgba_map[i];
> +            const uint8_t *srcrow = in->data[0];
> +            uint8_t *dstrow = out->data[0];
> +            int imin = round(r->in_min  * UINT8_MAX);
> +            int imax = round(r->in_max  * UINT8_MAX);
> +            int omin = round(r->out_min * UINT8_MAX);
> +            int omax = round(r->out_max * UINT8_MAX);
> +            double coeff;
> +
> +            if (imin < 0) {
> +                imin = UINT8_MAX;
> +                for (y = 0; y < inlink->h; y++) {
> +                    const uint8_t *src = srcrow;
> +
> +                    for (x = 0; x < s->linesize; x += step)
> +                        imin = FFMIN(imin, src[x + offset]);
> +                    srcrow += in->linesize[0];
> +                }
> +            }
> +            if (imax < 0) {
> +                srcrow = in->data[0];
> +                imax = 0;
> +                for (y = 0; y < inlink->h; y++) {
> +                    const uint8_t *src = srcrow;
> +
> +                    for (x = 0; x < s->linesize; x += step)
> +                        imax = FFMAX(imax, src[x + offset]);
> +                    srcrow += in->linesize[0];
> +                }
> +            }
> +
> +            srcrow = in->data[0];
> +            coeff = (omax - omin) / (double)(imax - imin);
> +            for (y = 0; y < inlink->h; y++) {
> +                const uint8_t *src = srcrow;
> +                uint8_t *dst = dstrow;
> +
> +                for (x = 0; x < s->linesize; x += step)
> +                    dst[x + offset] = av_clip_uint8((src[x + offset] - imin) * coeff + omin);
> +                dstrow += out->linesize[0];
> +                srcrow += in->linesize[0];
> +            }
> +        }
> +        break;
> +    case 2:
> +        for (i = 0; i < s->nb_comp; i++) {
> +            Range *r = &s->range[i];
> +            const uint8_t offset = s->rgba_map[i];
> +            const uint8_t *srcrow = in->data[0];
> +            uint8_t *dstrow = out->data[0];
> +            int imin = round(r->in_min  * UINT16_MAX);
> +            int imax = round(r->in_max  * UINT16_MAX);
> +            int omin = round(r->out_min * UINT16_MAX);
> +            int omax = round(r->out_max * UINT16_MAX);
> +            double coeff;
> +
> +            if (imin < 0) {
> +                imin = UINT16_MAX;
> +                for (y = 0; y < inlink->h; y++) {
> +                    const uint16_t *src = (const uint16_t *)srcrow;
> +
> +                    for (x = 0; x < s->linesize; x += step)
> +                        imin = FFMIN(imin, src[x + offset]);
> +                    srcrow += in->linesize[0];
> +                }
> +            }
> +            if (imax < 0) {
> +                srcrow = in->data[0];
> +                imax = 0;
> +                for (y = 0; y < inlink->h; y++) {
> +                    const uint16_t *src = (const uint16_t *)srcrow;
> +
> +                    for (x = 0; x < s->linesize; x += step)
> +                        imax = FFMAX(imax, src[x + offset]);
> +                    srcrow += in->linesize[0];
> +                }
> +            }
> +
> +            srcrow = in->data[0];
> +            coeff = (omax - omin) / (double)(imax - imin);
> +            for (y = 0; y < inlink->h; y++) {
> +                const uint16_t *src = (const uint16_t*)srcrow;
> +                uint16_t *dst = (uint16_t *)dstrow;
> +
> +                for (x = 0; x < s->linesize; x += step)
> +                    dst[x + offset] = av_clip_uint16((src[x + offset] - imin) * coeff + omin);
> +                dstrow += out->linesize[0];
> +                srcrow += in->linesize[0];
> +            }
> +        }
> +    }

Don't you need to do something with the alpha channel if in != out?

[...]

Rest should be OK, but I'm curious about the documentation.

-- 
Clément B.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 490 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20130523/483ed323/attachment.asc>


More information about the ffmpeg-devel mailing list