KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > pdfbox > filter > FlateFilter


1 /**
2  * Copyright (c) 2003-2005, www.pdfbox.org
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  * 3. Neither the name of pdfbox; nor the names of its
14  * contributors may be used to endorse or promote products derived from this
15  * software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * http://www.pdfbox.org
29  *
30  */

31 package org.pdfbox.filter;
32
33 import java.io.ByteArrayInputStream JavaDoc;
34 import java.io.ByteArrayOutputStream JavaDoc;
35 import java.io.IOException JavaDoc;
36 import java.io.InputStream JavaDoc;
37 import java.io.OutputStream JavaDoc;
38 import java.util.zip.DeflaterOutputStream JavaDoc;
39 import java.util.zip.InflaterInputStream JavaDoc;
40
41 import org.pdfbox.cos.COSDictionary;
42
43 /**
44  * This is the used for the FlateDecode filter.
45  *
46  * @author <a HREF="mailto:ben@benlitchfield.com">Ben Litchfield</a>
47  * @author Marcel Kammer
48  * @version $Revision: 1.10 $
49  */

50 public class FlateFilter implements Filter
51 {
52     private static final int BUFFER_SIZE = 2048;
53
54     /**
55      * This will decode some compressed data.
56      *
57      * @param compressedData
58      * The compressed byte stream.
59      * @param result
60      * The place to write the uncompressed byte stream.
61      * @param options
62      * The options to use to encode the data.
63      *
64      * @throws IOException
65      * If there is an error decompressing the stream.
66      */

67
68     public void decode(InputStream JavaDoc compressedData, OutputStream JavaDoc result, COSDictionary options) throws IOException JavaDoc
69     {
70         COSDictionary dict = (COSDictionary) options.getDictionaryObject("DecodeParms");
71         int predictor = -1;
72         int colors = -1;
73         int bitsPerPixel = -1;
74         int columns = -1;
75         InflaterInputStream JavaDoc decompressor = null;
76         ByteArrayInputStream JavaDoc bais = null;
77         ByteArrayOutputStream JavaDoc baos = null;
78         if (dict!=null)
79         {
80             predictor = dict.getInt("Predictor");
81             colors = dict.getInt("Colors");
82             bitsPerPixel = options.getInt("BitsPerComponent");
83             columns = dict.getInt("Columns");
84         }
85
86         try
87         {
88             // Decompress data to temporary ByteArrayOutputStream
89
decompressor = new InflaterInputStream JavaDoc(compressedData);
90             byte[] buffer = new byte[BUFFER_SIZE];
91             int amountRead;
92
93             // Decode data using given predictor
94
if (predictor==-1 || predictor == 1 && predictor == 10)
95             {
96                 // decoding not needed
97
while ((amountRead = decompressor.read(buffer, 0, BUFFER_SIZE)) != -1)
98                 {
99                     result.write(buffer, 0, amountRead);
100                 }
101             }
102             else
103             {
104                 if (colors==-1 || bitsPerPixel==-1 || columns==-1)
105                 {
106                     throw new IOException JavaDoc("Could not read all parameters to decode image");
107                 }
108                 
109                 baos = new ByteArrayOutputStream JavaDoc();
110                 while ((amountRead = decompressor.read(buffer, 0, BUFFER_SIZE)) != -1)
111                 {
112                     baos.write(buffer, 0, amountRead);
113                 }
114                 baos.flush();
115
116                 // Copy data to ByteArrayInputStream for reading
117
bais = new ByteArrayInputStream JavaDoc(baos.toByteArray());
118                 baos.close();
119                 baos = null;
120
121                 byte[] decodedData = decodePredictor(predictor, colors, bitsPerPixel, columns, bais);
122                 bais.close();
123                 bais = new ByteArrayInputStream JavaDoc(decodedData);
124
125                 // write decoded data to result
126
while ((amountRead = bais.read(buffer)) != -1)
127                 {
128                     result.write(buffer, 0, amountRead);
129                 }
130                 bais.close();
131                 bais = null;
132             }
133             
134             
135             result.flush();
136         }
137         finally
138         {
139             if (decompressor != null)
140             {
141                 decompressor.close();
142             }
143             if (bais != null)
144             {
145                 bais.close();
146             }
147             if (baos != null)
148             {
149                 baos.close();
150             }
151         }
152     }
153
154     private byte[] decodePredictor(int predictor, int colors, int bitsPerComponent, int columns, InputStream JavaDoc data)
155         throws IOException JavaDoc
156     {
157         ByteArrayOutputStream JavaDoc baos = new ByteArrayOutputStream JavaDoc();
158         byte[] buffer = new byte[2048];
159
160         if (predictor == 1 || predictor == 10)
161         {
162             // No prediction or PNG NONE
163
int i = 0;
164             while ((i = data.read(buffer)) != -1)
165             {
166                 baos.write(buffer, 0, i);
167             }
168         }
169         else
170         {
171             // calculate sizes
172
int bpp = (colors * bitsPerComponent + 7) / 8;
173             int rowlength = (columns * colors * bitsPerComponent + 7) / 8 + bpp;
174             byte[] actline = new byte[rowlength];
175             byte[] lastline = new byte[rowlength];// Initialize lastline with
176
// Zeros according to
177
// PNG-specification
178
boolean done = false;
179             int linepredictor = predictor;
180
181             while (!done)
182             {
183                 if (predictor == 15)
184                 {
185                     linepredictor = data.read();// read per line predictor
186
if (linepredictor == -1)
187                     {
188                         done = true;// reached EOF
189
break;
190                     }
191                     else
192                     {
193                         linepredictor += 10; // add 10 to tread value 1 as 11
194
}
195                     // (instead of PRED NONE) and 2
196
// as 12 (instead of PRED TIFF)
197
}
198
199                 // read line
200
int i = 0;
201                 int offset = bpp;
202                 while (offset < rowlength && ((i = data.read(actline, offset, rowlength - offset)) != -1))
203                 {
204                     offset += i;
205                 }
206
207                 // Do prediction as specified in PNG-Specification 1.2
208
switch (linepredictor)
209                 {
210                     case 2:// PRED TIFF SUB
211
/**
212                          * @todo decode tiff
213                          */

214                         throw new IOException JavaDoc("TIFF-Predictor not supported");
215                     case 11:// PRED SUB
216
for (int p = bpp; p < rowlength; p++)
217                         {
218                             int sub = actline[p] & 0xff;
219                             int left = actline[p - bpp] & 0xff;
220                             actline[p] = (byte) (sub + left);
221                         }
222                         break;
223                     case 12:// PRED UP
224
for (int p = bpp; p < rowlength; p++)
225                         {
226                             int up = actline[p] & 0xff;
227                             int prior = lastline[p] & 0xff;
228                             actline[p] = (byte) (up + prior);
229                         }
230                         break;
231                     case 13:// PRED AVG
232
for (int p = bpp; p < rowlength; p++)
233                         {
234                             int avg = actline[p] & 0xff;
235                             int left = actline[p - bpp] & 0xff;
236                             int up = lastline[p] & 0xff;
237                             actline[p] = (byte) (avg + ((left + up) / 2));
238                         }
239                         break;
240                     case 14:// PRED PAETH
241
for (int p = bpp; p < rowlength; p++)
242                         {
243                             int paeth = actline[p] & 0xff;
244                             int a = actline[p - bpp] & 0xff;// left
245
int b = lastline[p] & 0xff;// upper
246
int c = lastline[p - bpp] & 0xff;// upperleft
247
int value = a + b - c;
248                             int absa = Math.abs(value - a);
249                             int absb = Math.abs(value - b);
250                             int absc = Math.abs(value - c);
251
252                             if (absa <= absb && absa <= absc)
253                             {
254                                 actline[p] = (byte) (paeth + absa);
255                             }
256                             else if (absb <= absc)
257                             {
258                                 actline[p] += (byte) (paeth + absb);
259                             }
260                             else
261                             {
262                                 actline[p] += (byte) (paeth + absc);
263                             }
264                         }
265                         break;
266                     default:
267                         break;
268                 }
269
270                 lastline = actline;
271                 baos.write(actline, bpp, actline.length - bpp);
272             }
273         }
274
275         return baos.toByteArray();
276     }
277
278     /**
279      * This will encode some data.
280      *
281      * @param rawData
282      * The raw data to encode.
283      * @param result
284      * The place to write to encoded results to.
285      * @param options
286      * The options to use to encode the data.
287      *
288      * @throws IOException
289      * If there is an error compressing the stream.
290      */

291     public void encode(InputStream JavaDoc rawData, OutputStream JavaDoc result, COSDictionary options) throws IOException JavaDoc
292     {
293         DeflaterOutputStream JavaDoc out = new DeflaterOutputStream JavaDoc(result);
294         byte[] buffer = new byte[BUFFER_SIZE];
295         int amountRead = 0;
296         while ((amountRead = rawData.read(buffer, 0, BUFFER_SIZE)) != -1)
297         {
298             out.write(buffer, 0, amountRead);
299         }
300         out.close();
301         result.flush();
302     }
303 }
Popular Tags