1 31 package org.pdfbox.filter; 32 33 import java.io.ByteArrayInputStream ; 34 import java.io.ByteArrayOutputStream ; 35 import java.io.IOException ; 36 import java.io.InputStream ; 37 import java.io.OutputStream ; 38 import java.util.zip.DeflaterOutputStream ; 39 import java.util.zip.InflaterInputStream ; 40 41 import org.pdfbox.cos.COSDictionary; 42 43 50 public class FlateFilter implements Filter 51 { 52 private static final int BUFFER_SIZE = 2048; 53 54 67 68 public void decode(InputStream compressedData, OutputStream result, COSDictionary options) throws IOException 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 decompressor = null; 76 ByteArrayInputStream bais = null; 77 ByteArrayOutputStream 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 decompressor = new InflaterInputStream (compressedData); 90 byte[] buffer = new byte[BUFFER_SIZE]; 91 int amountRead; 92 93 if (predictor==-1 || predictor == 1 && predictor == 10) 95 { 96 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 ("Could not read all parameters to decode image"); 107 } 108 109 baos = new ByteArrayOutputStream (); 110 while ((amountRead = decompressor.read(buffer, 0, BUFFER_SIZE)) != -1) 111 { 112 baos.write(buffer, 0, amountRead); 113 } 114 baos.flush(); 115 116 bais = new ByteArrayInputStream (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 (decodedData); 124 125 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 data) 155 throws IOException 156 { 157 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 158 byte[] buffer = new byte[2048]; 159 160 if (predictor == 1 || predictor == 10) 161 { 162 int i = 0; 164 while ((i = data.read(buffer)) != -1) 165 { 166 baos.write(buffer, 0, i); 167 } 168 } 169 else 170 { 171 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]; boolean done = false; 179 int linepredictor = predictor; 180 181 while (!done) 182 { 183 if (predictor == 15) 184 { 185 linepredictor = data.read(); if (linepredictor == -1) 187 { 188 done = true; break; 190 } 191 else 192 { 193 linepredictor += 10; } 195 } 198 199 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 switch (linepredictor) 209 { 210 case 2: 214 throw new IOException ("TIFF-Predictor not supported"); 215 case 11: 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: 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: 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: for (int p = bpp; p < rowlength; p++) 242 { 243 int paeth = actline[p] & 0xff; 244 int a = actline[p - bpp] & 0xff; int b = lastline[p] & 0xff; int c = lastline[p - bpp] & 0xff; 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 291 public void encode(InputStream rawData, OutputStream result, COSDictionary options) throws IOException 292 { 293 DeflaterOutputStream out = new DeflaterOutputStream (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 |