src/main/java/com/mxgraph/util/png/mxPngEncodeParam.java
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.  */
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.

 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.

 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.

 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.

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


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;


@param currRow The current row as an array of bytes
of length at least bytesPerRow + bytesPerPixel.
The pixel data starts at index bytesPerPixel;
the initial bytesPerPixel bytes are zero.
@param prevRow The current row as an array of bytes
The pixel data starts at index bytesPerPixel;
the initial bytesPerPixel bytes are zero.
@param scratchRows An array of 5 byte arrays of
length at least bytesPerRow +
bytesPerPixel, 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 bytesPerPixel; The initial
bytesPerPixel 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
scratchRows[] at this index holds the
filtered data.
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 . 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 . 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 . 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 . As an example to perform only ' sub ' filtering this method could be implemented ( non - optimally ) as follows . 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 ; @param currRow The current row as an array of bytes of length at least bytesPerRow + bytesPerPixel . The pixel data starts at index bytesPerPixel ; the initial bytesPerPixel bytes are zero . @param prevRow The current row as an array of bytes The pixel data starts at index bytesPerPixel ; the initial bytesPerPixel bytes are zero . @param scratchRows An array of 5 byte arrays of length at least bytesPerRow + bytesPerPixel 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 bytesPerPixel ; The initial bytesPerPixel 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 scratchRows [] at this index holds the filtered data .
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;
			badness[0] += curr;
			diff = curr - left;
			scratchRows[1][i] = (byte) diff;
			badness[1] += (diff > 0) ? diff : -diff;
			diff = curr - up;
			scratchRows[2][i] = (byte) diff;
			badness[2] += (diff >= 0) ? diff : -diff;
			diff = curr - ((left + up) >> 1);
			scratchRows[3][i] = (byte) diff;
			badness[3] += (diff >= 0) ? diff : -diff;
			pa = up - upleft;
			pb = left - upleft;
			if (pa < 0)
			{
				if (pb < 0)
				{
					if (pa >= pb) 
						diff = curr - left;
					else
						diff = curr - up;
				}
				else
				{
					pc = pa + pb;
					pa = -pa;
					if (pa <= pb) 
						if (pa <= pc)
							diff = curr - left;
						else
							diff = curr - upleft;
					else
					if (pb <= -pc)
						diff = curr - up;
					else
						diff = curr - upleft;
				}
			}
			else
			{
				if (pb < 0)
				{
					pb = -pb; 
					if (pa <= pb)
					{
						pc = pb - pa;
						if (pa <= pc)
							diff = curr - left;
						else if (pb == pc)
							diff = curr - up;
						else
							diff = curr - upleft;
					}
					else
					{
						pc = pa - pb;
						if (pb <= pc)
							diff = curr - up;
						else
							diff = curr - upleft;
					}
				}
				else
				{
					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;
	}
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 ; badness [ 0 ] += curr ; diff = curr - left ; scratchRows [ 1 ] [ i ] = ( byte ) diff ; badness [ 1 ] += ( diff > 0 ) ? diff : - diff ; diff = curr - up ; scratchRows [ 2 ] [ i ] = ( byte ) diff ; badness [ 2 ] += ( diff >= 0 ) ? diff : - diff ; diff = curr - ( ( left + up ) >> 1 ) ; scratchRows [ 3 ] [ i ] = ( byte ) diff ; badness [ 3 ] += ( diff >= 0 ) ? diff : - diff ; pa = up - upleft ; pb = left - upleft ; if ( pa < 0 ) { if ( pb < 0 ) { if ( pa >= pb ) diff = curr - left ; else diff = curr - up ; } else { pc = pa + pb ; pa = - pa ; if ( pa <= pb ) if ( pa <= pc ) diff = curr - left ; else diff = curr - upleft ; else if ( pb <= - pc ) diff = curr - up ; else diff = curr - upleft ; } } else { if ( pb < 0 ) { pb = - pb ; if ( pa <= pb ) { pc = pb - pa ; if ( pa <= pc ) diff = curr - left ; else if ( pb == pc ) diff = curr - up ; else diff = curr - upleft ; } else { pc = pa - pb ; if ( pb <= pc ) diff = curr - up ; else diff = curr - upleft ; } } else { 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.
Performs filtering on a row of an image .
// no filter // sub filter // up filter // average filter // 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; // both pa & pb neg so pc is always greater than or // equal to pa or pb; // since pa & pb neg check sense is reversed. // pa neg pb pos so we must compute pc... // pc is positive and less than pb // pc is negative and less than or equal to pa, // but since pa is greater than pb this isn't an issue... // make it positive... // pc would be negative and less than or equal to pb // if pa is zero then pc==pb otherwise // pc must be less than pb. // pc would be positive and less than pa. // both pos so pa+pb is always greater than pa/pb