    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    }