/*
* Copyright (c) 2013 Allogy Interactive.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.sun.pdfview;
import java.io.IOException;
import java.nio.ByteBuffer;
/**
* A PDF Decoder encapsulates all the methods of decoding a stream of bytes
* based on all the various encoding methods.
* <p>
* You should use the decodeStream() method of this object rather than using
* any of the decoders directly.
*/
public class PDFDecoder {
/** Creates a new instance of PDFDecoder */
private PDFDecoder() {
}
/**
* decode a byte[] stream using the filters specified in the object's
* dictionary (passed as argument 1).
* @param dict the dictionary associated with the stream
* @param streamBuf the data in the stream, as a byte buffer
*/
public static ByteBuffer decodeStream(PDFObject dict, ByteBuffer streamBuf)
throws IOException {
PDFObject filter = dict.getDictRef("Filter");
if (filter == null) {
// just apply default decryption
return dict.getDecrypter().decryptBuffer(null, dict, streamBuf);
} else {
// apply filters
PDFObject ary[];
PDFObject params[];
if (filter.getType() == PDFObject.NAME) {
ary = new PDFObject[1];
ary[0] = filter;
params = new PDFObject[1];
params[0] = dict.getDictRef("DecodeParms");
} else {
ary = filter.getArray();
PDFObject parmsobj = dict.getDictRef("DecodeParms");
if (parmsobj != null) {
params = parmsobj.getArray();
} else {
params = new PDFObject[ary.length];
}
}
// determine whether default encryption applies or if there's a
// specific Crypt filter; it must be the first filter according to
// the errata for PDF1.7
boolean specificCryptFilter =
ary.length != 0 && ary[0].getStringValue().equals("Crypt");
if (!specificCryptFilter) {
// No Crypt filter, so should apply default decryption (if
// present!)
streamBuf = dict.getDecrypter().decryptBuffer(
null, dict, streamBuf);
}
for (int i = 0; i < ary.length; i++) {
String enctype = ary[i].getStringValue();
if (enctype == null) {
} else if (enctype.equals("FlateDecode") || enctype.equals("Fl")) {
streamBuf = FlateDecode.decode(dict, streamBuf, params[i]);
} else if (enctype.equals("LZWDecode") || enctype.equals("LZW")) {
streamBuf = LZWDecode.decode(streamBuf, params[i]);
} else if (enctype.equals("ASCII85Decode") || enctype.equals("A85")) {
streamBuf = ASCII85Decode.decode(streamBuf, params[i]);
} else if (enctype.equals("ASCIIHexDecode") || enctype.equals("AHx")) {
streamBuf = ASCIIHexDecode.decode(streamBuf, params[i]);
} else if (enctype.equals("RunLengthDecode") || enctype.equals("RL")) {
streamBuf = RunLengthDecode.decode(streamBuf, params[i]);
// } else if (enctype.equals("DCTDecode") || enctype.equals("DCT")) {
// streamBuf = DCTDecode.decode(dict, streamBuf, params[i]);
} else if (enctype.equals("CCITTFaxDecode") || enctype.equals("CCF")) {
streamBuf = CCITTFaxDecode.decode(dict, streamBuf, params[i]);
} else if (enctype.equals("Crypt")) {
String cfName = PDFDecrypterFactory.CF_IDENTITY;
if (params[i] != null) {
final PDFObject nameObj = params[i].getDictRef("Name");
if (nameObj != null && nameObj.getType() == PDFObject.NAME) {
cfName = nameObj.getStringValue();
}
}
streamBuf = dict.getDecrypter().decryptBuffer(cfName, null, streamBuf);
} else {
throw new PDFParseException("Unknown coding method:" + ary[i].getStringValue());
}
}
}
return streamBuf;
}
}