1:
37:
38: package ;
39:
40:
43: public class PNGFilter
44: {
45:
46: public static final byte FILTER_NONE = 0;
47: public static final byte FILTER_SUB = 1;
48: public static final byte FILTER_UP = 2;
49: public static final byte FILTER_AVERAGE = 3;
50: public static final byte FILTER_PAETH = 4;
51:
52:
56: public static boolean useFilter( PNGHeader header )
57: {
58: switch( header.getColorType() )
59: {
60: case PNGHeader.INDEXED:
61: return false;
62:
63: case PNGHeader.GRAYSCALE:
64: case PNGHeader.RGB:
65: if( header.bytesPerPixel() <= 1 )
66: return false;
67: case PNGHeader.GRAYSCALE_WITH_ALPHA:
68: case PNGHeader.RGB_WITH_ALPHA:
69: default:
70: return true;
71: }
72: }
73:
74:
79: public static byte chooseFilter( byte[] scanline, byte[] lastScanline,
80: int bpp)
81:
82: {
83: long[] values = new long[5];
84: int idx = 0;
85: for( int i = 0; i < 5; i++ )
86: {
87: byte[] filtered = filterScanline((byte)i, scanline, lastScanline, bpp);
88: values[i] = 0;
89: for(int j = 0; j < filtered.length; j++ )
90: values[i] += (int)(filtered[j] & 0xFF);
91: if( values[ idx ] > values[i] )
92: idx = i;
93: }
94: return (byte)idx;
95: }
96:
97:
100: public static byte[] filterScanline( byte filtertype, byte[] scanline,
101: byte[] lastScanline, int bpp)
102: {
103: int stride = scanline.length;
104: byte[] out = new byte[ stride ];
105: switch( filtertype )
106: {
107: case FILTER_SUB:
108: for( int i = 0; i < bpp; i++)
109: out[ i ] = scanline[ i ];
110:
111: for( int i = bpp; i < stride; i++ )
112: out[i] = (byte)(scanline[ i ] -
113: scanline[ i - bpp ]);
114: break;
115:
116: case FILTER_UP:
117: for( int i = 0; i < stride; i++ )
118: out[ i ] = (byte)(scanline[ i ] - lastScanline[ i ]);
119: break;
120:
121: case FILTER_AVERAGE:
122: for( int i = 0; i < bpp; i++)
123: out[ i ] = (byte)((scanline[ i ] & 0xFF) - ((lastScanline[ i ] & 0xFF) >> 1));
124: for( int i = bpp; i < stride; i++ )
125: out[ i ] = (byte)((scanline[ i ] & 0xFF) -
126: (((scanline[ i - bpp ] & 0xFF) +
127: (lastScanline[ i ] & 0xFF)) >> 1));
128: break;
129:
130: case FILTER_PAETH:
131: for( int i = 0; i < stride; i++ )
132: {
133: int x;
134: {
135: int a, b, c;
136: if( i >= bpp )
137: {
138: a = (scanline[ i - bpp ] & 0xFF);
139: c = (lastScanline[ i - bpp ] & 0xFF);
140: }
141: else
142: a = c = 0;
143: b = (lastScanline[ i ] & 0xFF);
144:
145: int p = (a + b - c);
146:
147: int pa = (p > a) ? p - a : a - p;
148: int pb = (p > b) ? p - b : b - p;
149: int pc = (p > c) ? p - c : c - p;
150:
151:
152: if( pa <= pb && pa <= pc ) x = a;
153: else { if( pb <= pc ) x = b;
154: else x = c;
155: }
156: }
157: out[ i ] = (byte)(scanline[ i ] - x);
158: }
159: break;
160: default:
161: case FILTER_NONE:
162: return scanline;
163: }
164: return out;
165: }
166:
167:
170: public static byte[] unFilterScanline( int filtertype, byte[] scanline,
171: byte[] lastScanline, int bpp)
172: {
173: int stride = scanline.length;
174: byte[] out = new byte[ stride ];
175: switch( filtertype )
176: {
177:
178: case FILTER_NONE:
179: System.arraycopy( scanline, 0, out, 0, stride );
180: break;
181:
182: case FILTER_SUB:
183: for( int i = 0; i < bpp; i++)
184: out[ i ] = scanline[ i ];
185:
186: for( int i = bpp; i < stride; i++ )
187: out[ i ] = (byte)(scanline[ i ] +
188: out[ i - bpp ]);
189: break;
190:
191: case FILTER_UP:
192: for( int i = 0; i < stride; i++ )
193: out[ i ] = (byte)(scanline[ i ] + lastScanline[ i ]);
194: break;
195:
196: case FILTER_AVERAGE:
197: for( int i = 0; i < bpp; i++)
198: out[ i ] = (byte)((scanline[ i ] & 0xFF) + ((lastScanline[ i ] & 0xFF) >> 1));
199: for( int i = bpp; i < stride; i++ )
200: out[ i ] = (byte)((scanline[ i ] & 0xFF) +
201: (((out[ i - bpp ] & 0xFF) + (lastScanline[ i ] & 0xFF)) >> 1));
202: break;
203:
204: case FILTER_PAETH:
205: for( int i = 0; i < stride; i++ )
206: {
207: int x;
208: {
209: int a, b, c;
210: if( i >= bpp )
211: {
212: a = (out[ i - bpp ] & 0xFF);
213: c = (lastScanline[ i - bpp ] & 0xFF);
214: }
215: else
216: a = c = 0;
217: b = (lastScanline[ i ] & 0xFF);
218:
219: int p = (a + b - c);
220:
221: int pa = (p > a) ? p - a : a - p;
222: int pb = (p > b) ? p - b : b - p;
223: int pc = (p > c) ? p - c : c - p;
224:
225:
226: if( pa <= pb && pa <= pc ) x = a;
227: else { if( pb <= pc ) x = b;
228: else x = c;
229: }
230: }
231: out[ i ] = (byte)(scanline[ i ] + x);
232: }
233: break;
234: }
235: return out;
236: }
237: }