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