001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/model/coverage/grid/ImageGridCoverage.java $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 004 This file is part of deegree. 005 Copyright (C) 2001-2008 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: greve@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: 9343 $, $Date: 2007-12-27 14:30:32 +0100 (Do, 27 Dez 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, BufferedImage image ) { 085 this( coverageOffering, envelope, false, image ); 086 } 087 088 /** 089 * 090 * @param coverageOffering 091 * @param envelope 092 * @param isEditable 093 * @param image 094 */ 095 public ImageGridCoverage( CoverageOffering coverageOffering, Envelope envelope, boolean isEditable, 096 BufferedImage image ) { 097 super( coverageOffering, envelope, isEditable ); 098 this.image = image; 099 } 100 101 /** 102 * 103 * @param coverageOffering 104 * @param envelope 105 * @param crs 106 * @param isEditable 107 * @param image 108 */ 109 public ImageGridCoverage( CoverageOffering coverageOffering, Envelope envelope, CoordinateSystem crs, 110 boolean isEditable, BufferedImage image ) { 111 super( coverageOffering, envelope, crs, isEditable ); 112 this.image = image; 113 } 114 115 /** 116 * 117 * @param coverageOffering 118 * @param envelope 119 * @param sources 120 */ 121 public ImageGridCoverage( CoverageOffering coverageOffering, Envelope envelope, ImageGridCoverage[] sources ) { 122 super( coverageOffering, envelope, sources ); 123 } 124 125 /** 126 * The number of sample dimensions in the coverage. For grid coverages, a sample dimension is a 127 * band. 128 * 129 * @return The number of sample dimensions in the coverage. 130 */ 131 public int getNumSampleDimensions() { 132 if ( image != null ) { 133 return image.getData().getNumBands(); 134 } 135 return sources[0].getNumSampleDimensions(); 136 } 137 138 /** 139 * Returns 2D view of this coverage as a renderable image. This optional operation allows 140 * interoperability with <A HREF="http://java.sun.com/products/java-media/2D/">Java2D</A>. If 141 * this coverage is a {@link "org.opengis.coverage.grid.GridCoverage"} backed by a 142 * {@link java.awt.image.RenderedImage}, the underlying image can be obtained with: 143 * 144 * <code>getRenderableImage(0,1).{@linkplain RenderableImage#createDefaultRendering() 145 * createDefaultRendering()}</code> 146 * 147 * @param xAxis 148 * Dimension to use for the <var>x</var> axis. 149 * @param yAxis 150 * Dimension to use for the <var>y</var> axis. 151 * @return A 2D view of this coverage as a renderable image. 152 * @throws UnsupportedOperationException 153 * if this optional operation is not supported. 154 * @throws IndexOutOfBoundsException 155 * if <code>xAxis</code> or <code>yAxis</code> is out of bounds. 156 */ 157 public RenderableImage getRenderableImage( int xAxis, int yAxis ) 158 throws UnsupportedOperationException, IndexOutOfBoundsException { 159 if ( image != null ) { 160 if ( xAxis > 0 && yAxis > 0 ) { 161 Rectangle rect = new Rectangle( xAxis, yAxis ); 162 RenderableGraphics rg = new RenderableGraphics( rect ); 163 rg.drawImage( image, 0, 0, xAxis, yAxis, null ); 164 return rg; 165 } 166 Rectangle rect = new Rectangle( image.getWidth(), image.getHeight() ); 167 RenderableGraphics rg = new RenderableGraphics( rect ); 168 rg.drawImage( image, 0, 0, null ); 169 return rg; 170 } 171 // TODO if multi images -> sources.length > 0 172 return null; 173 } 174 175 /** 176 * this is a deegree convenience method which returns the source image of an 177 * <tt>ImageGridCoverage</tt>. In procipal the same can be done with the 178 * getRenderableImage(int xAxis, int yAxis) method. but creating a <tt>RenderableImage</tt> 179 * image is very slow. I xAxis or yAxis <= 0 then the size of the returned image will be 180 * calculated from the source images of the coverage. 181 * 182 * @param xAxis 183 * Dimension to use for the <var>x</var> axis. 184 * @param yAxis 185 * Dimension to use for the <var>y</var> axis. 186 * @return the source image of an <tt>ImageGridCoverage</tt>. 187 */ 188 public BufferedImage getAsImage( int xAxis, int yAxis ) { 189 190 if ( xAxis <= 0 || yAxis <= 0 ) { 191 // get default size if passed target size is <= 0 192 Rectangle rect = calculateOriginalSize(); 193 xAxis = rect.width; 194 yAxis = rect.height; 195 } 196 BufferedImage bi = null; 197 if ( image != null ) { 198 if ( xAxis == image.getWidth() && yAxis == image.getHeight() ) { 199 bi = image; 200 } else { 201 // it's a simple ImageGridCoverage just made up of one image 202 ParameterBlock pb = new ParameterBlock(); 203 pb.addSource( image ); 204 pb.add( xAxis / (float) image.getWidth() ); // The xScale 205 pb.add( yAxis / (float) image.getHeight() ); // The yScale 206 pb.add( 0.0F ); // The x translation 207 pb.add( 0.0F ); // The y translation 208 Interpolation interpolation = new InterpolationNearest(); 209 pb.add( interpolation ); // The interpolation 210 // Create the scale operation 211 RenderedOp ro = JAI.create( "scale", pb, null ); 212 bi = ro.getAsBufferedImage(); 213 } 214 } else { 215 String natFrm = coverageOffering.getSupportedFormats().getNativeFormat().getCode(); 216 if ( "jpg".equalsIgnoreCase( natFrm ) || "jpeg".equalsIgnoreCase( natFrm ) 217 || "bmp".equalsIgnoreCase( natFrm ) ) { 218 bi = new BufferedImage( xAxis, yAxis, BufferedImage.TYPE_INT_RGB ); 219 } else { 220 bi = new BufferedImage( xAxis, yAxis, BufferedImage.TYPE_INT_ARGB ); 221 } 222 // it's a complex ImageGridCoverage made up of different 223 // source coverages 224 if ( sources == null || sources.length == 0 ) { 225 return bi; 226 } 227 228 for ( int i = 0; i < sources.length; i++ ) { 229 PT_Envelope env = sources[i].getEnvelope(); 230 Envelope sourceEnv = GeometryFactory.createEnvelope( env.minCP.ord[0], env.minCP.ord[1], 231 env.maxCP.ord[0], env.maxCP.ord[1], null ); 232 env = this.getEnvelope(); 233 Envelope targetEnv = GeometryFactory.createEnvelope( env.minCP.ord[0], env.minCP.ord[1], 234 env.maxCP.ord[0], env.maxCP.ord[1], null ); 235 236 BufferedImage sourceImg = ( (ImageGridCoverage) sources[i] ).getAsImage( -1, -1 ); 237 bi = paintImage( bi, targetEnv, sourceImg, sourceEnv ); 238 } 239 } 240 241 return bi; 242 } 243 244 /** 245 * calculates the original size of a gridcoverage based on its resolution and the envelope(s) of 246 * its source(s). 247 * 248 * @return 249 */ 250 private Rectangle calculateOriginalSize() { 251 if ( image != null ) { 252 return new Rectangle( image.getWidth(), image.getHeight() ); 253 } 254 BufferedImage bi = ( (ImageGridCoverage) sources[0] ).getAsImage( -1, -1 ); 255 PT_Envelope env = sources[0].getEnvelope(); 256 double dx = ( env.maxCP.ord[0] - env.minCP.ord[0] ) / bi.getWidth(); 257 double dy = ( env.maxCP.ord[1] - env.minCP.ord[1] ) / bi.getHeight(); 258 env = this.getEnvelope(); 259 int w = (int) Math.round( ( env.maxCP.ord[0] - env.minCP.ord[0] ) / dx ); 260 int h = (int) Math.round( ( env.maxCP.ord[1] - env.minCP.ord[1] ) / dy ); 261 return new Rectangle( w, h ); 262 } 263 264 }