static void png_filter_row(PNGDSPContext *dsp, uint8_t *dst, int filter_type,

                           uint8_t *src, uint8_t *last, int size, int bpp)

{

    int i, p, r, g, b, a;



    switch (filter_type) {

    case PNG_FILTER_VALUE_NONE:

        memcpy(dst, src, size);

        break;

    case PNG_FILTER_VALUE_SUB:

        for (i = 0; i < bpp; i++)

            dst[i] = src[i];

        if (bpp == 4) {

            p = *(int *)dst;

            for (; i < size; i += bpp) {

                unsigned s = *(int *)(src + i);

                p = ((s & 0x7f7f7f7f) + (p & 0x7f7f7f7f)) ^ ((s ^ p) & 0x80808080);

                *(int *)(dst + i) = p;

            }

        } else {

#define OP_SUB(x, s, l) ((x) + (s))

            UNROLL_FILTER(OP_SUB);

        }

        break;

    case PNG_FILTER_VALUE_UP:

        dsp->add_bytes_l2(dst, src, last, size);

        break;

    case PNG_FILTER_VALUE_AVG:

        for (i = 0; i < bpp; i++) {

            p      = (last[i] >> 1);

            dst[i] = p + src[i];

        }

#define OP_AVG(x, s, l) (((((x) + (l)) >> 1) + (s)) & 0xff)

        UNROLL_FILTER(OP_AVG);

        break;

    case PNG_FILTER_VALUE_PAETH:

        for (i = 0; i < bpp; i++) {

            p      = last[i];

            dst[i] = p + src[i];

        }

        if (bpp > 2 && size > 4) {

            



            int w = bpp == 4 ? size : size - 3;

            dsp->add_paeth_prediction(dst + i, src + i, last + i, w - i, bpp);

            i = w;

        }

        ff_add_png_paeth_prediction(dst + i, src + i, last + i, size - i, bpp);

        break;

    }

}
