001    //$HeadURL: svn+ssh://developername@svn.wald.intevation.org/deegree/base/trunk/src/org/deegree/tools/raster/SimpleText2Tiff.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     Klaus Greve
035     Department of Geography
036     University of Bonn
037     Meckenheimer Allee 166
038     53115 Bonn
039     Germany
040     E-Mail: klaus.greve@giub.uni-bonn.de
041    
042     ---------------------------------------------------------------------------*/
043    package org.deegree.tools.raster;
044    
045    import java.awt.color.ColorSpace;
046    import java.awt.image.BufferedImage;
047    import java.awt.image.ComponentColorModel;
048    import java.awt.image.DataBuffer;
049    import java.awt.image.Raster;
050    import java.awt.image.WritableRaster;
051    import java.io.BufferedReader;
052    import java.io.File;
053    import java.io.FileReader;
054    import java.io.IOException;
055    import java.util.ArrayList;
056    import java.util.Hashtable;
057    import java.util.List;
058    import java.util.Properties;
059    
060    import org.deegree.framework.util.ConvenienceFileFilter;
061    import org.deegree.framework.util.ImageUtils;
062    import org.deegree.framework.util.StringTools;
063    import org.deegree.model.coverage.grid.WorldFile;
064    import org.deegree.model.spatialschema.Envelope;
065    import org.deegree.model.spatialschema.GeometryFactory;
066    
067    /**
068     * This class ist similar to Text2Tiff. The major difference is that SimpleText2Tiff just is able to
069     * transform x y z formateted textfiles into 16BIT tiff images if the text files contains equal
070     * distance rasters. Missing raster cells will be filled with '0'.<br>
071     * The major advantage of SimpleText2Tiff is its speed. It is significantly faster than Text2Tiff
072     * because several checks and calculations can be skippted.
073     * 
074     * 
075     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
076     * @author last edited by: $Author: poth $
077     * 
078     * @version. $Revision: 6251 $, $Date: 2007-03-19 16:59:28 +0100 (Mo, 19 Mrz 2007) $
079     */
080    public class SimpleText2Tiff {
081    
082        private File[] files;
083    
084        private double resolution;
085    
086        private float offset = 0;
087    
088        private float scaleFactor = 1;
089    
090        private boolean use32Bit = false;
091    
092        /**
093         * 
094         * @param files
095         *            list of text files to tranform
096         * @param resolution
097         *            desired target resolution
098         * @param offset
099         *            desired z-value offset
100         * @param scaleFactor
101         *            desired z-value scale factor [value = (z + offset) * scaleFactor]
102         * @param use32Bit
103         */
104        public SimpleText2Tiff( File[] files, double resolution, float offset, float scaleFactor, boolean use32Bit ) {
105            this.files = files;
106            this.resolution = resolution;
107            this.offset = offset;
108            this.scaleFactor = scaleFactor;
109            this.use32Bit = use32Bit;
110        }
111    
112        /**
113         * starts transformation
114         * 
115         * @throws Exception
116         */
117        public void perform()
118                                throws Exception {
119            for ( int i = 0; i < files.length; i++ ) {
120                System.out.println( "process: " + files[i] );
121                text2tiff( files[i] );
122            }
123        }
124    
125        /**
126         * 
127         * @param file
128         * @throws Exception
129         */
130        private void text2tiff( File file )
131                                throws Exception {
132            Envelope bbox = getBoundingBox( file );
133            int width = (int) Math.round( bbox.getWidth() / resolution ) + 1;
134            int height = (int) Math.round( bbox.getHeight() / resolution ) + 1;
135    
136            BufferedImage out = null;
137            if ( use32Bit ) {
138                out = new BufferedImage( width, height, BufferedImage.TYPE_INT_ARGB );
139            } else {
140                ComponentColorModel ccm = new ComponentColorModel( ColorSpace.getInstance( ColorSpace.CS_GRAY ), null,
141                                                                   false, false, BufferedImage.OPAQUE,
142                                                                   DataBuffer.TYPE_USHORT );
143                WritableRaster wr = ccm.createCompatibleWritableRaster( width, height );
144                out = new BufferedImage( ccm, wr, false, new Hashtable() );
145            }
146            DataBuffer buffer = out.getRaster().getDataBuffer();
147    
148            BufferedReader br = new BufferedReader( new FileReader( file ) );
149            String line = null;
150            while ( ( line = br.readLine() ) != null ) {
151                double[] d = StringTools.toArrayDouble( line.trim(), " \t" );
152                int x = (int) Math.round( ( d[0] - bbox.getMin().getX() ) / resolution );
153                int y = height - (int) Math.round( ( d[1] - bbox.getMin().getY() ) / resolution ) - 1;
154                int pos = width * y + x;
155    
156                try {
157                    if ( use32Bit ) {
158                        buffer.setElem( pos, Float.floatToIntBits( (float) ( ( d[2] + offset ) * scaleFactor ) ) );
159                    } else {
160                        // buffer.setElemFloat( pos, (float) ( ( d[2] + offset ) * scaleFactor ) );
161                        buffer.setElem( pos, (int) Math.round( ( d[2] + offset ) * scaleFactor ) );
162                    }
163                    buffer.setElem( pos, Float.floatToIntBits( (float) d[2] ) );
164                } catch ( Exception e ) {
165                    System.out.println( "-------------------------------" );
166                    System.out.println( buffer.getSize() );
167                    System.out.println( "file bbox: " + bbox );
168                    System.out.println( "last line read: " + line );
169                    throw e;
170                }
171            }
172            br.close();
173            out.setData( Raster.createRaster( out.getSampleModel(), buffer, null ) );
174    
175            int pos = file.getAbsolutePath().lastIndexOf( '.' );
176            if ( pos < 0 ) {
177                pos = file.getAbsolutePath().length();
178            }
179            String fileName = file.getAbsolutePath().substring( 0, pos ) + ".tif";
180            ImageUtils.saveImage( out, fileName, 1 );
181            WorldFile wf = new WorldFile( resolution, resolution, 0, 0, bbox );
182            WorldFile.writeWorldFile( wf, file.getAbsolutePath().substring( 0, pos ) );
183    
184        }
185    
186        /**
187         * 
188         * @param file
189         * @return
190         * @throws IOException
191         */
192        private Envelope getBoundingBox( File file )
193                                throws IOException {
194            BufferedReader br = new BufferedReader( new FileReader( file ) );
195            String line = null;
196            double minx = Double.MAX_VALUE;
197            double miny = Double.MAX_VALUE;
198            double maxx = Double.MIN_VALUE;
199            double maxy = Double.MIN_VALUE;
200    
201            while ( ( line = br.readLine() ) != null ) {
202                double[] d = StringTools.toArrayDouble( line.trim(), " \t" );
203                if ( d[0] < minx ) {
204                    minx = d[0];
205                }
206                if ( d[0] > maxx ) {
207                    maxx = d[0];
208                }
209    
210                if ( d[1] < miny ) {
211                    miny = d[1];
212                }
213                if ( d[1] > maxy ) {
214                    maxy = d[1];
215                }
216            }
217            br.close();
218            return GeometryFactory.createEnvelope( minx, miny, maxx, maxy, null );
219        }
220    
221        /**
222         * @param args
223         * @throws IOException
224         */
225        public static void main( String[] args )
226                                throws Exception {
227    
228            Properties map = new Properties();
229            for ( int i = 0; i < args.length; i += 2 ) {
230                map.put( args[i], args[i + 1] );
231            }
232            if ( !validate( map ) ) {
233                System.out.println( "Parameters: -rootDir, -resolution, -offset and -scaleFactor must be set" );
234                return;
235            }
236    
237            List<File> fileList = new ArrayList<File>( 1000 );
238            File dir = new File( map.getProperty( "-rootDir" ) );
239            File[] files = null;
240            ConvenienceFileFilter cff = null;
241            if ( map.getProperty( "-extension" ) != null ) {
242                cff = new ConvenienceFileFilter( true, map.getProperty( "-extension" ) );
243                files = dir.listFiles( cff );
244            } else {
245                files = dir.listFiles();
246            }
247            for ( int i = 0; i < files.length; i++ ) {
248                if ( files[i].isDirectory() ) {
249                    readSubDirs( files[i], fileList, cff );
250                } else {
251                    fileList.add( files[i] );
252                }
253            }
254    
255            double resolution = Double.parseDouble( map.getProperty( "-resolution" ) );
256            float offset = Float.parseFloat( map.getProperty( "-offset" ) );
257            float scaleFactor = Float.parseFloat( map.getProperty( "-scaleFactor" ) );
258            boolean use32Bit = "true".equals( map.getProperty( "-use32Bit" ) );
259            SimpleText2Tiff t2t = new SimpleText2Tiff( fileList.toArray( new File[fileList.size()] ), resolution, offset,
260                                                       scaleFactor, use32Bit );
261            t2t.perform();
262    
263        }
264    
265        /**
266         * 
267         * @param file
268         * @param list
269         * @param cff
270         * @return list of files
271         */
272        private static List<File> readSubDirs( File file, List<File> list, ConvenienceFileFilter cff ) {
273            File[] entries = null;
274            if ( cff != null ) {
275                entries = file.listFiles( cff );
276            } else {
277                entries = file.listFiles();
278            }
279            if ( entries != null ) {
280                for ( int i = 0; i < entries.length; i++ ) {
281                    if ( entries[i].isDirectory() ) {
282                        list = readSubDirs( entries[i], list, cff );
283                    } else {
284                        list.add( entries[i] );
285                    }
286                }
287            }
288            return list;
289        }
290    
291        /**
292         * 
293         * @param param
294         * @return true if everything is correct
295         * @throws Exception
296         */
297        private static boolean validate( Properties param )
298                                throws Exception {
299    
300            if ( param.get( "-rootDir" ) == null ) {
301                System.out.println( "parameter -rootDir must be set" );
302                return false;
303            }
304            if ( param.get( "-resolution" ) == null ) {
305                System.out.println( "parameter -resolution must be set" );
306                return false;
307            }
308            if ( param.get( "-offset" ) == null ) {
309                System.out.println( "parameter -offset must be set" );
310                return false;
311            }
312            if ( param.get( "-scaleFactor" ) == null ) {
313                System.out.println( "parameter -scaleFactor must be set" );
314                return false;
315            }
316    
317            return true;
318        }
319    
320    }