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