Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* $Id: 1f3788ba34eebeb8850e8bd702493948446b21d6 $
*
* This file is part of the iText (R) project.
* Copyright (c) 1998-2015 iText Group NV
* Authors: Kevin Day, Bruno Lowagie, Paulo Soares, et al.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License version 3
* as published by the Free Software Foundation with the addition of the
* following permission added to Section 15 as permitted in Section 7(a):
* FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
* ITEXT GROUP. ITEXT GROUP DISCLAIMS THE WARRANTY OF NON INFRINGEMENT
* OF THIRD PARTY RIGHTS
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public License
* along with this program; if not, see http://www.gnu.org/licenses or write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA, 02110-1301 USA, or download the license from the following URL:
* http://itextpdf.com/terms-of-use/
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License.
*
* In accordance with Section 7(b) of the GNU Affero General Public License,
* a covered work must retain the producer line in every PDF that is created
* or manipulated using iText.
*
* You can be released from the requirements of the license by purchasing
* a commercial license. Buying such a license is mandatory as soon as you
* develop commercial activities involving the iText software without
* disclosing the source code of your own applications.
* These activities include: offering paid services to customers as an ASP,
* serving PDFs on the fly in a web application, shipping iText with a closed
* source product.
*
* For more information, please contact iText Software Corp. at this
* address: [email protected]
*/
package com.itextpdf.text.pdf;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import com.itextpdf.text.error_messages.MessageLocalization;
import com.itextpdf.text.exceptions.UnsupportedPdfException;
import com.itextpdf.text.pdf.codec.TIFFConstants;
import com.itextpdf.text.pdf.codec.TIFFFaxDecoder;
import com.itextpdf.text.pdf.codec.TIFFFaxDecompressor;
/**
* Encapsulates filter behavior for PDF streams. Classes generally interace with this
* using the static getDefaultFilterHandlers() method, then obtain the desired {@link FilterHandler}
* via a lookup.
* @since 5.0.4
*/
// Dev note: we eventually want to refactor PdfReader so all of the existing filter functionality is moved into this class
// it may also be better to split the sub-classes out into a separate package
public final class FilterHandlers {
/**
* The main interface for creating a new {@link FilterHandler}
*/
public static interface FilterHandler{
public byte[] decode(byte[] b, PdfName filterName, PdfObject decodeParams, final PdfDictionary streamDictionary) throws IOException;
}
/** The default {@link FilterHandler}s used by iText */
private static final Map defaults;
static {
HashMap map = new HashMap();
map.put(PdfName.FLATEDECODE, new Filter_FLATEDECODE());
map.put(PdfName.FL, new Filter_FLATEDECODE());
map.put(PdfName.ASCIIHEXDECODE, new Filter_ASCIIHEXDECODE());
map.put(PdfName.AHX, new Filter_ASCIIHEXDECODE());
map.put(PdfName.ASCII85DECODE, new Filter_ASCII85DECODE());
map.put(PdfName.A85, new Filter_ASCII85DECODE());
map.put(PdfName.LZWDECODE, new Filter_LZWDECODE());
map.put(PdfName.CCITTFAXDECODE, new Filter_CCITTFAXDECODE());
map.put(PdfName.CRYPT, new Filter_DoNothing());
map.put(PdfName.RUNLENGTHDECODE, new Filter_RUNLENGTHDECODE());
defaults = Collections.unmodifiableMap(map);
}
/**
* @return the default {@link FilterHandler}s used by iText
*/
public static Map getDefaultFilterHandlers(){
return defaults;
}
/**
* Handles FLATEDECODE filter
*/
private static class Filter_FLATEDECODE implements FilterHandler{
public byte[] decode(byte[] b, PdfName filterName, PdfObject decodeParams, PdfDictionary streamDictionary) throws IOException {
b = PdfReader.FlateDecode(b);
b = PdfReader.decodePredictor(b, decodeParams);
return b;
}
}
/**
* Handles ASCIIHEXDECODE filter
*/
private static class Filter_ASCIIHEXDECODE implements FilterHandler{
public byte[] decode(byte[] b, PdfName filterName, PdfObject decodeParams, PdfDictionary streamDictionary) throws IOException {
b = PdfReader.ASCIIHexDecode(b);
return b;
}
}
/**
* Handles ASCIIHEXDECODE filter
*/
private static class Filter_ASCII85DECODE implements FilterHandler{
public byte[] decode(byte[] b, PdfName filterName, PdfObject decodeParams, PdfDictionary streamDictionary) throws IOException {
b = PdfReader.ASCII85Decode(b);
return b;
}
}
/**
* Handles LZWDECODE filter
*/
private static class Filter_LZWDECODE implements FilterHandler{
public byte[] decode(byte[] b, PdfName filterName, PdfObject decodeParams, PdfDictionary streamDictionary) throws IOException {
b = PdfReader.LZWDecode(b);
b = PdfReader.decodePredictor(b, decodeParams);
return b;
}
}
/**
* Handles CCITTFAXDECODE filter
*/
private static class Filter_CCITTFAXDECODE implements FilterHandler{
public byte[] decode(byte[] b, PdfName filterName, PdfObject decodeParams, PdfDictionary streamDictionary) throws IOException {
PdfNumber wn = (PdfNumber)PdfReader.getPdfObjectRelease(streamDictionary.get(PdfName.WIDTH));
PdfNumber hn = (PdfNumber)PdfReader.getPdfObjectRelease(streamDictionary.get(PdfName.HEIGHT));
if (wn == null || hn == null)
throw new UnsupportedPdfException(MessageLocalization.getComposedMessage("filter.ccittfaxdecode.is.only.supported.for.images"));
int width = wn.intValue();
int height = hn.intValue();
PdfDictionary param = decodeParams instanceof PdfDictionary ? (PdfDictionary)decodeParams : null;
int k = 0;
boolean blackIs1 = false;
boolean byteAlign = false;
if (param != null) {
PdfNumber kn = param.getAsNumber(PdfName.K);
if (kn != null)
k = kn.intValue();
PdfBoolean bo = param.getAsBoolean(PdfName.BLACKIS1);
if (bo != null)
blackIs1 = bo.booleanValue();
bo = param.getAsBoolean(PdfName.ENCODEDBYTEALIGN);
if (bo != null)
byteAlign = bo.booleanValue();
}
byte[] outBuf = new byte[(width + 7) / 8 * height];
TIFFFaxDecompressor decoder = new TIFFFaxDecompressor();
if (k == 0 || k > 0) {
int tiffT4Options = k > 0 ? TIFFConstants.GROUP3OPT_2DENCODING : 0;
tiffT4Options |= byteAlign ? TIFFConstants.GROUP3OPT_FILLBITS : 0;
decoder.SetOptions(1, TIFFConstants.COMPRESSION_CCITTFAX3, tiffT4Options, 0);
decoder.decodeRaw(outBuf, b, width, height);
if (decoder.fails > 0) {
byte[] outBuf2 = new byte[(width + 7) / 8 * height];
int oldFails = decoder.fails;
decoder.SetOptions(1, TIFFConstants.COMPRESSION_CCITTRLE, tiffT4Options, 0);
decoder.decodeRaw(outBuf2, b, width, height);
if (decoder.fails < oldFails) {
outBuf = outBuf2;
}
}
}
else {
TIFFFaxDecoder deca = new TIFFFaxDecoder(1, width, height);
deca.decodeT6(outBuf, b, 0, height, 0);
}
if (!blackIs1) {
int len = outBuf.length;
for (int t = 0; t < len; ++t) {
outBuf[t] ^= 0xff;
}
}
b = outBuf;
return b;
}
}
/**
* A filter that doesn't modify the stream at all
*/
private static class Filter_DoNothing implements FilterHandler{
public byte[] decode(byte[] b, PdfName filterName, PdfObject decodeParams, PdfDictionary streamDictionary) throws IOException {
return b;
}
}
/**
* Handles RUNLENGTHDECODE filter
*/
private static class Filter_RUNLENGTHDECODE implements FilterHandler{
public byte[] decode(byte[] b, PdfName filterName, PdfObject decodeParams, PdfDictionary streamDictionary) throws IOException {
// allocate the output buffer
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte dupCount = -1;
for(int i = 0; i < b.length; i++){
dupCount = b[i];
if (dupCount == -128) break; // this is implicit end of data
if (dupCount >= 0 && dupCount <= 127){
int bytesToCopy = dupCount+1;
baos.write(b, i, bytesToCopy);
i+=bytesToCopy;
} else {
// make dupcount copies of the next byte
i++;
for(int j = 0; j < 1-(int)(dupCount);j++){
baos.write(b[i]);
}
}
}
return baos.toByteArray();
}
}
}