001: /*
002: * $Id: FlateDecode.java,v 1.3 2007/12/20 18:33:33 rbair Exp $
003: *
004: * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
005: * Santa Clara, California 95054, U.S.A. All rights reserved.
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this library; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
020: */
021:
022: package com.sun.pdfview.decode;
023:
024: import java.io.ByteArrayOutputStream;
025: import java.io.IOException;
026: import java.nio.ByteBuffer;
027: import java.util.zip.DataFormatException;
028: import java.util.zip.Inflater;
029:
030: import com.sun.pdfview.PDFObject;
031: import com.sun.pdfview.PDFParseException;
032:
033: /**
034: * decode a deFlated byte array
035: * @author Mike Wessler
036: */
037: public class FlateDecode {
038:
039: /**
040: * decode a byte buffer in Flate format.
041: * <p>
042: * Flate is a built-in Java algorithm. It's part of the java.util.zip
043: * package.
044: *
045: * @param buf the deflated input buffer
046: * @param params parameters to the decoder (unused)
047: * @return the decoded (inflated) bytes
048: */
049: public static ByteBuffer decode(PDFObject dict, ByteBuffer buf,
050: PDFObject params) throws IOException {
051: Inflater inf = new Inflater(false);
052:
053: int bufSize = buf.remaining();
054:
055: // copy the data, since the array() method is not supported
056: // on raf-based ByteBuffers
057: byte[] data = new byte[bufSize];
058: buf.get(data);
059:
060: // set the input to the inflater
061: inf.setInput(data);
062:
063: // output to a byte-array output stream, since we don't
064: // know how big the output will be
065: ByteArrayOutputStream baos = new ByteArrayOutputStream();
066: byte[] decomp = new byte[bufSize];
067: int loc = 0;
068: int read = 0;
069:
070: try {
071: while (!inf.finished()) {
072: read = inf.inflate(decomp);
073: if (read <= 0) {
074: // System.out.println("Read = " + read + "! Params: " + params);
075: if (inf.needsDictionary()) {
076: throw new PDFParseException(
077: "Don't know how to ask for a dictionary in FlateDecode");
078: } else {
079: // System.out.println("Inflate data length=" + buf.remaining());
080: return ByteBuffer.allocate(0);
081: // throw new PDFParseException("Inflater wants more data... but it's already here!");
082: }
083: }
084: baos.write(decomp, 0, read);
085: }
086: } catch (DataFormatException dfe) {
087: throw new PDFParseException("Data format exception:"
088: + dfe.getMessage());
089: }
090:
091: // return the output as a byte buffer
092: ByteBuffer outBytes = ByteBuffer.wrap(baos.toByteArray());
093:
094: // undo a predictor algorithm, if any was used
095: if (params != null
096: && params.getDictionary().containsKey("Predictor")) {
097: Predictor predictor = Predictor.getPredictor(params);
098: if (predictor != null) {
099: outBytes = predictor.unpredict(outBytes);
100: }
101: }
102:
103: return outBytes;
104: }
105:
106: }
|