
// NOTE: this file implements the PNG filter row functions in JavaScript,
//       and can therefore be a bit slow. Use ffpng_pred.js instead for
//       PNG filter row functions that are optimized for speed (ffpng).

// use with:
// $ ffgac -i <input> -pred <pred> -pred_script png_pred.js -y output.png
// where <pred> can be any one of:
// - none
// - sub
// - up
// - avg
// - paeth
// - mixed

const PNG_FILTER_VALUE_NONE  = 0;
const PNG_FILTER_VALUE_SUB   = 1;
const PNG_FILTER_VALUE_UP    = 2;
const PNG_FILTER_VALUE_AVG   = 3;
const PNG_FILTER_VALUE_PAETH = 4;

function sub_png_paeth_prediction(dst, src, top, size, bpp)
{
    const ilen = size - bpp;
    for ( let i = 0; i < ilen; i++ )
    {
        const a = src[i];
        const b = top[bpp + i];
        const c = top[i];

        let p  = b - c;
        let pc = a - c;

        const pa = Math.abs(p);
        const pb = Math.abs(pc);
        pc = Math.abs(p + pc);

        if ( pa <= pb && pa <= pc )
            p = a;
        else if (pb <= pc)
            p = b;
        else
            p = c;
        dst[bpp + i] = src[bpp + i] - p;
    }
}

function filter_row(args)
{
    let dst = args.dst;
    let pred = args.pred;
    let src = args.src;
    let top = args.top;
    let size = args.size;
    let bpp = args.bpp;

    switch ( pred )
    {
    case PNG_FILTER_VALUE_NONE:
        // ffpng.none(dst, src, top, size, bpp);
        for ( let i = 0; i < size; i++ )
            dst[i] = src[i];
        break;
    case PNG_FILTER_VALUE_SUB:
        // ffpng.sub(dst, src, top, size, bpp);
        for ( let i = 0; i < bpp; i++ )
            dst[i] = src[i];
        for ( let i = bpp; i < size; i++ )
            dst[i] = src[i] - src[i - bpp];
        break;
    case PNG_FILTER_VALUE_UP:
        // ffpng.up(dst, src, top, size, bpp);
        for ( let i = 0; i < size; i++ )
            dst[i] = src[i] - top[i];
        break;
    case PNG_FILTER_VALUE_AVG:
        // ffpng.avg(dst, src, top, size, bpp);
        for ( let i = 0; i < bpp; i++ )
            dst[i] = src[i] - (top[i] >> 1);
        for ( let i = bpp; i < size; i++ )
            dst[i] = src[i] - ((src[i - bpp] + top[i]) >> 1);
        break;
    case PNG_FILTER_VALUE_PAETH:
        // ffpng.paeth(dst, src, top, size, bpp);
        for ( let i = 0; i < bpp; i++ )
            dst[i] = src[i] - top[i];
        sub_png_paeth_prediction(dst, src, top, size, bpp);
        break;
    }
}
