Package thirdparty.pngtastic

Source Code of thirdparty.pngtastic.PngtasticCompressionHandler

package thirdparty.pngtastic;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterInputStream;

/**
* Implements PNG compression and decompression
*
* @author rayvanderborght
*/
public class PngtasticCompressionHandler implements PngCompressionHandler {

    private static final List<Integer> compressionStrategies = Arrays.asList(
            Deflater.DEFAULT_STRATEGY,
            Deflater.FILTERED,
            Deflater.HUFFMAN_ONLY);

    public PngtasticCompressionHandler() {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public byte[] inflate(ByteArrayOutputStream imageBytes) throws IOException {
        InflaterInputStream inflater = new InflaterInputStream(new ByteArrayInputStream(imageBytes.toByteArray()));
        ByteArrayOutputStream inflatedOut = new ByteArrayOutputStream();

        int readLength;
        byte[] block = new byte[8192];
        while ((readLength = inflater.read(block)) != -1) {
            inflatedOut.write(block, 0, readLength);
        }

        return inflatedOut.toByteArray();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public byte[] deflate(byte[] inflatedImageData, Integer compressionLevel, boolean concurrent) throws IOException {
        List<byte[]> results = (concurrent)
                ? this.deflateImageDataConcurrently(inflatedImageData, compressionLevel)
                : this.deflateImageDataSerially(inflatedImageData, compressionLevel, Deflater.DEFAULT_STRATEGY);

        byte[] result = null;
        for (int i = 0; i < results.size(); i++) {
            byte[] data = results.get(i);
            if (result == null || (data.length < result.length)) {
                result = data;
            }
        }

        return result;
    }

    /*
     * Do the work of deflating (compressing) the image data with the
     * different compression strategies in separate threads to take
     * advantage of multiple core architectures.
     */
    private List<byte[]> deflateImageDataConcurrently(final byte[] inflatedImageData, final Integer compressionLevel) {
        final Collection<byte[]> results = new ConcurrentLinkedQueue<byte[]>();

        final Collection<Callable<Object>> tasks = new ArrayList<Callable<Object>>();
        for (final int strategy : compressionStrategies) {
            tasks.add(Executors.callable(new Runnable() {
                @Override
                public void run() {
                    try {
                        results.add(PngtasticCompressionHandler.this.deflateImageData(inflatedImageData, strategy, compressionLevel));
                    } catch (Throwable e) {
                    }
                }
            }));
        }

        ExecutorService compressionThreadPool = Executors.newFixedThreadPool(compressionStrategies.size());
        try {
            compressionThreadPool.invokeAll(tasks);
        } catch (InterruptedException ex) {
        } finally {
            compressionThreadPool.shutdown();
        }

        return new ArrayList<byte[]>(results);
    }

    private List<byte[]> deflateImageDataSerially(byte[] inflatedImageData, Integer compressionLevel, Integer compressionStrategy) {
        List<byte[]> results = new ArrayList<byte[]>();

        List<Integer> strategies = (compressionStrategy == null) ? compressionStrategies
                : Collections.singletonList(compressionStrategy);

        for (final int strategy : strategies) {
            try {
                results.add(PngtasticCompressionHandler.this.deflateImageData(inflatedImageData, strategy, compressionLevel));
            } catch (Throwable e) {
            }
        }

        return results;
    }

    private byte[] deflateImageData(byte[] inflatedImageData, int strategy, Integer compressionLevel) throws IOException {
        byte[] result = null;

        if (compressionLevel == null || compressionLevel > Deflater.BEST_COMPRESSION || compressionLevel < Deflater.NO_COMPRESSION) {
            for (int compression = Deflater.BEST_COMPRESSION; compression > Deflater.NO_COMPRESSION; compression--) {
                ByteArrayOutputStream deflatedOut = this.deflate(inflatedImageData, strategy, compression);

                if (result == null || (result.length > deflatedOut.size())) {
                    result = deflatedOut.toByteArray();
                }
            }
        } else {
            result = this.deflate(inflatedImageData, strategy, compressionLevel).toByteArray();
        }
        return result;
    }

    private ByteArrayOutputStream deflate(byte[] inflatedImageData, int strategy, int compression) throws IOException {
        ByteArrayOutputStream deflatedOut = new ByteArrayOutputStream();
        Deflater deflater = new Deflater(compression);
        deflater.setStrategy(strategy);

        DeflaterOutputStream stream = new DeflaterOutputStream(deflatedOut, deflater);
        stream.write(inflatedImageData);
        stream.close();

        return deflatedOut;
    }
}
TOP

Related Classes of thirdparty.pngtastic.PngtasticCompressionHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.