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