/*---------------- FILE HEADER ------------------------------------------
This file is part of deegree
Copyright (C) 2001-2006 by:
EXSE, Department of Geography, University of Bonn
http://www.giub.uni-bonn.de/deegree/
lat/lon GmbH
http://www.lat-lon.de
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact:
Andreas Poth
lat/lon GmbH
Aennchenstr. 19
53115 Bonn
Germany
E-Mail: poth@lat-lon.de
Prof. Dr. Klaus Greve
Department of Geography
University of Bonn
Meckenheimer Allee 166
53115 Bonn
Germany
E-Mail: fitzke@giub.uni-bonn.de
---------------------------------------------------------------------------*/
package org.deegree.model.coverage.grid;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.renderable.ParameterBlock;
import java.awt.image.renderable.RenderableImage;
import javax.media.jai.InterpolationNearest;
import javax.media.jai.JAI;
import javax.media.jai.RenderableGraphics;
import javax.media.jai.RenderedOp;
import org.deegree.model.crs.CoordinateSystem;
import org.deegree.model.spatialschema.Envelope;
import org.deegree.model.spatialschema.GeometryFactory;
import org.deegree.ogcwebservices.wcs.describecoverage.CoverageOffering;
import org.opengis.coverage.grid.GridNotEditableException;
import org.opengis.coverage.grid.GridRange;
import org.opengis.coverage.grid.InvalidRangeException;
import org.opengis.pt.PT_Envelope;
/**
* GridCoverage implementation for holding grids stored in an
* <tt>BufferedImage</tt> or in a set of <tt>ImageGridCoverage</tt>s
*
* @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
* @version 2.11.2002
*/
public class ImageGridCoverage extends AbstractGridCoverage {
private static final long serialVersionUID = -531939507044569726L;
private transient BufferedImage image = null;
/**
*
* @param coverageOffering
* @param envelope
* @param image
*/
public ImageGridCoverage( CoverageOffering coverageOffering, Envelope envelope,
BufferedImage image ) {
this( coverageOffering, envelope, false, image );
}
/**
*
* @param coverageOffering
* @param envelope
* @param isEditable
* @param image
*/
public ImageGridCoverage( CoverageOffering coverageOffering, Envelope envelope,
boolean isEditable, BufferedImage image ) {
super( coverageOffering, envelope, isEditable );
this.image = image;
}
/**
*
* @param coverageOffering
* @param envelope
* @param crs
* @param isEditable
* @param image
*/
public ImageGridCoverage( CoverageOffering coverageOffering, Envelope envelope,
CoordinateSystem crs, boolean isEditable, BufferedImage image ) {
super( coverageOffering, envelope, crs, isEditable );
this.image = image;
}
/**
*
* @param coverageOffering
* @param envelope
* @param sources
*/
public ImageGridCoverage( CoverageOffering coverageOffering, Envelope envelope,
ImageGridCoverage[] sources ) {
super( coverageOffering, envelope, sources );
}
/**
* The number of sample dimensions in the coverage.
* For grid coverages, a sample dimension is a band.
*
* @return The number of sample dimensions in the coverage.
*/
public int getNumSampleDimensions() {
if ( image != null ) {
return image.getData().getNumBands();
}
return sources[0].getNumSampleDimensions();
}
/**
* Return a sequence of boolean values for a block.
* A value for each sample dimension will be returned.
* The semantic is the same as {@link #getDataBlock(GridRange, double[])}
* except for the return type.
*
* @param gridRange Grid range for block of data to be accessed.
* @param destination An optionally preallocated array in which to store the values,
* or <code>null</code> if none.
* @return A sequence of boolean values for a given block in the coverage.
* If <code>destination</code> was non-null, then it is returned.
* Otherwise, a new array is allocated and returned.
* @throws InvalidRangeException if <code>gridRange</code> is out of this grid range bounds.
* @throws ArrayIndexOutOfBoundsException if the <code>destination</code> array is not null
* and too small to hold the output.
*
* @see #setDataBlock(GridRange, boolean[])
*/
public boolean[] getDataBlock( GridRange gridRange, boolean[] destination )
throws InvalidRangeException, ArrayIndexOutOfBoundsException {
return null;
}
/**
* Return a sequence of double values for a block.
* A value for each sample dimension will be returned.
*
* The return value is an <VAR>N</VAR>+1 dimensional safe-array, with dimensions
* (sample dimension, dimension <var>n</var>, dimension <var>n</var>-1, ... dimension 1).
*
* For 2 dimensional grid coverages, this safe array will be accessed as
* (sample dimension, column, row).
*
* The index values will be based from 0. The indices in the returned <VAR>N</VAR> dimensional
* safe array will need to be offset by <code>gridRange</code> {@linkplain GridRange#getLower()
* minimum coordinates} to get equivalent grid coordinates.
* <br><br>
* The requested grid range must satisfy the following rules for each dimension of the grid
* coverage:
* <center>
* minimum grid coordinate <= {@linkplain GridRange#getLower() grid range mimimun} <=
* {@linkplain GridRange#getUpper() grid range maximum} <= maximum grid coordinate
* </center>
*
* The number of values returned will equal:
* <center>
* (max<sub>1</sub> � min<sub>1</sub> + 1) *
* (max<sub>2</sub> � min<sub>2</sub> + 1) ... *
* (max<sub>n</sub> � min<sub>n</sub> + 1) *
* </center>
*
* Where <var>min</var> is the minimum ordinate in the grid range,
* <var>max</var> is the maximum ordinate in the grid range and
* <VAR>N</VAR> is the number of dimensions in the grid coverage.
*
* @param gridRange Grid range for block of data to be accessed.
* @param destination An optionally preallocated array in which to store the values,
* or <code>null</code> if none.
* @return A sequence of double values for a given block in the coverage.
* If <code>destination</code> was non-null, then it is returned.
* Otherwise, a new array is allocated and returned.
* @throws InvalidRangeException if <code>gridRange</code> is out of this grid range bounds.
* @throws ArrayIndexOutOfBoundsException if the <code>destination</code> array is not null
* and too small to hold the output.
*
* @rename Renamed <code>getValueBlockAsDouble</code> as <code>getDataBlockAsDouble</code>
* for consistency with all others <code>getDataBlock...</code> methods and
* <code>setDataBlockAsDouble</code>.
*
* @revisit Which indices vary fastest?
*
* @see #setDataBlock(GridRange, double[])
* @see javax.media.jai.UnpackedImageData#getDoubleData()
*/
public double[] getDataBlock( GridRange gridRange, double[] destination )
throws InvalidRangeException, ArrayIndexOutOfBoundsException {
byte[] data = null;
data = getDataBlock( gridRange, data );
double[] sdata = new double[data.length];
for ( int i = 0; i < sdata.length; i++ ) {
sdata[i] = data[i];
}
return sdata;
}
/** Return a block of grid coverage data for all sample dimensions.
* A value for each sample dimension will be returned.
* This operation provides efficient access of the grid values.
* The sequencing order of the values in the sequence will follow the rules
* given by valueInBytePacking and bandPacking defined in GridPacking.
*
* The requested grid range must satisfy the following rules for each dimension
* of the grid coverage:
*
* <blockquote><pre>
* Min grid coordinate <= grid range minimum <= grid range maximum <= maximum grid coordinate
* </pre></blockquote>
*
* The sequence of bytes returned will match the data type of the dimension.
* For example, a grid with one 16 bit unsigned (CV_16BIT_U) sample dimension will
* return 2 bytes for every cell in the block.
* <br><br>
* <strong>Byte padding Rules for grid values of less than 8 bits</strong><br>
* For 2 D grid coverages, padding is to the nearest byte for the following cases:
*
* <table border=0>
* <tr> <td>For PixelInterleaved</td>
* <td>For grids with multiple sample dimensions, padding occurs between
* pixels for each change in dimension type.</td>
* </tr>
* <tr> <td>For LineInterleaved</td>
* <td>Padding occurs at the end of each row or column (depending on the
* valueSequence of the grid).</td>
* </tr>
* <tr> <td>For BandSequencial</td>
* <td>Padding occurs at the end of every sample dimension.</td>
* </tr>
* </table>
*
* For grid values smaller than 8 bits, their order within each byte is given by the
* value defined in {@link org.opengis.coverage.grid.GridPacking#getValueInBytePacking
* valueInBytePacking}.
* For grid values bigger than 8 bits, the order of their bytes is given by the
* value defined in {@link org.opengis.coverage.grid.GridPacking#getByteInValuePacking
* byteInValuePacking}.
*
* @param gridRange Grid range for block of data to be accessed.
* @return a block of grid coverage data for all sample dimensions.
*
*/
public byte[] getPackedDataBlock( GridRange gridRange ) {
return null;
}
/** Optimal size to use for each dimension when accessing grid values.
* These values together give the optimal block size to use when retrieving
* grid coverage values.
* For example, a client application can achieve better performance for a 2-D grid
* coverage by reading blocks of 128 by 128 if the grid is tiled into blocks of
* this size.
* The sequence is ordered by dimension.
* If the implementation does not have optimal sizes the sequence will be empty.
*
* @return the optimal size to use for each dimension when accessing grid values.
*
*/
public int[] getOptimalDataBlockSizes() {
return new int[0];
}
/**
* Return a sequence of 32 bits values for a block.
* A value for each sample dimension will be returned.
* The semantic is the same as {@link #getDataBlock(GridRange, double[])}
* except for the return type.
*
* @param gridRange Grid range for block of data to be accessed.
* @param destination An optionally preallocated array in which to store the values,
* or <code>null</code> if none.
* @return A sequence of 32 bits values for a given block in the coverage.
* If <code>destination</code> was non-null, then it is returned.
* Otherwise, a new array is allocated and returned.
* @throws InvalidRangeException if <code>gridRange</code> is out of this grid range bounds.
* @throws ArrayIndexOutOfBoundsException if the <code>destination</code> array is not null
* and too small to hold the output.
*
* @see #setDataBlock(GridRange, int[])
* @see javax.media.jai.UnpackedImageData#getIntData()
*/
public int[] getDataBlock( GridRange gridRange, int[] destination )
throws InvalidRangeException, ArrayIndexOutOfBoundsException {
byte[] data = null;
data = getDataBlock( gridRange, data );
int[] sdata = new int[data.length];
for ( int i = 0; i < sdata.length; i++ ) {
sdata[i] = data[i];
}
return sdata;
}
/**
* Return a sequence of float values for a block.
* A value for each sample dimension will be returned.
* The semantic is the same as {@link #getDataBlock(GridRange, double[])}
* except for the return type.
*
* @param gridRange Grid range for block of data to be accessed.
* @param destination An optionally preallocated array in which to store the values,
* or <code>null</code> if none.
* @return A sequence of float values for a given block in the coverage.
* If <code>destination</code> was non-null, then it is returned.
* Otherwise, a new array is allocated and returned.
* @throws InvalidRangeException if <code>gridRange</code> is out of this grid range bounds.
* @throws ArrayIndexOutOfBoundsException if the <code>destination</code> array is not null
* and too small to hold the output.
*
* @see #setDataBlock(GridRange, float[])
* @see javax.media.jai.UnpackedImageData#getFloatData()
*/
public float[] getDataBlock( GridRange gridRange, float[] destination )
throws InvalidRangeException, ArrayIndexOutOfBoundsException {
byte[] data = null;
data = getDataBlock( gridRange, data );
float[] sdata = new float[data.length];
for ( int i = 0; i < sdata.length; i++ ) {
sdata[i] = data[i];
}
return sdata;
}
/**
* Return a sequence of 8 bits values for a block.
* A value for each sample dimension will be returned.
* The semantic is the same as {@link #getDataBlock(GridRange, double[])}
* except for the return type.
*
* @param gridRange Grid range for block of data to be accessed.
* @param destination An optionally preallocated array in which to store the values,
* or <code>null</code> if none.
* @return A sequence of 8 bits values for a given block in the coverage.
* If <code>destination</code> was non-null, then it is returned.
* Otherwise, a new array is allocated and returned.
* @throws InvalidRangeException if <code>gridRange</code> is out of this grid range bounds.
* @throws ArrayIndexOutOfBoundsException if the <code>destination</code> array is not null
* and too small to hold the output.
*
* @see #setDataBlock(GridRange, byte[])
* @see javax.media.jai.UnpackedImageData#getByteData()
*/
public byte[] getDataBlock( GridRange gridRange, byte[] destination )
throws InvalidRangeException, ArrayIndexOutOfBoundsException {
int[] hi = gridRange.getUpper();
int[] lo = gridRange.getLower();
BufferedImage img = null;
if ( image != null ) {
img = image;
} else {
// get entire image from all source coverages in its
// original resolution
getAsImage( -1, -1 );
}
if ( lo[0] < 0 || lo[1] < 0 || hi[0] > img.getWidth() || hi[1] > img.getHeight() ) {
throw new InvalidRangeException( "upper range and lower range"
+ "must be within the image size." );
}
if ( hi[0] <= lo[0] || hi[1] <= lo[1] ) {
throw new InvalidRangeException( "lower range must be less than upper range" );
}
Rectangle rect = new Rectangle( lo[0], lo[1], hi[0] - lo[0], hi[1] - lo[1] );
// extract byte data from the renderedOps and write them to a byte matrix
DataBuffer db = img.getData( rect ).getDataBuffer();
DataBufferByte dbb = (DataBufferByte) db;
byte[] o = dbb.getData();
// calculate offsets of the bands / sample dimensions
// a RGB color image is assumed
int[] off = new int[3];
off[0] = 0;
off[1] = rect.width * rect.height * 3;
off[2] = off[1] * 2;
destination = new byte[rect.width * rect.height * 3];
int c = 0;
for ( int j = 0; j < rect.height * rect.width; j++ ) {
destination[off[0] + j] = o[c++];
destination[off[1] + j] = o[c++];
destination[off[2] + j] = o[c++];
}
return destination;
}
/**
* Return a sequence of 16 bits values for a block.
* A value for each sample dimension will be returned.
* The semantic is the same as {@link #getDataBlock(GridRange, double[])}
* except for the return type.
*
* @param gridRange Grid range for block of data to be accessed.
* @param destination An optionally preallocated array in which to store the values,
* or <code>null</code> if none.
* @return A sequence of 16 bits values for a given block in the coverage.
* If <code>destination</code> was non-null, then it is returned.
* Otherwise, a new array is allocated and returned.
* @throws InvalidRangeException if <code>gridRange</code> is out of this grid range bounds.
* @throws ArrayIndexOutOfBoundsException if the <code>destination</code> array is not null
* and too small to hold the output.
* @UML operation getDataBlockAsInteger
*
* @see #setDataBlock(GridRange, int[])
* @see javax.media.jai.UnpackedImageData#getShortData()
*/
public short[] getDataBlock( GridRange gridRange, short[] destination )
throws InvalidRangeException, ArrayIndexOutOfBoundsException {
byte[] data = null;
data = getDataBlock( gridRange, data );
short[] sdata = new short[data.length];
for ( int i = 0; i < sdata.length; i++ ) {
sdata[i] = data[i];
}
return sdata;
}
/**
* Set a block of boolean values for all sample dimensions.
* The semantic is the same as {@link #setDataBlock(GridRange, double[])}.
*
* @param gridRange Grid range for block of data to be accessed.
* @param values Sequence of grid values for the given region.
* @throws InvalidRangeException if <code>gridRange</code> is out of this grid range bounds.
* @throws GridNotEditableException if the grid coverage is not editable.
* @throws ArrayIndexOutOfBoundsException if the <code>values</code> array is too small.
*
* @see #getDataBlock(GridRange, boolean[])
*/
public void setDataBlock( GridRange gridRange, boolean[] values )
throws InvalidRangeException, GridNotEditableException,
ArrayIndexOutOfBoundsException {
throw new NoSuchMethodError();
}
/**
* Set a block of 8 bits values for all sample dimensions.
* The semantic is the same as {@link #setDataBlock(GridRange, double[])}.
*
* @param gridRange Grid range for block of data to be accessed.
* @param values Sequence of grid values for the given region.
* @throws InvalidRangeException if <code>gridRange</code> is out of this grid range bounds.
* @throws GridNotEditableException if the grid coverage is not editable.
* @throws ArrayIndexOutOfBoundsException if the <code>values</code> array is too small.
*
* @see #getDataBlock(GridRange, byte[])
*/
public void setDataBlock( GridRange gridRange, byte[] values )
throws InvalidRangeException, GridNotEditableException,
ArrayIndexOutOfBoundsException {
// DataBuffer db = new DataBufferByte(values, values.length);
// SampleModel sm = new BandedSampleModel(DataBuffer.TYPE_BYTE, 500,500,3);
// WritableRaster raster = Raster.createWritableRaster( sm, db, null );
// BufferedImage bi = new BufferedImage(500,500,BufferedImage.TYPE_INT_RGB);
// bi.setData(raster);
// sources = null;
}
/**
* Set a block of 16 bits values for all sample dimensions.
* The semantic is the same as {@link #setDataBlock(GridRange, double[])}.
*
* @param gridRange Grid range for block of data to be accessed.
* @param values Sequence of grid values for the given region.
* @throws InvalidRangeException if <code>gridRange</code> is out of this grid range bounds.
* @throws GridNotEditableException if the grid coverage is not editable.
* @throws ArrayIndexOutOfBoundsException if the <code>values</code> array is too small.
*
* @see #getDataBlock(GridRange, short[])
*/
public void setDataBlock( GridRange gridRange, short[] values )
throws InvalidRangeException, GridNotEditableException,
ArrayIndexOutOfBoundsException {
new NoSuchMethodError();
}
/**
* Set a block of 32 bits values for all sample dimensions.
* The semantic is the same as {@link #setDataBlock(GridRange, double[])}.
*
* @param gridRange Grid range for block of data to be accessed.
* @param values Sequence of grid values for the given region.
* @throws InvalidRangeException if <code>gridRange</code> is out of this grid range bounds.
* @throws GridNotEditableException if the grid coverage is not editable.
* @throws ArrayIndexOutOfBoundsException if the <code>values</code> array is too small.
*
* @see #getDataBlock(GridRange, int[])
* @see java.awt.image.WritableRaster#setPixels(int,int,int,int,int[])
*/
public void setDataBlock( GridRange gridRange, int[] values )
throws InvalidRangeException, GridNotEditableException,
ArrayIndexOutOfBoundsException {
new NoSuchMethodError();
}
/**
* Set a block of float values for all sample dimensions.
* The semantic is the same as {@link #setDataBlock(GridRange, double[])}.
*
* @param gridRange Grid range for block of data to be accessed.
* @param values Sequence of grid values for the given region.
* @throws InvalidRangeException if <code>gridRange</code> is out of this grid range bounds.
* @throws GridNotEditableException if the grid coverage is not editable.
* @throws ArrayIndexOutOfBoundsException if the <code>values</code> array is too small.
*
* @see #getDataBlock(GridRange, float[])
* @see java.awt.image.WritableRaster#setPixels(int,int,int,int,float[])
*/
public void setDataBlock( GridRange gridRange, float[] values )
throws InvalidRangeException, GridNotEditableException,
ArrayIndexOutOfBoundsException {
new NoSuchMethodError();
}
/**
* Set a block of double values for all sample dimensions.
* The requested grid range must satisfy the following rules for each
* dimension of the grid coverage:
*
* <center>
* minimum grid coordinate <= {@linkplain GridRange#getLower() grid range mimimun} <=
* </center>
*
* The number of values must equal:
*
* <center>
* (max<sub>1</sub> � min<sub>1</sub> + 1) *
* (max<sub>2</sub> � min<sub>2</sub> + 1) ... *
* (max<sub>n</sub> � min<sub>n</sub> + 1) *
* </center>
*
* Where <var>min</var> is the minimum ordinate in the grid range,
* <var>max</var> is the maximum ordinate in the grid range and
* <VAR>N</VAR> is the number of dimensions in the grid coverage.
*
* @param gridRange Grid range for block of data to be accessed.
* @param values Sequence of grid values for the given region.
* @throws InvalidRangeException if <code>gridRange</code> is out of this grid range bounds.
* @throws GridNotEditableException if the grid coverage is not editable.
* @throws ArrayIndexOutOfBoundsException if the <code>values</code> array is too small.
*
* @see #getDataBlock(GridRange, double[])
* @see java.awt.image.WritableRaster#setPixels(int,int,int,int,double[])
*/
public void setDataBlock( GridRange gridRange, double[] values )
throws InvalidRangeException, GridNotEditableException,
ArrayIndexOutOfBoundsException {
new NoSuchMethodError();
}
/**
* Set a block of grid coverage data for all sample dimensions.
* See {@link #getPackedDataBlock} for details on how to pack the values.
*
* @param gridRange Grid range for block of data to be accessed.
* @param values Sequence of grid values for the given region.
* @throws InvalidRangeException if <code>gridRange</code> is out of this grid range bounds.
* @throws GridNotEditableException if the grid coverage is not editable.
* @throws ArrayIndexOutOfBoundsException if the <code>values</code> array is too small.
*
* @revisit This operation can hardly be implemented efficiently in Java with a
* <code>byte[]</code> argument type, since we can't easily cast an array
* of <code>byte[]</code> to an array of arbitrary type.
*/
public void setPackedDataBlock( GridRange gridRange, byte[] values )
throws InvalidRangeException, GridNotEditableException,
ArrayIndexOutOfBoundsException {
}
/**
* Returns 2D view of this coverage as a renderable image.
* This optional operation allows interoperability with
* <A HREF="http://java.sun.com/products/java-media/2D/">Java2D</A>.
* If this coverage is a {@link org.opengis.coverage.grid.GridCoverage} backed
* by a {@link java.awt.image.RenderedImage}, the underlying image can be obtained
* with:
*
* <code>getRenderableImage(0,1).{@linkplain RenderableImage#createDefaultRendering()
* createDefaultRendering()}</code>
*
* @param xAxis Dimension to use for the <var>x</var> axis.
* @param yAxis Dimension to use for the <var>y</var> axis.
* @return A 2D view of this coverage as a renderable image.
* @throws UnsupportedOperationException if this optional operation is not supported.
* @throws IndexOutOfBoundsException if <code>xAxis</code> or
* <code>yAxis</code> is out of bounds.
*/
public RenderableImage getRenderableImage( int xAxis, int yAxis )
throws UnsupportedOperationException, IndexOutOfBoundsException {
if ( image != null ) {
if ( xAxis > 0 && yAxis > 0 ) {
Rectangle rect = new Rectangle( xAxis, yAxis );
RenderableGraphics rg = new RenderableGraphics( rect );
rg.drawImage( image, 0, 0, xAxis, yAxis, null );
return rg;
}
Rectangle rect = new Rectangle( image.getWidth(), image.getHeight() );
RenderableGraphics rg = new RenderableGraphics( rect );
rg.drawImage( image, 0, 0, null );
return rg;
}
//TODO if multi images -> sources.length > 0
return null;
}
/**
* this is a deegree convenience method which returns the source image
* of an <tt>ImageGridCoverage</tt>. In procipal the same can be done
* with the getRenderableImage(int xAxis, int yAxis) method. but creating
* a <tt>RenderableImage</tt> image is very slow.
* I xAxis or yAxis <= 0 then the size of the returned image will be
* calculated from the source images of the coverage.
* @param xAxis Dimension to use for the <var>x</var> axis.
* @param yAxis Dimension to use for the <var>y</var> axis.
* @return
*/
public BufferedImage getAsImage( int xAxis, int yAxis ) {
if ( xAxis <= 0 || yAxis <= 0 ) {
// get default size if passed target size is <= 0
Rectangle rect = calculateOriginalSize();
xAxis = rect.width;
yAxis = rect.height;
}
BufferedImage bi = null;
if ( image != null ) {
if ( xAxis == image.getWidth() && yAxis == image.getHeight() ) {
bi = image;
} else {
// it's a simple ImageGridCoverage just made up of one image
ParameterBlock pb = new ParameterBlock();
pb.addSource( image );
pb.add( xAxis / (float)image.getWidth() ); // The xScale
pb.add( yAxis / (float)image.getHeight() ); // The yScale
pb.add( 0.0F ); // The x translation
pb.add( 0.0F ); // The y translation
pb.add( new InterpolationNearest() ); // The interpolation
// Create the scale operation
RenderedOp ro = JAI.create( "scale", pb, null );
bi = ro.getAsBufferedImage();
}
} else {
bi = new BufferedImage( xAxis, yAxis, BufferedImage.TYPE_INT_ARGB );
// it's a complex ImageGridCoverage made up of different
// source coverages
if ( sources == null || sources.length == 0 ) {
return bi;
}
for ( int i = 0; i < sources.length; i++ ) {
PT_Envelope env = sources[i].getEnvelope();
Envelope sourceEnv = GeometryFactory.createEnvelope( env.minCP.ord[0],
env.minCP.ord[1],
env.maxCP.ord[0],
env.maxCP.ord[1], null );
env = this.getEnvelope();
Envelope targetEnv = GeometryFactory.createEnvelope( env.minCP.ord[0],
env.minCP.ord[1],
env.maxCP.ord[0],
env.maxCP.ord[1], null );
BufferedImage sourceImg = ( (ImageGridCoverage) sources[i] ).getAsImage( -1, -1 );
bi = paintImage( bi, targetEnv, sourceImg, sourceEnv );
}
}
return bi;
}
/**
* calculates the original size of a gridcoverage based on its resolution
* and the envelope(s) of its source(s).
* @return
*/
private Rectangle calculateOriginalSize() {
if ( image != null ) {
return new Rectangle( image.getWidth(), image.getHeight() );
}
BufferedImage bi = ( (ImageGridCoverage) sources[0] ).getAsImage( -1, -1 );
PT_Envelope env = sources[0].getEnvelope();
double dx = ( env.maxCP.ord[0] - env.minCP.ord[0] ) / bi.getWidth();
double dy = ( env.maxCP.ord[1] - env.minCP.ord[1] ) / bi.getHeight();
env = this.getEnvelope();
int w = (int) Math.round( ( env.maxCP.ord[0] - env.minCP.ord[0] ) / dx );
int h = (int) Math.round( ( env.maxCP.ord[1] - env.minCP.ord[1] ) / dy );
return new Rectangle( w, h );
}
}
/* ********************************************************************
Changes to this class. What the people have been up to:
$Log: ImageGridCoverage.java,v $
Revision 1.11 2006/12/03 21:19:53 poth
new constructor added
Revision 1.10 2006/11/17 08:58:01 poth
bug fixes - setting correct interpolation
Revision 1.9 2006/11/16 21:02:37 poth
bug fixes - rescaling images
Revision 1.8 2006/11/15 14:19:54 poth
bug fix - cast scaling values to float
Revision 1.7 2006/11/14 14:08:25 poth
bug fix - scaling image
Revision 1.6 2006/04/06 20:25:26 poth
*** empty log message ***
Revision 1.5 2006/03/30 21:20:26 poth
*** empty log message ***
Revision 1.4 2006/03/01 19:50:38 poth
*** empty log message ***
Revision 1.3 2005/07/22 16:19:56 poth
no message
Revision 1.2 2005/03/16 11:54:25 poth
no message
Revision 1.15 2004/08/23 06:59:52 ap
no message
Revision 1.14 2004/08/09 06:43:50 ap
no message
Revision 1.13 2004/08/06 06:41:51 ap
grid coverage implementation extension
Revision 1.12 2004/07/30 06:29:29 ap
code optimization
Revision 1.11 2004/07/23 07:14:45 ap
no message
Revision 1.10 2004/07/22 15:20:41 ap
no message
Revision 1.9 2004/07/22 12:17:08 ap
no message
********************************************************************** */