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) {

                int 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) {

            // would write off the end of the array if we let it process the last pixel with bpp=3

            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;

    }

}
