001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/processing/raster/converter/RawData2Image.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.processing.raster.converter;
037    
038    import java.awt.color.ColorSpace;
039    import java.awt.image.BufferedImage;
040    import java.awt.image.ColorModel;
041    import java.awt.image.ComponentColorModel;
042    import java.awt.image.DataBuffer;
043    import java.awt.image.Raster;
044    import java.awt.image.SampleModel;
045    import java.awt.image.WritableRaster;
046    import java.util.Hashtable;
047    
048    /**
049     * Offeres methods to wrap raw number data into a <code>BufferedImage</code>
050     *
051     *
052     * @version $Revision: 18195 $
053     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
054     * @author last edited by: $Author: mschneider $
055     *
056     * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
057     */
058    public class RawData2Image {
059    
060        /**
061         *
062         * @param type
063         *            the desired DataBuffer type
064         * @param width
065         * @param height
066         * @return a new Image
067         */
068        private static BufferedImage createImage( int type, int width, int height ) {
069    
070            ColorModel ccm = new ComponentColorModel( ColorSpace.getInstance( ColorSpace.CS_GRAY ), null, false, false,
071                                                      BufferedImage.OPAQUE, type );
072    
073            WritableRaster wr = ccm.createCompatibleWritableRaster( width, height );
074    
075            return new BufferedImage( ccm, wr, false, new Hashtable<Object, Object>() );
076    
077        }
078    
079        /**
080         * @return result will be a <code>BufferedImage</code> with a GRAY colorspace and
081         *         <code>DataBuffer.TYPE_BYTE</code>
082         *
083         * @param data
084         *            data to wrap
085         */
086        public static BufferedImage rawData2Image( byte[][] data ) {
087    
088            BufferedImage img = createImage( DataBuffer.TYPE_BYTE, data[0].length, data.length );
089            Raster raster = img.getData();
090            DataBuffer buffer = raster.getDataBuffer();
091    
092            for ( int i = 0; i < data.length; i++ ) {
093                for ( int j = 0; j < data[0].length; j++ ) {
094                    int pos = data[0].length * i + j;
095                    buffer.setElem( pos, data[i][j] );
096                }
097            }
098            img.setData( Raster.createRaster( img.getSampleModel(), buffer, null ) );
099            return img;
100        }
101    
102        /**
103         * @return result will be a <code>BufferedImage</code> with a GRAY colorspace and
104         *         <code>DataBuffer.TYPE_USHORT</code>
105         *
106         * @param data
107         *            data to wrap
108         */
109        public static BufferedImage rawData2Image( short[][] data ) {
110            BufferedImage img = createImage( DataBuffer.TYPE_USHORT, data[0].length, data.length );
111            Raster raster = img.getData();
112            DataBuffer buffer = raster.getDataBuffer();
113    
114            for ( int i = 0; i < data.length; i++ ) {
115                for ( int j = 0; j < data[0].length; j++ ) {
116                    int pos = data[0].length * i + j;
117                    buffer.setElem( pos, data[i][j] );
118                }
119            }
120            img.setData( Raster.createRaster( img.getSampleModel(), buffer, null ) );
121            return img;
122        }
123    
124        /**
125         * @return result will be a <code>BufferedImage</code> with a GRAY colorspace and
126         *         <code>DataBuffer.TYPE_INT</code>
127         *
128         * @param data
129         *            data to wrap
130         */
131        public static BufferedImage rawData2Image( int[][] data ) {
132            BufferedImage img = createImage( DataBuffer.TYPE_INT, data[0].length, data.length );
133            Raster raster = img.getData();
134            DataBuffer buffer = raster.getDataBuffer();
135    
136            for ( int i = 0; i < data.length; i++ ) {
137                for ( int j = 0; j < data[0].length; j++ ) {
138                    int pos = data[0].length * i + j;
139                    buffer.setElem( pos, data[i][j] );
140                }
141            }
142            img.setData( Raster.createRaster( img.getSampleModel(), buffer, null ) );
143            return img;
144        }
145    
146        /**
147         * Float data requires 4 Byte (32Bit) per data cell. It is common to reduce data depth by
148         * multiplying float values with 10 and map the rounded result to an unsigned short value
149         * (16Bit). This behavior can be controlled by the second parameter passed to this method. If
150         * set to <code>true</code> a image with 32Bit data depth and INT Databuffer will be created.
151         * Otherwise a 16Bit Image with an USHORT Databuffer will be created.<br>
152         * A default scale of 10 and no offset will be used
153         *
154         * @return result will be a <code>BufferedImage</code> with a GRAY colorspace.
155         *
156         * @param data
157         *            data to wrap
158         * @param use32Bits
159         */
160        public static BufferedImage rawData2Image( float[][] data, boolean use32Bits ) {
161            return rawData2Image( data, use32Bits, 10, 0 );
162        }
163    
164        /**
165         * Float data requires 4 Byte (32Bit) per data cell. It is common to reduce data depth by
166         * multiplying float values with 10 and map the rounded result to an unsigned short value
167         * (16Bit). This behavior can be controlled by the second parameter passed to this method. If
168         * set to <code>true</code> a image with 32Bit data depth and INT Databuffer will be created.
169         * Otherwise a 16Bit Image with an USHORT Databuffer will be created.
170         *
171         * @param data
172         * @param use32Bits
173         * @param scale
174         * @param offset
175         * @return result will be a <code>BufferedImage</code> with a GRAY colorspace.
176         */
177        public static BufferedImage rawData2Image( float[][] data, boolean use32Bits, float scale, float offset ) {
178            BufferedImage img = null;
179            if ( use32Bits ) {
180                img = new BufferedImage( data[0].length, data.length, BufferedImage.TYPE_INT_ARGB );
181                Raster raster = img.getData();
182                DataBuffer buffer = raster.getDataBuffer();
183                for ( int i = 0; i < data.length; i++ ) {
184                    for ( int j = 0; j < data[0].length; j++ ) {
185                        int pos = data[0].length * i + j;
186                        buffer.setElem( pos, Float.floatToIntBits( data[i][j] ) );
187                    }
188                }
189                img.setData( Raster.createRaster( img.getSampleModel(), buffer, null ) );
190            } else {
191                img = createImage( DataBuffer.TYPE_USHORT, data[0].length, data.length );
192                Raster raster = img.getData();
193                DataBuffer buffer = raster.getDataBuffer();
194                for ( int i = 0; i < data.length; i++ ) {
195                    for ( int j = 0; j < data[0].length; j++ ) {
196                        int pos = data[0].length * i + j;
197                        buffer.setElem( pos, Math.round( ( data[i][j] + offset ) * scale ) );
198                    }
199                }
200                img.setData( Raster.createRaster( img.getSampleModel(), buffer, null ) );
201            }
202    
203            return img;
204        }
205    
206        /**
207         * Special version of the method which creates a new BufferedImage according to the models
208         * given.
209         *
210         * @return result will be a <code>BufferedImage</code> with the given color model
211         *
212         * @param data
213         *            data to wrap
214         * @param use32Bits
215         * @param colorModel
216         * @param sampleModel
217         */
218        public static BufferedImage rawData2Image( float[][] data, boolean use32Bits, ColorModel colorModel,
219                                                   SampleModel sampleModel ) {
220    
221            BufferedImage img = null;
222            if ( use32Bits ) {
223                SampleModel sm = sampleModel.createCompatibleSampleModel( data[0].length, data.length );
224    
225                WritableRaster raster = Raster.createWritableRaster( sm, null );
226    
227                img = new BufferedImage( colorModel, raster, true, new Hashtable<Object, Object>() );
228    
229                for ( int i = 0; i < data.length; i++ ) {
230                    for ( int j = 0; j < data[i].length; j++ ) {
231                        img.setRGB( j, i, Float.floatToRawIntBits( data[i][j] ) );
232                    }
233                }
234    
235            } else {
236                img = createImage( DataBuffer.TYPE_USHORT, data[0].length, data.length );
237                Raster raster = img.getData();
238                DataBuffer buffer = raster.getDataBuffer();
239                for ( int i = 0; i < data.length; i++ ) {
240                    for ( int j = 0; j < data[i].length; j++ ) {
241                        int pos = data[i].length * i + j;
242                        buffer.setElem( pos, Math.round( data[i][j] * 10 ) );
243                    }
244                }
245                img.setData( Raster.createRaster( img.getSampleModel(), buffer, null ) );
246            }
247    
248            return img;
249        }
250    }