001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_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 }