/** * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * 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 General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * @author Nicola Lagomarsini, GeoSolutions S.A.S., Copyright 2014 * */ package org.geowebcache.io; import it.geosolutions.imageio.plugins.png.PNGWriter; import java.awt.image.RenderedImage; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import org.geotools.image.ImageWorker; import org.geowebcache.mime.ImageMime; import org.geowebcache.mime.MimeType; import ar.com.hjg.pngj.FilterType; /** * Subclass of the {@link ImageEncoderImpl} class optimized for the PNG format. It uses a new PNGEncoder which provides better performances. */ public class PNGImageEncoder extends ImageEncoderImpl { /** Filter type associated string*/ private static final String FILTER_TYPE = "filterType"; /** Logger used*/ private static final Logger LOGGER = Logger.getLogger(PNGImageEncoder.class); /** Supported mime types*/ private static List<String> supportedMimeTypes; /** Boolean used for disabling the png encoding*/ private boolean disablePNG; /** Boolean indicating if the aggressive output stream is supported*/ private final boolean isAggressiveSupported; /** Default quality value*/ private final static float DEFAULT_QUALITY = 1; /** Quality value*/ private final float quality; static { supportedMimeTypes = new ArrayList<String>(); supportedMimeTypes.add(ImageMime.png.getMimeType()); supportedMimeTypes.add(ImageMime.png8.getMimeType()); supportedMimeTypes.add(ImageMime.png24.getMimeType()); supportedMimeTypes.add(ImageMime.png_24.getMimeType()); } public PNGImageEncoder(boolean aggressiveOutputStreamOptimization, Float quality, List<String> writerSpi, Map<String, String> inputParams, boolean disablePNG, ImageIOInitializer initializer) { super(aggressiveOutputStreamOptimization, supportedMimeTypes, writerSpi, inputParams, initializer); if (quality != null) { this.quality = quality; } else { this.quality = DEFAULT_QUALITY; } this.disablePNG = disablePNG; // Setting of the Aggressive OutputStream only if the first ImageWriterSpi object is an instance of the Default PNGImageWriterSpi this.isAggressiveSupported = (!this.disablePNG); } public boolean isAggressiveOutputStreamSupported() { // If Default PNG Writer must not be used, then Aggressive OutputStream is not supported. return super.isAggressiveOutputStreamSupported() && isAggressiveSupported; } public void encode(RenderedImage image, Object destination, boolean aggressiveOutputStreamOptimization, MimeType type, Map<String, ?> map) throws Exception { if (!isAggressiveOutputStreamSupported() && aggressiveOutputStreamOptimization) { throw new UnsupportedOperationException(OPERATION_NOT_SUPPORTED); } // If the new PNGWriter must be disabled then the other writers are used if (disablePNG) { super.encode(image, destination, aggressiveOutputStreamOptimization, type, map); } else { // Creation of the associated Writer PNGWriter writer = new PNGWriter(); OutputStream stream = null; try { // writer = new PNGJWriter(); // Check if the input object is an OutputStream if (destination instanceof OutputStream) { boolean isScanlinePresent = writer.isScanlineSupported(image); if (!isScanlinePresent) { image = new ImageWorker(image).rescaleToBytes().forceComponentColorModel() .getRenderedImage(); } Object filterObj = null; if (map != null) { filterObj = map.get(FILTER_TYPE); } FilterType filter = null; if (filterObj == null || !(filterObj instanceof FilterType)) { filter = FilterType.FILTER_NONE; } else { filter = (FilterType) filterObj; } stream = (OutputStream) destination; //Image preparation if an image helper is present WriteHelper helper = getHelper(); RenderedImage finalImage = image; if(helper!=null){ finalImage = helper.prepareImage(image, type); } // Image writing writer.writePNG(finalImage, stream, quality, filter); } else { throw new IllegalArgumentException( "Only an OutputStream can be provided to the PNGEncoder"); } } catch (Exception e) { LOGGER.error(e.getMessage(), e); throw e; } finally { // Writer disposal if (writer != null) { writer = null; } // Stream closure if (stream != null) { try { stream.close(); } catch (IOException e) { LOGGER.error(e.getMessage(), e); } stream = null; } } } } /** * Boolean indicating if the new PNG encoder is disabled */ public boolean isDisablePNG() { return disablePNG; } }