    001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_testing/src/org/deegree/model/coverage/grid/ByteGridCoverage.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.model.coverage.grid;
    037
    038    import java.awt.Rectangle;
    039    import java.awt.image.BandedSampleModel;
    040    import java.awt.image.BufferedImage;
    041    import java.awt.image.DataBuffer;
    042    import java.awt.image.DataBufferByte;
    043    import java.awt.image.Raster;
    044    import java.awt.image.SampleModel;
    045    import java.awt.image.renderable.RenderableImage;
    046
    047    import org.deegree.model.spatialschema.Envelope;
    048    import org.deegree.ogcwebservices.wcs.describecoverage.CoverageOffering;
    049
    050    /**
    051     * GridCoverage implementation for holding grids stored in a raw byte matrix (byte[][]) or in a set of
    052     * <tt>ByteGridCoverage</tt>s
    053     *
    054     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
    055     * @author last edited by: $Author: mschneider $
    056     *
    057     * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
    058     */
    059    public class ByteGridCoverage extends AbstractGridCoverage {
    060
    061        private static final long serialVersionUID = 5612511572056707069L;
    062
    063        private byte[][][] data = null;
    064
    065        /**
    066         * @param coverageOffering
    067         * @param envelope
    068         * @param data
    069         */
    070        public ByteGridCoverage( CoverageOffering coverageOffering, Envelope envelope, byte[][][] data ) {
    071            this( coverageOffering, envelope, false, data );
    072        }
    073
    074        /**
    075         * @param coverageOffering
    076         * @param envelope
    077         * @param isEditable
    078         * @param data
    079         */
    080        public ByteGridCoverage( CoverageOffering coverageOffering, Envelope envelope, boolean isEditable, byte[][][] data ) {
    081            super( coverageOffering, envelope, isEditable );
    082            this.data = data;
    083        }
    084
    085        /**
    086         * @param coverageOffering
    087         * @param envelope
    088         * @param sources
    089         */
    090        public ByteGridCoverage( CoverageOffering coverageOffering, Envelope envelope, ByteGridCoverage[] sources ) {
    091            super( coverageOffering, envelope, sources );
    092        }
    093
    094        /**
    095         * The number of sample dimensions in the coverage. For grid coverages, a sample dimension is a band.
    096         *
    097         * @return The number of sample dimensions in the coverage.
    098         * @UML mandatory numSampleDimensions
    099         */
    100        public int getNumSampleDimensions() {
    101            if ( data != null ) {
    102                return data.length;
    103            }
    104            return sources[0].getNumSampleDimensions();
    105        }
    106
    107        /**
    108         * Returns 2D view of this coverage as a renderable image. This optional operation allows interoperability with <A
    109         * HREF="http://java.sun.com/products/java-media/2D/">Java2D</A>. If this coverage is a
    110         * {@link "org.opengis.coverage.grid.GridCoverage"} backed by a {@link java.awt.image.RenderedImage}, the underlying
    111         * image can be obtained with:
    112         *
    113         * <code>getRenderableImage(0,1).{@linkplain RenderableImage#createDefaultRendering()
    114         * createDefaultRendering()}</code>
    115         *
    116         * @param xAxis
    117         *            Dimension to use for the <var>x</var> axis.
    118         * @param yAxis
    119         *            Dimension to use for the <var>y</var> axis.
    120         * @return A 2D view of this coverage as a renderable image.
    121         * @throws UnsupportedOperationException
    122         *             if this optional operation is not supported.
    123         * @throws IndexOutOfBoundsException
    124         *             if <code>xAxis</code> or <code>yAxis</code> is out of bounds.
    125         */
    126        @Override
    127        public RenderableImage getRenderableImage( int xAxis, int yAxis )
    128                                throws UnsupportedOperationException, IndexOutOfBoundsException {
    129            if ( data != null ) {
    130
    131                return null;
    132            }
    133            // TODO if multi images -> sources.length > 0
    134            return null;
    135        }
    136
    137        /**
    138         * this is a deegree convenience method which returns the source image of an <tt>ImageGridCoverage</tt>. In procipal
    139         * the same can be done with the getRenderableImage(int xAxis, int yAxis) method. but creating a
    140         * <tt>RenderableImage</tt> image is very slow. I xAxis or yAxis <= 0 then the size of the returned image will be
    141         * calculated from the source images of the coverage.
    142         *
    143         * @param xAxis
    144         *            Dimension to use for the <var>x</var> axis.
    145         * @param yAxis
    146         *            Dimension to use for the <var>y</var> axis.
    147         * @return the source image of an <tt>ImageGridCoverage</tt>.
    148         */
    149        @Override
    150        public BufferedImage getAsImage( int xAxis, int yAxis ) {
    151
    152            if ( xAxis <= 0 || yAxis <= 0 ) {
    153                // get default size if passed target size is <= 0
    154                Rectangle rect = calculateOriginalSize();
    155                xAxis = rect.width;
    156                yAxis = rect.height;
    157            }
    158            BufferedImage bi = createBufferedImage( xAxis, yAxis );
    159            if ( data != null ) {
    160                bi = createBufferedImage( data[0][0].length, data[0].length );
    161                // total number of fields for one band; it is assumed that each
    162                // band has the same number of fiels
    163                int numOfFields = data[0].length * data[0][0].length;
    164                byte[][] bb = new byte[data.length][];
    165                for ( int z = 0; z < data.length; z++ ) {
    166                    bb[z] = new byte[numOfFields];
    167                }
    168                int c = 0;
    169                for ( int i = 0; i < data[0].length; i++ ) {
    170                    for ( int j = 0; j < data[0][i].length; j++ ) {
    171                        for ( int z = 0; z < data.length; z++ ) {
    172                            bb[z][c] = data[z][i][j];
    173                        }
    174                        c++;
    175                    }
    176                }
    177                DataBuffer db = new DataBufferByte( bb, numOfFields );
    178                SampleModel sm = new BandedSampleModel( DataBuffer.TYPE_BYTE, data[0][0].length, data[0].length,
    179                                                        data.length );
    180                Raster raster = Raster.createWritableRaster( sm, db, null );
    181                bi.setData( raster );
    182            } else {
    183                // it's a complex ByteGridCoverage made up of different
    184                // source coverages
    185                for ( int i = 0; i < sources.length; i++ ) {
    186                    BufferedImage sourceImg = ( (AbstractGridCoverage) sources[i] ).getAsImage( -1, -1 );
    187                    bi = paintImage( bi, getEnvelope(), sourceImg, sources[i].getEnvelope() );
    188                }
    189            }
    190
    191            return bi;
    192        }
    193
    194        private BufferedImage createBufferedImage( int xAxis, int yAxis ) {
    195            int sampleDim = getNumSampleDimensions();
    196            switch ( sampleDim ) {
    197            case 1:
    198                return new BufferedImage( xAxis, yAxis, BufferedImage.TYPE_BYTE_GRAY );
    199            case 3:
    200                return new BufferedImage( xAxis, yAxis, BufferedImage.TYPE_INT_RGB );
    201            default:
    202                return new BufferedImage( xAxis, yAxis, BufferedImage.TYPE_INT_ARGB );
    203            }
    204        }
    205
    206        /**
    207         * calculates the original size of a gridcoverage based on its resolution and the envelope(s) of its source(s).
    208         *
    209         * @return the size
    210         */
    211        private Rectangle calculateOriginalSize() {
    212            if ( data != null ) {
    213                return new Rectangle( data[0].length, data.length );
    214            }
    215            BufferedImage bi = ( (ImageGridCoverage) sources[0] ).getAsImage( -1, -1 );
    216            Envelope env = sources[0].getEnvelope();
    217            double dx = env.getWidth() / bi.getWidth();
    218            double dy = env.getHeight() / bi.getHeight();
    219            env = this.getEnvelope();
    220            int w = (int) Math.round( env.getWidth() / dx );
    221            int h = (int) Math.round( env.getHeight() / dy );
    222            return new Rectangle( w, h );
    223        }
    224    }