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