001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/graphics/displayelements/RasterDisplayElement.java $ 002 /*---------------------------------------------------------------------------- 003 This file is part of deegree, http://deegree.org/ 004 Copyright (C) 2001-2009 by: 005 Department of Geography, University of Bonn 006 and 007 lat/lon GmbH 008 009 This library is free software; you can redistribute it and/or modify it under 010 the terms of the GNU Lesser General Public License as published by the Free 011 Software Foundation; either version 2.1 of the License, or (at your option) 012 any later version. 013 This library is distributed in the hope that it will be useful, but WITHOUT 014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 016 details. 017 You should have received a copy of the GNU Lesser General Public License 018 along with this library; if not, write to the Free Software Foundation, Inc., 019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 021 Contact information: 022 023 lat/lon GmbH 024 Aennchenstr. 19, 53177 Bonn 025 Germany 026 http://lat-lon.de/ 027 028 Department of Geography, University of Bonn 029 Prof. Dr. Klaus Greve 030 Postfach 1147, 53001 Bonn 031 Germany 032 http://www.geographie.uni-bonn.de/deegree/ 033 034 e-mail: info@deegree.org 035 ----------------------------------------------------------------------------*/ 036 package org.deegree.graphics.displayelements; 037 038 import static java.lang.Math.max; 039 import static java.lang.Math.min; 040 041 import java.awt.Color; 042 import java.awt.Graphics; 043 import java.awt.Graphics2D; 044 import java.awt.image.BufferedImage; 045 import java.awt.image.ConvolveOp; 046 import java.awt.image.Kernel; 047 048 import org.deegree.framework.log.ILogger; 049 import org.deegree.framework.log.LoggerFactory; 050 import org.deegree.framework.util.Pair; 051 import org.deegree.graphics.sld.Categorize; 052 import org.deegree.graphics.sld.Interpolate; 053 import org.deegree.graphics.sld.RasterSymbolizer; 054 import org.deegree.graphics.transformation.GeoTransform; 055 import org.deegree.model.coverage.grid.GridCoverage; 056 import org.deegree.model.coverage.grid.ImageGridCoverage; 057 import org.deegree.model.spatialschema.Envelope; 058 import org.deegree.ogcwebservices.wms.operation.DimensionValues; 059 import org.deegree.ogcwebservices.wms.operation.GetMap; 060 import org.deegree.processing.raster.converter.Image2RawData; 061 062 /** 063 * 064 * 065 * 066 * @version $Revision: 24553 $ 067 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 068 * @author last edited by: $Author: aschmitz $ 069 * 070 * @version 1.0. $Revision: 24553 $, $Date: 2010-05-25 15:39:19 +0200 (Di, 25 Mai 2010) $ 071 * 072 * @since 2.0 073 */ 074 public class RasterDisplayElement extends AbstractDisplayElement { 075 076 private static final long serialVersionUID = -5195730721807600940L; 077 078 private static ILogger LOG = LoggerFactory.getLogger( RasterDisplayElement.class ); 079 080 private RasterSymbolizer symbolizer = null; 081 082 private GridCoverage gc = null; 083 084 private GetMap request; 085 086 /** 087 * Creates a new RasterDisplayElement_Impl object. 088 * 089 * @param gc 090 * raster 091 */ 092 RasterDisplayElement( GridCoverage gc ) { 093 setRaster( gc ); 094 symbolizer = new RasterSymbolizer(); 095 } 096 097 /** 098 * Creates a new RasterDisplayElement_Impl object. 099 * 100 * @param gc 101 * raster 102 * @param symbolizer 103 */ 104 RasterDisplayElement( GridCoverage gc, RasterSymbolizer symbolizer ) { 105 setRaster( gc ); 106 this.symbolizer = symbolizer; 107 } 108 109 RasterDisplayElement( GridCoverage gc, RasterSymbolizer symbolizer, GetMap request ) { 110 this.request = request; 111 setRaster( gc ); 112 this.symbolizer = symbolizer; 113 } 114 115 private void paintCoverage( Graphics2D g, float[][] data, int minx, int miny, int maxx, int maxy, 116 BufferedImage image ) { 117 Categorize categorize = symbolizer == null ? null : symbolizer.getCategorize(); 118 Interpolate interpolate = symbolizer == null ? null : symbolizer.getInterpolate(); 119 120 LOG.logDebug( categorize == null ? "Not using categorization symbolizer." : "Using categorization symbolizer." ); 121 LOG.logDebug( interpolate == null ? "Not using interpolation symbolizer." : "Using interpolation symbolizer." ); 122 123 int opac = symbolizer == null ? 1 : ( (int) ( 255 * symbolizer.getOpacity() ) << 24 ); 124 125 int width = maxx - minx; 126 int height = maxy - miny; 127 128 BufferedImage img = new BufferedImage( data[0].length, data.length, BufferedImage.TYPE_INT_ARGB ); 129 130 DimensionValues vals = request == null ? null : request.getDimElev(); 131 132 for ( int x = 0; x < data[0].length; ++x ) { 133 for ( int y = 0; y < data.length; ++y ) { 134 float d = data[y][x]; 135 int val = 0; 136 137 if ( ( vals != null && vals.includesValue( d ) ) || vals == null ) { 138 if ( categorize == null && interpolate == null ) { 139 val = image.getRGB( x, y ); 140 val = val & 0xffffff + opac; 141 } else if ( categorize != null ) { 142 val = categorize.categorize( d, opac ); 143 } else if ( interpolate != null ) { 144 val = interpolate.interpolate( d, opac ); 145 } 146 } 147 148 img.setRGB( x, y, val ); 149 } 150 } 151 152 if ( symbolizer != null && symbolizer.getShaded() ) { 153 BufferedImage old = img; 154 155 Pair<Integer, float[]> pair = symbolizer.getShadeKernel(); 156 Kernel kernel = new Kernel( 3, 3, new float[] { -1, -1, -1, -1, 10, -1, -1, -1, -1 } ); 157 ConvolveOp op = new ConvolveOp( kernel ); 158 img = op.filter( img, null ); 159 kernel = new Kernel( pair.first, pair.first, pair.second ); 160 op = new ConvolveOp( kernel ); 161 img = op.filter( img, null ); 162 163 // this post processing is necessary to remove pixels that were filtered out by the 164 // ELEVATION parameter 165 // value and to fix up artifacts from the shade operations above 166 for ( int y = 0; y < old.getHeight(); ++y ) { 167 for ( int x = 0; x < old.getWidth(); ++x ) { 168 int oldVal = old.getRGB( x, y ); 169 int newVal = img.getRGB( x, y ); 170 if ( oldVal == 0 ) { 171 img.setRGB( x, y, 0 ); 172 } else { 173 if ( ( newVal & 0xff000000 ) == 0 ) { 174 img.setRGB( x, y, oldVal ); 175 } else if ( ( newVal & 0xffffff ) == 0xffffff ) { 176 img.setRGB( x, y, oldVal ); 177 } 178 } 179 } 180 } 181 182 } 183 184 // attention: this is not gamma, but brightness (and a hack for iGeoDesktop) 185 if ( symbolizer != null && symbolizer.getGamma() != 0 ) { 186 for ( int y = 0; y < img.getHeight(); ++y ) { 187 for ( int x = 0; x < img.getWidth(); ++x ) { 188 int oldVal = img.getRGB( x, y ); 189 int gamma = (int) symbolizer.getGamma(); 190 Color c = new Color( oldVal, true ); 191 Color newC = new Color( min( 255, max( 0, c.getRed() + gamma ) ), min( 255, max( 0, c.getGreen() 192 + gamma ) ), 193 min( 255, max( 0, c.getBlue() + gamma ) ), c.getAlpha() ); 194 img.setRGB( x, y, newC.getRGB() ); 195 } 196 } 197 } 198 199 g.drawImage( img, minx, miny, width, height, null ); 200 } 201 202 /** 203 * renders the DisplayElement to the submitted graphic context 204 * 205 */ 206 public void paint( Graphics g, GeoTransform projection, double scale ) { 207 synchronized ( symbolizer ) { 208 try { 209 if ( doesScaleConstraintApply( scale ) ) { 210 Envelope env = gc.getEnvelope(); 211 int minx = (int) ( projection.getDestX( env.getMin().getX() ) ); 212 int maxy = (int) ( projection.getDestY( env.getMin().getY() ) ); 213 int maxx = (int) ( projection.getDestX( env.getMax().getX() ) ); 214 int miny = (int) ( projection.getDestY( env.getMax().getY() ) ); 215 216 if ( gc instanceof ImageGridCoverage ) { 217 ImageGridCoverage igc = (ImageGridCoverage) gc; 218 Graphics2D g2 = (Graphics2D) g; 219 BufferedImage image = igc.getAsImage( -1, -1 ); 220 221 if ( symbolizer.isDefault() && ( request == null || request.getDimElev() == null ) ) { 222 if ( symbolizer.getGamma() != 1 ) { 223 Kernel kernel = new Kernel( 1, 1, new float[] { (float) symbolizer.getGamma() } ); 224 image = new ConvolveOp( kernel ).filter( image, null ); 225 } 226 g2.drawImage( image, minx, miny, maxx - minx, maxy - miny, null ); 227 } else { 228 if ( symbolizer.scaleValid( scale ) ) { 229 paintCoverage( g2, new Image2RawData( image ).parse(), minx, miny, maxx, maxy, image ); 230 } 231 } 232 } else { 233 // TODO 234 // handle other grid coverages 235 } 236 } 237 } catch ( Exception e ) { 238 LOG.logError( e.getMessage(), e ); 239 throw new RuntimeException( e.getMessage(), e ); 240 } 241 } 242 } 243 244 /** 245 * returns the content of the <code>RasterDisplayElement</code> 246 * 247 * @return gird coverage 248 */ 249 public GridCoverage getRaster() { 250 return gc; 251 } 252 253 /** 254 * sets the grid coverage that represents the content of the <code>RasterDisplayElement</code> 255 * 256 * @param gc 257 * 258 */ 259 public void setRaster( GridCoverage gc ) { 260 this.gc = gc; 261 } 262 263 @Override 264 public boolean doesScaleConstraintApply( double scale ) { 265 return symbolizer.scaleValid( scale ); 266 } 267 268 }