All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jpedal.io.filter.Flate Maven / Gradle / Ivy

/*
 * ===========================================
 * Java Pdf Extraction Decoding Access Library
 * ===========================================
 *
 * Project Info:  http://www.idrsolutions.com
 * Help section for developers at http://www.idrsolutions.com/support/
 *
 * (C) Copyright 1997-2017 IDRsolutions and Contributors.
 *
 * This file is part of JPedal/JPDF2HTML5
 *
 @LICENSE@
 *
 * ---------------
 * Flate.java
 * ---------------
 */
package org.jpedal.io.filter;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.InputStream;
import java.util.Map;
import java.util.zip.Inflater;

import org.jpedal.objects.raw.PdfDictionary;
import org.jpedal.objects.raw.PdfObject;
import org.jpedal.utils.LogWriter;
import org.jpedal.utils.repositories.FastByteArrayOutputStream;

/**
 * flate
 */
public class Flate extends BaseFilter implements PdfFilter {

    //default values
    private int predictor = 1, colors = 1, bitsPerComponent = 8, columns = 1;

    private boolean hasError;

    public Flate(final PdfObject decodeParms) {

        super(decodeParms);

        if (decodeParms != null) {

            final int newBitsPerComponent = decodeParms.getInt(PdfDictionary.BitsPerComponent);
            if (newBitsPerComponent != -1) {
                bitsPerComponent = newBitsPerComponent;
            }

            final int newColors = decodeParms.getInt(PdfDictionary.Colors);
            if (newColors != -1) {
                colors = newColors;
            }

            final int columnsSet = decodeParms.getInt(PdfDictionary.Columns);
            if (columnsSet != -1) {
                columns = columnsSet;
            }

            predictor = decodeParms.getInt(PdfDictionary.Predictor);
        }

    }

    /**
     * flate decode - use a byte array stream to decompress data in memory
     */
    @Override
    public byte[] decode(byte[] data) throws Exception {

        if (data[0] == 0 && data[1] == 0 && data[2] == 0) { //no flate flags found so return the raw data : case 24436
            return data;
        }

        int bufSize = 512000;
        FastByteArrayOutputStream bos = null;
        boolean failed = true;

        final int orgSize = data.length;

        /*
         * decompress byte[]
         */
        if (data != null) {

            while (failed) { //sometimes partly valid so loop to try this

                // create a inflater and initialize it Inflater inf=new Inflater();
                final Inflater inf = new Inflater();
                inf.setInput(data);

                final int size = data.length;
                bos = new FastByteArrayOutputStream(size);

                if (size < bufSize) {
                    bufSize = size;
                }

                final byte[] buf = new byte[bufSize];
                //int debug = 20;
                int count;
                try {
                    while (!inf.finished()) {

                        count = inf.inflate(buf);
                        bos.write(buf, 0, count);

                        if (inf.getRemaining() == 0) {
                            break;
                        }
                    }

                    failed = false;
                } catch (final Exception ee) {

                    LogWriter.writeLog("Exception in Flate " + ee);

                    failed = true;

                    hasError = true;

                    //retrun on small streams
                    if (data.length == orgSize && data.length > 10000) {
                        failed = false;
                    } else if (data.length > 10) {
                        final byte[] newData = new byte[data.length - 1];
                        System.arraycopy(data, 0, newData, 0, data.length - 1);
                        data = newData;
                    } else {
                        failed = false;
                    }
                }
            }

            data = bos.toByteArray();

            return applyPredictor(predictor, data, colors, bitsPerComponent, columns);

        }

        return data;

    }

    @Override
    public void decode(final BufferedInputStream bis, final BufferedOutputStream streamCache, final String cacheName, final Map cachedObjects) throws Exception {

        this.bis = bis;
        this.streamCache = streamCache;
        this.cachedObjects = cachedObjects;

        /*
         * decompress cached object
         */
        if (bis != null) {

            InputStream inf = null;

            try {

                // create a inflater and initialize it Inflater inf=new
                // Inflater();
                // if((predictor==1) || (predictor==10) )
                inf = new java.util.zip.InflaterInputStream(bis);
                // else
                // inf=new DecodePredictor(null, predictor,params,new
                // java.util.zip.InflaterInputStream(bis));

                while (true) {

                    final int b = inf.read();
                    if ((inf.available() == 0) || (b == -1)) {
                        break;
                    }

                    streamCache.write(b);

                }

                if (predictor != 1 && predictor != 10) {
                    streamCache.flush();
                    streamCache.close();
                    if (cacheName != null) {
                        setupCachedObjectForDecoding(cacheName);
                    }
                }

            } catch (final Exception e) {
                LogWriter.writeLog("Exception " + e + " accessing Flate filter ");
            } finally {
                if (inf != null) {
                    inf.close();
                }
            }
        }

        applyPredictor(predictor, null, colors, bitsPerComponent, columns);
    }

    @Override
    public boolean hasError() {
        return hasError;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy