[FFmpeg-devel] [PATCH] colorlevels filter

Paul B Mahol onemda at gmail.com
Thu May 23 14:07:52 CEST 2013


On 5/23/13, Clement Boesch <ubitux at gmail.com> wrote:
> 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?

Nope, as its also normalized.

>
> [...]
>
> Rest should be OK, but I'm curious about the documentation.
>
> --
> Clement B.
>


More information about the ffmpeg-devel mailing list