public int filterRow(byte[] currRow,
                         byte[] prevRow,
                         byte[][] scratchRows,
                         int bytesPerRow,
                         int bytesPerPixel) {

        int [] badness = {0, 0, 0, 0, 0};
        int curr, left, up, upleft, diff;
        int pa, pb, pc;
        for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) {
            curr   = currRow[i] & 0xff;
            left   = currRow[i - bytesPerPixel] & 0xff;
            up     = prevRow[i] & 0xff;
            upleft = prevRow[i - bytesPerPixel] & 0xff;

            // no filter
            badness[0] += curr;

            // sub filter
            diff = curr - left;
            scratchRows[1][i]  = (byte)diff;
            badness    [1]    +=   (diff>0)?diff:-diff;

            // up filter
            diff = curr - up;
            scratchRows[2][i]  = (byte)diff;
            badness    [2]    +=   (diff>=0)?diff:-diff;

            // average filter
            diff = curr - ((left+up)>>1);
            scratchRows[3][i]  = (byte)diff;
            badness    [3]    +=   (diff>=0)?diff:-diff;

            // paeth filter

            // Original code much simplier but doesn't take full
            // advantage of relationship between pa/b/c and
            // information gleaned in abs operations.
            /// pa = up  -upleft;
            /// pb = left-upleft;
            /// pc = pa+pb;
            /// pa = abs(pa);
            /// pb = abs(pb);
            /// pc = abs(pc);
            /// if ((pa <= pb) && (pa <= pc))
            ///   diff = curr-left;
            /// else if (pb <= pc)
            ///   diff = curr-up;
            /// else
            ///   diff = curr-upleft;

            pa = up  -upleft;
            pb = left-upleft;
            if (pa<0) {
              if (pb<0) {
                // both pa & pb neg so pc is always greater than or
                // equal to pa or pb;
                if (pa >= pb) // since pa & pb neg check sense is reversed.
                  diff = curr-left;
                else
                  diff = curr-up;
              } else {
                // pa neg pb pos so we must compute pc...
                pc = pa+pb;
                pa=-pa;
                if (pa <= pb)     // pc is positive and less than pb
                  if (pa <= pc)
                    diff = curr-left;
                  else
                    diff = curr-upleft;
                else
                  // pc is negative and less than or equal to pa,
                  // but since pa is greater than pb this isn't an issue...
                  if (pb <= -pc)
                    diff = curr-up;
                  else
                    diff = curr-upleft;
              }
            } else {
              if (pb<0) {
                pb =-pb; // make it positive...
                if (pa <= pb) {
                  // pc would be negative and less than or equal to pb
                  pc = pb-pa;
                  if (pa <= pc)
                    diff = curr-left;
                  else if (pb == pc)
                    // if pa is zero then pc==pb otherwise
                    // pc must be less than pb.
                    diff = curr-up;
                  else
                    diff = curr-upleft;
                } else {
                  // pc would be positive and less than pa.
                  pc = pa-pb;
                  if (pb <= pc)
                    diff = curr-up;
                  else
                    diff = curr-upleft;
                }
              } else {
                // both pos so pa+pb is always greater than pa/pb
                if (pa <= pb)
                  diff = curr-left;
                else
                  diff = curr-up;
              }
            }
            scratchRows[4][i]  = (byte)diff;
            badness    [4]    +=   (diff>=0)?diff:-diff;
        }
        int filterType = 0;
        int minBadness = badness[0];

        for (int i = 1; i < 5; i++) {
            if (badness[i] < minBadness) {
                minBadness = badness[i];
                filterType = i;
            }
        }

        if (filterType == 0) {
            System.arraycopy(currRow, bytesPerPixel,
                             scratchRows[0], bytesPerPixel,
                             bytesPerRow);
        }

        return filterType;
    }
Performs filtering on a row of an image.  This method may be
overridden in order to provide a custom algorithm for choosing
the filter type for a given row.

<p> The method is supplied with the current and previous rows
of the image.  For the first row of the image, or of an
interlacing pass, the previous row array will be filled with
zeros as required by the PNG specification.

<p> The method is also supplied with five scratch arrays.
These arrays may be used within the method for any purpose.
At method exit, the array at the index given by the return
value of the method should contain the filtered data.  The
return value will also be used as the filter type.

<p> The default implementation of the method performs a trial
encoding with each of the filter types, and computes the sum of
absolute values of the differences between the raw bytes of the
current row and the predicted values.  The index of the filter
producing the smallest result is returned.

<p> As an example, to perform only 'sub' filtering, this method
could be implemented (non-optimally) as follows:

<pre>
for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) {
    int curr = currRow[i] & 0xff;
    int left = currRow[i - bytesPerPixel] & 0xff;
    scratchRow[PNG_FILTER_SUB][i] = (byte)(curr - left);
}
return PNG_FILTER_SUB;
</pre>

@param currRow The current row as an array of <code>byte</code>s
       of length at least <code>bytesPerRow + bytesPerPixel</code>.
       The pixel data starts at index <code>bytesPerPixel</code>;
       the initial <code>bytesPerPixel</code> bytes are zero.
@param prevRow The current row as an array of <code>byte</code>s
       The pixel data starts at index <code>bytesPerPixel</code>;
       the initial <code>bytesPerPixel</code> bytes are zero.
@param scratchRows An array of 5 <code>byte</code> arrays of
       length at least <code>bytesPerRow +
       bytesPerPixel</code>, useable to hold temporary results.
       The filtered row will be returned as one of the entries
       of this array.  The returned filtered data should start
       at index <code>bytesPerPixel</code>; The initial
       <code>bytesPerPixel</code> bytes are not used.
@param bytesPerRow The number of bytes in the image row.
       This value will always be greater than 0.
@param bytesPerPixel The number of bytes representing a single
       pixel, rounded up to an integer.  This is the 'bpp' parameter
       described in the PNG specification.

@return The filter type to be used.  The entry of
        <code>scratchRows[]</code> at this index holds the
        filtered data.
plugins/svg-plugin/batik-codec-fix/src/main/java/org/apache/batik/ext/awt/image/codec/png/PNGEncodeParam.java