Package org.geoserver.map.turbojpeg

Source Code of org.geoserver.map.turbojpeg.TurboJpegImageWorker

/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.map.turbojpeg;

import it.geosolutions.imageio.plugins.turbojpeg.TurboJpegImageWriteParam;
import it.geosolutions.imageio.plugins.turbojpeg.TurboJpegImageWriter;
import it.geosolutions.imageio.plugins.turbojpeg.TurboJpegImageWriterSpi;
import it.geosolutions.imageio.plugins.turbojpeg.TurboJpegUtilities;
import it.geosolutions.imageio.utilities.ImageOutputStreamAdapter2;

import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.imageio.IIOImage;
import javax.imageio.ImageWriteParam;
import javax.imageio.spi.ImageOutputStreamSpi;
import javax.imageio.stream.ImageOutputStream;
import javax.media.jai.ImageLayout;
import javax.media.jai.JAI;
import javax.media.jai.operator.FormatDescriptor;

import org.geotools.image.ImageWorker;
import org.geotools.resources.image.ImageUtilities;
import org.geotools.util.logging.Logging;

/**
* Specific subclass of {@link ImageWorker} for writing JPEG images using libjpeg-turbo.
*
* @author Simone Giannecchini, GeoSolutions SAS
*
*/
final class TurboJpegImageWorker extends ImageWorker {

    static final String ERROR_LIB_MESSAGE = "The TurboJpeg native library hasn't been loaded: Skipping";

    static final String ERROR_FILE_MESSAGE = "The specified input file can't be read: Skipping";

    /** Is the libjpeg-turbo available? **/
    private static final TurboJpegImageWriterSpi TURBO_JPEG_SPI = new TurboJpegImageWriterSpi();

    /**
     * The logger to use for this class.
     */
    private final static Logger LOGGER = Logging.getLogger(TurboJpegImageWorker.class);

    public TurboJpegImageWorker() {
        super();
    }

    public TurboJpegImageWorker(File input) throws IOException {
        super(input);
    }

    public TurboJpegImageWorker(RenderedImage image) {
        super(image);
    }

    /**
     * Writes outs the image contained into this {@link ImageWorker} as a JPEG using the provided destination , compression and compression rate.
     * <p>
     * The destination object can be anything providing that we have an {@link ImageOutputStreamSpi} that recognizes it.
     *
     * @param destination where to write the internal {@link #image} as a JPEG.
     * @param compressionRate percentage of compression.
     * @return this {@link ImageWorker}.
     * @throws IOException In case an error occurs during the search for an {@link ImageOutputStream} or during the eoncding process.
     */
    public final void writeTurboJPEG(final OutputStream destination, final float compressionRate)
            throws IOException {

        if (!TurboJpegUtilities.isTurboJpegAvailable()) {
            throw new IllegalStateException(ERROR_LIB_MESSAGE);
        }

        // Reformatting this image for jpeg.
        if (LOGGER.isLoggable(Level.FINE))
            LOGGER.fine("Encoding input image to write out as JPEG using .");

        // go to component color model if needed
        ColorModel cm = image.getColorModel();
        final boolean hasAlpha = cm.hasAlpha();
        forceComponentColorModel();
        cm = image.getColorModel();

        // rescale to 8 bit
        rescaleToBytes();
        cm = image.getColorModel();

        // remove transparent band
        final int numBands = image.getSampleModel().getNumBands();
        if (hasAlpha) {
            final int requestedBands = numBands - 1;
            if (ImageUtilities.isMediaLibAvailable()) {
                retainBands(requestedBands);
            } else if (getNumBands() > requestedBands) {
                removeAlpha(requestedBands);
            }
        }

        // Getting a writer.
        if (LOGGER.isLoggable(Level.FINE))
            LOGGER.fine("Creating a TURBO JPEG writer and configuring it.");

        final TurboJpegImageWriter writer = (TurboJpegImageWriter) TURBO_JPEG_SPI.createWriterInstance();
        // Compression is available on both lib
        TurboJpegImageWriteParam iwp = (TurboJpegImageWriteParam) writer.getDefaultWriteParam();
        final ImageOutputStreamAdapter2 outStream = new ImageOutputStreamAdapter2(destination);
        iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        iwp.setCompressionType("JPEG");
        iwp.setCompressionQuality(compressionRate); // We can control quality here.

        if (LOGGER.isLoggable(Level.FINE))
            LOGGER.fine("Writing image out...");

        try {
            writer.setOutput(outStream);
            writer.write(null, new IIOImage(image, null, null), iwp);
        } finally {
            try {
                writer.dispose();
            } catch (Throwable e) {
                if (LOGGER.isLoggable(Level.FINE))
                    LOGGER.log(Level.FINE, e.getLocalizedMessage(), e);
            }
            try {
                outStream.close();
            } catch (Throwable e) {
                if (LOGGER.isLoggable(Level.FINE))
                    LOGGER.log(Level.FINE, e.getLocalizedMessage(), e);
            }
        }
    }

    /**
     * Remove the alpha band
     *
     * @param requestedBands
     */
    private void removeAlpha(int requestedBands) {
        // Retrieving/Setting the ImageLayout
        final RenderingHints hints = getRenderingHints();
        ImageLayout layout = null;
        if (hints.containsKey(JAI.KEY_IMAGE_LAYOUT)) {
            layout = (ImageLayout) hints.get(JAI.KEY_IMAGE_LAYOUT);
        } else {
            layout = new ImageLayout();
            hints.put(JAI.KEY_IMAGE_LAYOUT, layout);
        }
       
        // Forcing the colormodel with noAlpha
        final ColorModel colorModel = new ComponentColorModel(
                ColorSpace.getInstance(requestedBands == 3 ? ColorSpace.CS_sRGB : ColorSpace.CS_GRAY),
                false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
        SampleModel sm = colorModel.createCompatibleSampleModel(image.getWidth(), image.getHeight());
        layout.setSampleModel(sm);
       
        // Forcing the output format to remove the alpha Band
        image = FormatDescriptor.create(image, DataBuffer.TYPE_BYTE, hints);
    }

}
TOP

Related Classes of org.geoserver.map.turbojpeg.TurboJpegImageWorker

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.