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 }