001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/model/coverage/grid/ImageGridCoverage.java $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 004 This file is part of deegree 005 Copyright (C) 2001-2006 by: 006 EXSE, Department of Geography, University of Bonn 007 http://www.giub.uni-bonn.de/deegree/ 008 lat/lon GmbH 009 http://www.lat-lon.de 010 011 This library is free software; you can redistribute it and/or 012 modify it under the terms of the GNU Lesser General Public 013 License as published by the Free Software Foundation; either 014 version 2.1 of the License, or (at your option) any later version. 015 016 This library is distributed in the hope that it will be useful, 017 but WITHOUT ANY WARRANTY; without even the implied warranty of 018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 019 Lesser General Public License for more details. 020 021 You should have received a copy of the GNU Lesser General Public 022 License along with this library; if not, write to the Free Software 023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 024 025 Contact: 026 027 Andreas Poth 028 lat/lon GmbH 029 Aennchenstr. 19 030 53115 Bonn 031 Germany 032 E-Mail: poth@lat-lon.de 033 034 Prof. Dr. Klaus Greve 035 Department of Geography 036 University of Bonn 037 Meckenheimer Allee 166 038 53115 Bonn 039 Germany 040 E-Mail: fitzke@giub.uni-bonn.de 041 042 043 ---------------------------------------------------------------------------*/ 044 package org.deegree.model.coverage.grid; 045 046 import java.awt.Rectangle; 047 import java.awt.image.BufferedImage; 048 import java.awt.image.renderable.ParameterBlock; 049 import java.awt.image.renderable.RenderableImage; 050 051 import javax.media.jai.Interpolation; 052 import javax.media.jai.InterpolationNearest; 053 import javax.media.jai.JAI; 054 import javax.media.jai.RenderableGraphics; 055 import javax.media.jai.RenderedOp; 056 057 import org.deegree.model.crs.CoordinateSystem; 058 import org.deegree.model.spatialschema.Envelope; 059 import org.deegree.model.spatialschema.GeometryFactory; 060 import org.deegree.ogcwebservices.wcs.describecoverage.CoverageOffering; 061 import org.opengis.pt.PT_Envelope; 062 063 /** 064 * GridCoverage implementation for holding grids stored in an <tt>BufferedImage</tt> or in a set 065 * of <tt>ImageGridCoverage</tt>s 066 * 067 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 068 * @author last edited by: $Author: apoth $ 069 * 070 * @version $Revision: 7842 $, $Date: 2007-07-25 09:44:14 +0200 (Mi, 25 Jul 2007) $ 071 */ 072 public class ImageGridCoverage extends AbstractGridCoverage { 073 074 private static final long serialVersionUID = -531939507044569726L; 075 076 private transient BufferedImage image = null; 077 078 /** 079 * 080 * @param coverageOffering 081 * @param envelope 082 * @param image 083 */ 084 public ImageGridCoverage( CoverageOffering coverageOffering, Envelope envelope, 085 BufferedImage image ) { 086 this( coverageOffering, envelope, false, image ); 087 } 088 089 /** 090 * 091 * @param coverageOffering 092 * @param envelope 093 * @param isEditable 094 * @param image 095 */ 096 public ImageGridCoverage( CoverageOffering coverageOffering, Envelope envelope, 097 boolean isEditable, BufferedImage image ) { 098 super( coverageOffering, envelope, isEditable ); 099 this.image = image; 100 } 101 102 /** 103 * 104 * @param coverageOffering 105 * @param envelope 106 * @param crs 107 * @param isEditable 108 * @param image 109 */ 110 public ImageGridCoverage( CoverageOffering coverageOffering, Envelope envelope, 111 CoordinateSystem crs, boolean isEditable, BufferedImage image ) { 112 super( coverageOffering, envelope, crs, isEditable ); 113 this.image = image; 114 } 115 116 /** 117 * 118 * @param coverageOffering 119 * @param envelope 120 * @param sources 121 */ 122 public ImageGridCoverage( CoverageOffering coverageOffering, Envelope envelope, 123 ImageGridCoverage[] sources ) { 124 super( coverageOffering, envelope, sources ); 125 } 126 127 /** 128 * The number of sample dimensions in the coverage. For grid coverages, a sample dimension is a 129 * band. 130 * 131 * @return The number of sample dimensions in the coverage. 132 */ 133 public int getNumSampleDimensions() { 134 if ( image != null ) { 135 return image.getData().getNumBands(); 136 } 137 return sources[0].getNumSampleDimensions(); 138 } 139 140 141 /** 142 * Returns 2D view of this coverage as a renderable image. This optional operation allows 143 * interoperability with <A HREF="http://java.sun.com/products/java-media/2D/">Java2D</A>. If 144 * this coverage is a {@link "org.opengis.coverage.grid.GridCoverage"} backed by a 145 * {@link java.awt.image.RenderedImage}, the underlying image can be obtained with: 146 * 147 * <code>getRenderableImage(0,1).{@linkplain RenderableImage#createDefaultRendering() 148 * createDefaultRendering()}</code> 149 * 150 * @param xAxis 151 * Dimension to use for the <var>x</var> axis. 152 * @param yAxis 153 * Dimension to use for the <var>y</var> axis. 154 * @return A 2D view of this coverage as a renderable image. 155 * @throws UnsupportedOperationException 156 * if this optional operation is not supported. 157 * @throws IndexOutOfBoundsException 158 * if <code>xAxis</code> or <code>yAxis</code> is out of bounds. 159 */ 160 public RenderableImage getRenderableImage( int xAxis, int yAxis ) 161 throws UnsupportedOperationException, IndexOutOfBoundsException { 162 if ( image != null ) { 163 if ( xAxis > 0 && yAxis > 0 ) { 164 Rectangle rect = new Rectangle( xAxis, yAxis ); 165 RenderableGraphics rg = new RenderableGraphics( rect ); 166 rg.drawImage( image, 0, 0, xAxis, yAxis, null ); 167 return rg; 168 } 169 Rectangle rect = new Rectangle( image.getWidth(), image.getHeight() ); 170 RenderableGraphics rg = new RenderableGraphics( rect ); 171 rg.drawImage( image, 0, 0, null ); 172 return rg; 173 } 174 // TODO if multi images -> sources.length > 0 175 return null; 176 } 177 178 /** 179 * this is a deegree convenience method which returns the source image of an 180 * <tt>ImageGridCoverage</tt>. In procipal the same can be done with the 181 * getRenderableImage(int xAxis, int yAxis) method. but creating a <tt>RenderableImage</tt> 182 * image is very slow. I xAxis or yAxis <= 0 then the size of the returned image will be 183 * calculated from the source images of the coverage. 184 * 185 * @param xAxis 186 * Dimension to use for the <var>x</var> axis. 187 * @param yAxis 188 * Dimension to use for the <var>y</var> axis. 189 * @return the source image of an <tt>ImageGridCoverage</tt>. 190 */ 191 public BufferedImage getAsImage( int xAxis, int yAxis ) { 192 193 if ( xAxis <= 0 || yAxis <= 0 ) { 194 // get default size if passed target size is <= 0 195 Rectangle rect = calculateOriginalSize(); 196 xAxis = rect.width; 197 yAxis = rect.height; 198 } 199 BufferedImage bi = null; 200 if ( image != null ) { 201 if ( xAxis == image.getWidth() && yAxis == image.getHeight() ) { 202 bi = image; 203 } else { 204 // it's a simple ImageGridCoverage just made up of one image 205 ParameterBlock pb = new ParameterBlock(); 206 pb.addSource( image ); 207 pb.add( xAxis / (float) image.getWidth() ); // The xScale 208 pb.add( yAxis / (float) image.getHeight() ); // The yScale 209 pb.add( 0.0F ); // The x translation 210 pb.add( 0.0F ); // The y translation 211 Interpolation interpolation = new InterpolationNearest(); 212 pb.add( interpolation ); // The interpolation 213 // Create the scale operation 214 RenderedOp ro = JAI.create( "scale", pb, null ); 215 bi = ro.getAsBufferedImage(); 216 } 217 } else { 218 String natFrm = coverageOffering.getSupportedFormats().getNativeFormat().getCode(); 219 if ( "jpg".equalsIgnoreCase( natFrm ) || "jpeg".equalsIgnoreCase( natFrm ) 220 || "bmp".equalsIgnoreCase( natFrm ) ) { 221 bi = new BufferedImage( xAxis, yAxis, BufferedImage.TYPE_INT_RGB ); 222 } else { 223 bi = new BufferedImage( xAxis, yAxis, BufferedImage.TYPE_INT_ARGB ); 224 } 225 // it's a complex ImageGridCoverage made up of different 226 // source coverages 227 if ( sources == null || sources.length == 0 ) { 228 return bi; 229 } 230 231 for ( int i = 0; i < sources.length; i++ ) { 232 PT_Envelope env = sources[i].getEnvelope(); 233 Envelope sourceEnv = GeometryFactory.createEnvelope( env.minCP.ord[0], 234 env.minCP.ord[1], 235 env.maxCP.ord[0], 236 env.maxCP.ord[1], null ); 237 env = this.getEnvelope(); 238 Envelope targetEnv = GeometryFactory.createEnvelope( env.minCP.ord[0], 239 env.minCP.ord[1], 240 env.maxCP.ord[0], 241 env.maxCP.ord[1], null ); 242 243 BufferedImage sourceImg = ( (ImageGridCoverage) sources[i] ).getAsImage( -1, -1 ); 244 bi = paintImage( bi, targetEnv, sourceImg, sourceEnv ); 245 } 246 } 247 248 return bi; 249 } 250 251 /** 252 * calculates the original size of a gridcoverage based on its resolution and the envelope(s) of 253 * its source(s). 254 * 255 * @return 256 */ 257 private Rectangle calculateOriginalSize() { 258 if ( image != null ) { 259 return new Rectangle( image.getWidth(), image.getHeight() ); 260 } 261 BufferedImage bi = ( (ImageGridCoverage) sources[0] ).getAsImage( -1, -1 ); 262 PT_Envelope env = sources[0].getEnvelope(); 263 double dx = ( env.maxCP.ord[0] - env.minCP.ord[0] ) / bi.getWidth(); 264 double dy = ( env.maxCP.ord[1] - env.minCP.ord[1] ) / bi.getHeight(); 265 env = this.getEnvelope(); 266 int w = (int) Math.round( ( env.maxCP.ord[0] - env.minCP.ord[0] ) / dx ); 267 int h = (int) Math.round( ( env.maxCP.ord[1] - env.minCP.ord[1] ) / dy ); 268 return new Rectangle( w, h ); 269 } 270 271 } 272 /*************************************************************************************************** 273 * <code> 274 Changes to this class. What the people have been up to: 275 276 $Log$ 277 Revision 1.19 2007/03/13 12:38:33 wanhoff 278 Fixed Javadoc (@link, @return) 279 Revision 280 1.18 2007/02/09 17:27:59 poth 281 *** empty log message *** 282 283 Revision 1.17 2007/01/10 15:26:41 poth 284 bug fixes handling raw data coverages 285 286 Revision 1.16 2007/01/05 10:54:43 poth 287 bug fix 288 289 Revision 1.15 2007/01/02 14:44:53 poth 290 bug fix 291 292 Revision 1.14 2006/12/14 16:59:28 poth 293 not necessary import statements removed 294 295 Revision 1.13 2006/12/13 16:08:06 poth 296 *** empty log message *** 297 298 Revision 1.12 2006/12/12 20:02:51 poth 299 use bilinear interpolation as default 300 301 Revision 1.11 2006/12/03 21:19:53 poth 302 new constructor added 303 304 Revision 1.10 2006/11/17 08:58:01 poth 305 bug fixes - setting correct interpolation 306 307 Revision 1.9 2006/11/16 21:02:37 poth 308 bug fixes - rescaling images 309 310 Revision 1.8 2006/11/15 14:19:54 poth 311 bug fix - cast scaling values to float 312 313 Revision 1.7 2006/11/14 14:08:25 poth 314 bug fix - scaling image 315 316 Revision 1.6 2006/04/06 20:25:26 poth 317 *** empty log message *** 318 319 Revision 1.5 2006/03/30 21:20:26 poth 320 *** empty log message *** 321 322 Revision 1.4 2006/03/01 19:50:38 poth 323 *** empty log message *** 324 325 Revision 1.3 2005/07/22 16:19:56 poth 326 no message 327 328 Revision 1.2 2005/03/16 11:54:25 poth 329 no message 330 331 Revision 1.15 2004/08/23 06:59:52 ap 332 no message 333 334 Revision 1.14 2004/08/09 06:43:50 ap 335 no message 336 337 Revision 1.13 2004/08/06 06:41:51 ap 338 grid coverage implementation extension 339 340 Revision 1.12 2004/07/30 06:29:29 ap 341 code optimization 342 343 Revision 1.11 2004/07/23 07:14:45 ap 344 no message 345 346 Revision 1.10 2004/07/22 15:20:41 ap 347 no message 348 349 Revision 1.9 2004/07/22 12:17:08 ap 350 no message 351 352 </code> 353 **************************************************************************************************/