/* * Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU 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 General Public License along * with this program; if not, see http://www.gnu.org/licenses/ */ package org.esa.snap.ui; import com.bc.ceres.binding.PropertyContainer; import com.bc.ceres.glayer.CollectionLayer; import com.bc.ceres.glayer.Layer; import com.bc.ceres.glayer.LayerContext; import com.bc.ceres.glayer.LayerType; import com.bc.ceres.glayer.LayerTypeRegistry; import com.bc.ceres.grender.support.BufferedImageRendering; import org.geotools.referencing.crs.DefaultGeographicCRS; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; /** * This utility class is responsible for loading the world map image. * * @author Marco Peters * @version $Revision$ $Date$ */ public class WorldMapImageLoader { private static BufferedImage worldMapImage; private static boolean highResolution = false; private static final Dimension HI_RES_DIMENSION = new Dimension(4320, 2160); private static final Dimension LOW_RES_DIMENSION = new Dimension(2160, 1080); private WorldMapImageLoader() { } /** * Reads the world map image from disk if not yet loaded, otherwise * it is just returning the image. * <p> * If the world map image cannot be read an image with an error message is returned. * * @param highRes specifies if the high-resolution image shall be returned, * * @return the world map image */ public static BufferedImage getWorldMapImage(boolean highRes) { if (worldMapImage == null || isHighRes() != highRes) { setHighRes(highRes); LayerType layerType = LayerTypeRegistry.getLayerType("org.esa.snap.worldmap.BlueMarbleLayerType"); if (layerType == null) { worldMapImage = createErrorImage(); } else { final CollectionLayer rootLayer = new CollectionLayer(); Layer worldMapLayer = layerType.createLayer(new WorldMapLayerContext(rootLayer), new PropertyContainer()); Dimension dimension = highRes ? HI_RES_DIMENSION : LOW_RES_DIMENSION; final BufferedImageRendering biRendering = new BufferedImageRendering(dimension.width, dimension.height); biRendering.getViewport().setModelYAxisDown(false); biRendering.getViewport().zoom(worldMapLayer.getModelBounds()); worldMapLayer.render(biRendering); worldMapImage = biRendering.getImage(); } } return worldMapImage; } private static BufferedImage createErrorImage() { final BufferedImage errorImage = new BufferedImage(LOW_RES_DIMENSION.width, LOW_RES_DIMENSION.height, BufferedImage.TYPE_3BYTE_BGR); final Graphics graphics = errorImage.getGraphics(); graphics.setColor(Color.WHITE); final Font font = graphics.getFont().deriveFont(75.0f); if (graphics instanceof Graphics2D) { final Graphics2D g2d = (Graphics2D) graphics; g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); } graphics.setFont(font); final String msg = "Failed to load worldmap image."; final Rectangle2D stringBounds = graphics.getFontMetrics().getStringBounds(msg, graphics); final int xPos = (int) (errorImage.getWidth() * 0.5f - stringBounds.getWidth() * 0.5f); final int yPos = (int) (errorImage.getWidth() * 0.1f); graphics.drawString(msg, xPos, yPos); return errorImage; } private static boolean isHighRes() { return highResolution; } private static void setHighRes(boolean highRes) { highResolution = highRes; } private static class WorldMapLayerContext implements LayerContext { private final Layer rootLayer; private WorldMapLayerContext(Layer rootLayer) { this.rootLayer = rootLayer; } @Override public Object getCoordinateReferenceSystem() { return DefaultGeographicCRS.WGS84; } @Override public Layer getRootLayer() { return rootLayer; } } }