001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/io/imgapi/IMGReader.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    
037    package org.deegree.io.imgapi;
038    
039    import java.io.IOException;
040    import java.io.RandomAccessFile;
041    
042    import org.deegree.graphics.transformation.GeoTransform;
043    import org.deegree.graphics.transformation.WorldToScreenTransform;
044    import org.deegree.model.spatialschema.ByteUtils;
045    import org.deegree.model.spatialschema.Envelope;
046    
047    /**
048     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
049     */
050    
051    public class IMGReader {
052    
053        public static final int BYTE = 1;
054    
055        public static final int SMALLINT = 2;
056    
057        public static final int INT = 3;
058    
059        public static final int FLOAT = 4;
060    
061        public static final int DOUBLE = 8;
062    
063        private String fileName = null;
064    
065        private int width = 0;
066    
067        private int height = 0;
068    
069        private int type = 0;
070    
071        private GeoTransform trans = null;
072    
073        /**
074         * Creates a new instance of IMGReader
075         *
076         * @param fileName
077         * @param width
078         * @param height
079         * @param bbox
080         * @param type
081         */
082        public IMGReader( String fileName, int width, int height, Envelope bbox, int type ) {
083    
084            this.fileName = fileName;
085            this.width = width;
086            this.height = height;
087            this.type = type;
088            trans = new WorldToScreenTransform( bbox.getMin().getX(), bbox.getMin().getY(), bbox.getMax().getX(),
089                                                bbox.getMax().getY(), 0, 0, width - 1, height - 1 );
090        }
091    
092        /**
093         * reads a rectangular subset from the image
094         *
095         * @param bbox
096         *            desired bounding box
097         */
098        public float[][] read( Envelope bbox )
099                                throws IOException {
100    
101            float[][] data = null;
102            switch ( type ) {
103            case BYTE:
104                data = readByte( bbox );
105                break;
106            case SMALLINT:
107                data = readSmallInt( bbox );
108                break;
109            case INT:
110                data = readInt( bbox );
111                break;
112            case FLOAT:
113                data = readFloat( bbox );
114                break;
115            case DOUBLE:
116                data = readDouble( bbox );
117                break;
118            default:
119                throw new IOException( "not supported file format!" );
120            }
121    
122            return data;
123        }
124    
125        /**
126         *
127         * @param bbox
128         * @return
129         * @throws IOException
130         */
131        private float[][] readByte( Envelope bbox )
132                                throws IOException {
133    
134            int x1 = (int) trans.getDestX( bbox.getMin().getX() );
135            if ( x1 < 0 )
136                x1 = 0;
137            int y1 = (int) trans.getDestY( bbox.getMin().getY() );
138            if ( y1 >= height )
139                y1 = height - 1;
140            int x2 = (int) trans.getDestX( bbox.getMax().getX() );
141            if ( x2 >= width )
142                x1 = width - 1;
143            int y2 = (int) trans.getDestY( bbox.getMax().getY() );
144            if ( y2 < 0 )
145                y2 = 0;
146    
147            int w = Math.abs( x2 - x1 );
148            int h = Math.abs( y1 - y2 );
149    
150            RandomAccessFile raf = new RandomAccessFile( fileName, "r" );
151    
152            byte[] b = new byte[w];
153            float[][] data = new float[h][w];
154            for ( int i = 0; i < h; i++ ) {
155                raf.seek( width * ( y2 + i ) + x1 );
156                raf.read( b );
157                for ( int j = 0; j < w; j++ ) {
158                    data[i][j] = b[j] + 127f;
159                }
160            }
161            raf.close();
162    
163            return data;
164        }
165    
166        /**
167         *
168         * @param bbox
169         * @return
170         * @throws IOException
171         */
172        private float[][] readSmallInt( Envelope bbox )
173                                throws IOException {
174            int x1 = (int) trans.getDestX( bbox.getMin().getX() );
175            if ( x1 < 0 )
176                x1 = 0;
177            int y1 = (int) trans.getDestY( bbox.getMin().getY() );
178            if ( y1 >= height )
179                y1 = height - 1;
180            int x2 = (int) trans.getDestX( bbox.getMax().getX() );
181            if ( x2 >= width )
182                x1 = width - 1;
183            int y2 = (int) trans.getDestY( bbox.getMax().getY() );
184            if ( y2 < 0 )
185                y2 = 0;
186    
187            int w = Math.abs( x2 - x1 );
188            int h = Math.abs( y1 - y2 );
189            RandomAccessFile raf = new RandomAccessFile( fileName, "r" );
190    
191            byte[] b = new byte[w * 4];
192            float[][] data = new float[h][w];
193            for ( int i = 0; i < h; i++ ) {
194                raf.seek( ( width * ( y2 + i ) + x1 ) * 4 );
195                raf.read( b );
196                int k = 0;
197                for ( int j = 0; j < w; j++ ) {
198                    data[i][j] = ByteUtils.readBEShort( b, k );
199                    k += 4;
200                }
201            }
202            raf.close();
203    
204            return data;
205        }
206    
207        /**
208         *
209         * @param bbox
210         * @return
211         * @throws IOException
212         */
213        private float[][] readInt( Envelope bbox )
214                                throws IOException {
215    
216            int x1 = (int) trans.getDestX( bbox.getMin().getX() );
217            if ( x1 < 0 )
218                x1 = 0;
219            int y1 = (int) trans.getDestY( bbox.getMin().getY() );
220            if ( y1 >= height )
221                y1 = height - 1;
222            int x2 = (int) trans.getDestX( bbox.getMax().getX() );
223            if ( x2 >= width )
224                x1 = width - 1;
225            int y2 = (int) trans.getDestY( bbox.getMax().getY() );
226            if ( y2 < 0 )
227                y2 = 0;
228    
229            int w = Math.abs( x2 - x1 );
230            int h = Math.abs( y1 - y2 );
231            RandomAccessFile raf = new RandomAccessFile( fileName, "r" );
232    
233            byte[] b = new byte[w * 4];
234            float[][] data = new float[h][w];
235            for ( int i = 0; i < h; i++ ) {
236                raf.seek( ( width * ( y2 + i ) + x1 ) * 4 );
237                raf.read( b );
238                int k = 0;
239                for ( int j = 0; j < w; j++ ) {
240                    data[i][j] = ByteUtils.readBEInt( b, k );
241                    k += 4;
242                }
243            }
244            raf.close();
245    
246            return data;
247        }
248    
249        /**
250         *
251         * @param bbox
252         * @return
253         * @throws IOException
254         */
255        private float[][] readFloat( Envelope bbox )
256                                throws IOException {
257    
258            int x1 = (int) trans.getDestX( bbox.getMin().getX() );
259            int y1 = (int) trans.getDestY( bbox.getMin().getY() );
260            int x2 = (int) trans.getDestX( bbox.getMax().getX() );
261            int y2 = (int) trans.getDestY( bbox.getMax().getY() );
262    
263            int w = Math.abs( x2 - x1 );
264            int h = Math.abs( y1 - y2 );
265    
266            if ( w <= 0 || h <= 0 )
267                return new float[0][0];
268    
269            RandomAccessFile raf = new RandomAccessFile( fileName, "r" );
270    
271            byte[] b = new byte[width * FLOAT];
272            float[][] data = new float[h][w];
273            for ( int i = y2; i < y1; i++ ) {
274                if ( i >= 0 && i < height ) {
275                    raf.seek( width * i * FLOAT );
276                    raf.readFully( b );
277                    int k = 0;
278                    if ( x1 > 0 )
279                        k = x1 * FLOAT;
280                    for ( int j = x1; j < x2; j++ ) {
281                        if ( j >= 0 && j < width ) {
282                            data[i - y2][j - x1] = ByteUtils.readBEFloat( b, k );
283                            k += FLOAT;
284                        }
285                    }
286                }
287            }
288            raf.close();
289    
290            return data;
291        }
292    
293        /**
294         *
295         * @param bbox
296         * @return
297         * @throws IOException
298         */
299        private float[][] readDouble( Envelope bbox )
300                                throws IOException {
301    
302            int x1 = (int) trans.getDestX( bbox.getMin().getX() );
303            if ( x1 < 0 )
304                x1 = 0;
305            int y1 = (int) trans.getDestY( bbox.getMin().getY() );
306            if ( y1 >= height )
307                y1 = height - 1;
308            int x2 = (int) trans.getDestX( bbox.getMax().getX() );
309            if ( x2 >= width )
310                x1 = width - 1;
311            int y2 = (int) trans.getDestY( bbox.getMax().getY() );
312            if ( y2 < 0 )
313                y2 = 0;
314    
315            int w = Math.abs( x2 - x1 );
316            int h = Math.abs( y1 - y2 );
317    
318            RandomAccessFile raf = new RandomAccessFile( fileName, "r" );
319    
320            byte[] b = new byte[w * DOUBLE];
321            float[][] data = new float[h][w];
322            for ( int i = 0; i < h; i++ ) {
323                raf.seek( ( width * ( y2 + i ) + x1 ) * DOUBLE );
324                raf.read( b );
325                int k = 0;
326                for ( int j = 0; j < w; j++ ) {
327                    data[i][j] = (float) ByteUtils.readBEDouble( b, k );
328                    k += DOUBLE;
329                }
330            }
331            raf.close();
332    
333            return data;
334        }
335    
336    }