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

com.github.davidmoten.grumpy.wms.LayerManager Maven / Gradle / Ivy

package com.github.davidmoten.grumpy.wms;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

class LayerManager {

    private static Logger log = LoggerFactory.getLogger(LayerManager.class);

    private final Layers layers;

    private final ExecutorService executor;

    private static final boolean DRAW_IN_PARALLEL = true;

    LayerManager(Layers layers) {
        this.layers = layers;
        GraphicsEnvironment gEnv = GraphicsEnvironment.getLocalGraphicsEnvironment();
        for (String name : gEnv.getAvailableFontFamilyNames())
            log.debug(name);
        log.info("constructed");
        executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1);
    }

    BufferedImage getImage(WmsRequest request) {
        MyGraphics graphics = createGraphics(request);
        Graphics2D g = graphics.graphics;

        log.info("painting image with layers");
        // paint the image
        paintImage(request, g);
        // release resources
        g.dispose();
        log.info("image finished");
        return graphics.image;
    }

    Map getInfos(Date time, WmsRequest request, Point point, String mimeType) {
        Map map = new HashMap();
        for (String layerName : request.getLayers()) {
            Layer layer = layers.getLayer(layerName);
            if (layer != null) {
                String info = layer.getInfo(time, request, point, mimeType);
                if (info != null)
                    map.put(layerName, info);
            } else
                log.warn("no getInfo implementation for layer: " + layerName);
        }
        return map;
    }

    private static final ImageObserver noActionImageObserver = new ImageObserver() {
        @Override
        public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) {
            return false;
        }
    };

    private static class MyGraphics {
        public MyGraphics(BufferedImage image, Graphics2D graphics) {
            super();
            this.image = image;
            this.graphics = graphics;
        }

        BufferedImage image;
        Graphics2D graphics;
    }

    private void prepareGraphics(Graphics2D g) {
        RendererUtil.useAntialiasing(g);
    }

    private MyGraphics createGraphics(WmsRequest request) {
        log.info("creating buffered image");
        BufferedImage image = new BufferedImage(request.getWidth(), request.getHeight(),
                BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = (Graphics2D) image.getGraphics();

        // set rendering options
        prepareGraphics(g);

        // paint the background with transparency as required
        paintBackground(request, g);

        log.info("image ready");
        return new MyGraphics(image, g);
    }

    private void paintImage(final WmsRequest request, Graphics2D g) {

        log.info("painting layers " + request.getLayers());

        if (DRAW_IN_PARALLEL) {
            paintImageParallel(request, g);
        } else {
            // using only a single g2d seems to help with IE8 png transparency
            // bug (fixed in IE9).
            for (final String layerName : request.getLayers()) {
                paintLayer(g, layerName, layers, request);
            }
        }
    }

    private void paintImageParallel(WmsRequest request, Graphics2D g) {
        // create future for each worker (layer)
        List> futures = new ArrayList>();

        for (final String layerName : request.getLayers()) {
            // create a worker for layer
            Callable worker = createWorker(layers, layerName, request);
            // start the worker
            Future submit = executor.submit(worker);
            // record the worker in a list so we can paint the images in
            // order later
            futures.add(submit);
        }
        // wait for each image to complete in turn then draw it to the
        // everything graphics object
        for (Future future : futures) {
            drawImage(g, future);
        }
    }

    private Callable createWorker(final Layers layers, final String layerName,
            final WmsRequest request) {
        return new Callable() {
            @Override
            public BufferedImage call() throws Exception {
                final MyGraphics graphics = createGraphics(request);
                try {
                    paintLayer(graphics.graphics, layerName, layers, request);
                } catch (Throwable t) {
                    log.error(t.getMessage(), t);
                    Graphics2D g = graphics.graphics;
                    g.setColor(Color.black);
                    g.setFont(g.getFont().deriveFont(14f));
                    g.drawString(t.getClass().getName() + ":" + t.getMessage(), graphics.image.getWidth()/2-50, graphics.image.getHeight() /2 + 10);
                }
                return graphics.image;
            }
        };
    }

    private static void paintLayer(Graphics2D g, String layerName, Layers layers, WmsRequest request) {
        log.info("painting " + layerName);
        final Layer layer = layers.getLayer(layerName);
        if (layer != null) {
            layer.render(g, request);
            log.info("finished painting " + layerName);
        } else
            log.warn("no paintImage implementation for layer: " + layerName);
    }

    private void drawImage(Graphics2D g, Future future) {
        try {
            BufferedImage image = future.get();
            g.drawImage(image, 0, 0, noActionImageObserver);
        } catch (InterruptedException e) {
            log.warn(e.getMessage(), e);
        } catch (ExecutionException e) {
            log.error(e.getMessage(), e);
        }
    }

    private void paintBackground(WmsRequest request, Graphics2D g) {
        g.setColor(request.getBackgroundColor());
        g.setBackground(request.getBackgroundColor());
        if (request.isTransparent())
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));
        else
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.0f));
        g.fillRect(0, 0, 100, 100);
        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy