Package org.geoserver.wms.map.png

Source Code of org.geoserver.wms.map.png.PNGJWriter$RasterSymbolizerVisitor

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

import it.geosolutions.imageio.plugins.png.PNGWriter;

import java.awt.image.RenderedImage;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.geoserver.platform.ServiceException;
import org.geoserver.wms.WMSMapContent;
import org.geotools.image.ImageWorker;
import org.geotools.map.Layer;
import org.geotools.styling.AbstractStyleVisitor;
import org.geotools.styling.ColorMap;
import org.geotools.styling.Style;
import org.geotools.util.logging.Logging;

import ar.com.hjg.pngj.FilterType;

/**
* Encodes the image in PNG using the PNGJ library
*
* @author Andrea Aime - GeoSolutions
*/
public class PNGJWriter {

    private static final Logger LOGGER = Logging.getLogger(PNGJWriter.class);

    public RenderedImage writePNG(RenderedImage image, OutputStream outStream, float quality,
            WMSMapContent mapContent) {
        // what kind of scaline filtering are we going to use?
        FilterType filterType = getFilterType(mapContent);
        // Creation of a new PNGWriter object
        PNGWriter writer = new PNGWriter();
        // Check if a Scanline is supported by the writer
        boolean isScanlineSupported = writer.isScanlineSupported(image);
        // If it is not supported, then the image is rescaled to bytes
        if(!isScanlineSupported){
            image = new ImageWorker(image).rescaleToBytes().forceComponentColorModel().getRenderedImage();          
        }
       
        RenderedImage output = null;
        // Image writing
        try {
            output =  writer.writePNG(image, outStream, quality, filterType);
        } catch (Exception e) {
            LOGGER.log(Level.SEVERE, "Failed to encode the PNG", e);
            throw new ServiceException(e);
        }
       
        return output;
    }

    /**
     * SUB filtering is useful for raster images with "high" variation, otherwise we go for NONE,
     * empirically it provides better compression at lower effort
     *
     * @param mapContent
     * @return
     */
    private FilterType getFilterType(WMSMapContent mapContent) {
        RasterSymbolizerVisitor visitor = new RasterSymbolizerVisitor();
        for (Layer layer : mapContent.layers()) {
            // check if the style has a raster symbolizer, don't trust the layer type as
            // we don't know in advance if there is a rendering transformation
            // WMS cascading is a ugly case, we might be cascading a map that is vector, but
            // we don't get to know
            Style style = layer.getStyle();
            if (style != null) {
                style.accept(visitor);
                if (visitor.highChangeRasterSymbolizer) {
                    return FilterType.FILTER_SUB;
                }
            }
        }

        return FilterType.FILTER_NONE;
    }

    /**
     * Check if the style contains a "high change" raster symbolizer, that is, one that generates a
     * continuous set of values for which SUB filtering provides better results
     *
     * @author Andrea Aime - GeoSolutions
     */
    class RasterSymbolizerVisitor extends AbstractStyleVisitor {

        boolean highChangeRasterSymbolizer;

        public void visit(org.geotools.styling.RasterSymbolizer raster) {
            if (raster.getColorMap() == null) {
                highChangeRasterSymbolizer = true;
                return;
            }

            int cmType = raster.getColorMap().getType();
            if (cmType != ColorMap.TYPE_INTERVALS && cmType != ColorMap.TYPE_VALUES) {
                highChangeRasterSymbolizer = true;
            }
        }
    }

}
TOP

Related Classes of org.geoserver.wms.map.png.PNGJWriter$RasterSymbolizerVisitor

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.