001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/tools/raster/Rescaler.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.tools.raster;
038    
039    import java.awt.image.BufferedImage;
040    import java.awt.image.renderable.ParameterBlock;
041    import java.io.File;
042    import java.net.URI;
043    import java.util.ArrayList;
044    import java.util.List;
045    import java.util.Properties;
046    
047    import javax.media.jai.Interpolation;
048    import javax.media.jai.InterpolationBilinear;
049    import javax.media.jai.JAI;
050    import javax.media.jai.RenderedOp;
051    
052    import org.deegree.datatypes.QualifiedName;
053    import org.deegree.framework.log.ILogger;
054    import org.deegree.framework.log.LoggerFactory;
055    import org.deegree.framework.util.ConvenienceFileFilter;
056    import org.deegree.framework.util.ImageUtils;
057    import org.deegree.io.dbaseapi.DBaseFile;
058    import org.deegree.model.coverage.grid.WorldFile;
059    import org.deegree.ogcbase.CommonNamespaces;
060    
061    /**
062     *
063     *
064     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
065     * @author last edited by: $Author: mschneider $
066     *
067     * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
068     */
069    public class Rescaler {
070    
071        private static final ILogger LOG = LoggerFactory.getLogger( Rescaler.class );
072    
073        private static final URI DEEGREEAPP = CommonNamespaces.buildNSURI( "http://www.deegree.org/app" );
074    
075        private static final String APP_PREFIX = "app";
076    
077        private String outDir;
078    
079        private String format;
080    
081        private Interpolation interpolation = new InterpolationBilinear();
082    
083        private List<String> fileList;
084    
085        private double resolution = 0;
086    
087        /**
088         *
089         * @param resolution
090         * @param rootDir
091         * @param outDir
092         * @param format
093         * @param subDirs
094         */
095        Rescaler( double resolution, String rootDir, String outDir, String format, boolean subDirs ) {
096            this.resolution = resolution;
097            this.outDir = outDir;
098            this.format = format;
099            fileList = getFileList( rootDir, subDirs );
100        }
101    
102        /**
103         *
104         * @param resolution
105         * @param rootDir
106         * @param outDir
107         * @param dBase
108         * @param format
109         * @param fileColumn
110         * @throws Exception
111         */
112        Rescaler( double resolution, String rootDir, String outDir, String dBase, String format, String fileColumn )
113                                throws Exception {
114            this.resolution = resolution;
115            this.outDir = outDir;
116            this.format = format;
117            fileList = getFileList( dBase, fileColumn, rootDir );
118        }
119    
120        /**
121         * returns the list of image map files to consider read from a dbase file defined by the dbase parameter
122         *
123         * @param dbaseFile
124         *            name of the dbase file
125         * @param fileColumn
126         *            name of the column containing the image map files names
127         * @param baseDir
128         *            name of the directory where the image map files are stored if this parameter is <code>null</code> it
129         *            is assumed that the image map files are full referenced within the dbase
130         * @return the list of image map files to consider read from a dbase file defined by the dbase parameter
131         * @throws Exception
132         */
133        private static List<String> getFileList( String dBaseFile, String fileColumn, String baseDir )
134                                throws Exception {
135    
136            // handle dbase file extension and file location/reading problems
137            if ( dBaseFile.endsWith( ".dbf" ) ) {
138                dBaseFile = dBaseFile.substring( 0, dBaseFile.lastIndexOf( "." ) );
139            }
140            DBaseFile dbf = new DBaseFile( dBaseFile );
141    
142            // sort dbase file contents chronologicaly (oldest first)
143            int cnt = dbf.getRecordNum();
144    
145            Object[] mapItems = new Object[cnt];
146            QualifiedName fileC = new QualifiedName( APP_PREFIX, fileColumn.toUpperCase(), DEEGREEAPP );
147    
148            for ( int i = 0; i < cnt; i++ ) {
149                // name of map file
150                mapItems[i] = dbf.getFRow( i + 1 ).getDefaultProperty( fileC ).getValue();
151            }
152    
153            // extract names of image files from dBase file and attach them to rootDir
154            if ( baseDir == null ) {
155                baseDir = "";
156            } else if ( !baseDir.endsWith( "/" ) && !baseDir.endsWith( "\\" ) ) {
157                baseDir = baseDir + '/';
158            }
159            List<String> imageFiles = new ArrayList<String>( mapItems.length );
160            for ( int i = 0; i < mapItems.length; i++ ) {
161                if ( mapItems[i] != null ) {
162                    imageFiles.add( baseDir + mapItems[i] );
163                }
164            }
165    
166            return imageFiles;
167        }
168    
169        /**
170         * returns the list of image map files to consider read from a defined root directory.
171         *
172         * @param rootDir
173         *            root directory where to read image map files
174         * @param subdirs
175         *            true if subdirectories of the root directory shall be parsed for image maps too
176         * @return the list of image map files to consider read from a defined root directory.
177         */
178        private static List<String> getFileList( String rootDir, boolean subdirs ) {
179            List<String> list = new ArrayList<String>( 10000 );
180            File file = new File( rootDir );
181            List<String> extensions = new ArrayList<String>();
182            extensions.add( "JPEG" );
183            extensions.add( "JPG" );
184            extensions.add( "BMP" );
185            extensions.add( "PNG" );
186            extensions.add( "GIF" );
187            extensions.add( "TIF" );
188            extensions.add( "TIFF" );
189            extensions.add( "GEOTIFF" );
190            ConvenienceFileFilter cff = new ConvenienceFileFilter( extensions, true );
191            String[] entries = file.list( cff );
192            if ( entries != null ) {
193                for ( int i = 0; i < entries.length; i++ ) {
194                    File entry = new File( rootDir + '/' + entries[i] );
195                    if ( entry.isDirectory() && subdirs ) {
196                        list = readSubDirs( entry, list, cff );
197                    } else {
198                        list.add( rootDir + '/' + entries[i] );
199                    }
200                }
201            }
202            return list;
203        }
204    
205        /**
206         *
207         * @param file
208         * @param list
209         * @return a list of strings
210         */
211        private static List<String> readSubDirs( File file, List<String> list, ConvenienceFileFilter cff ) {
212    
213            String[] entries = file.list( cff );
214            if ( entries != null ) {
215                for ( int i = 0; i < entries.length; i++ ) {
216                    File entry = new File( file.getAbsolutePath() + '/' + entries[i] );
217                    if ( entry.isDirectory() ) {
218                        list = readSubDirs( entry, list, cff );
219                    } else {
220                        list.add( file.getAbsolutePath() + '/' + entries[i] );
221                    }
222                }
223            }
224            return list;
225        }
226    
227        /**
228         *
229         * @throws Exception
230         */
231        public void process()
232                                throws Exception {
233            for ( int i = 0; i < fileList.size(); i++ ) {
234                System.out.print( fileList.get( i ) + "\r" );
235                File file = new File( fileList.get( i ) );
236                BufferedImage image = ImageUtils.loadImage( file );
237                WorldFile wf = WorldFile.readWorldFile( fileList.get( i ), WorldFile.TYPE.CENTER, image.getWidth(),
238                                                        image.getHeight() );
239                float qx = (float) ( wf.getResx() / resolution );
240                float qy = (float) ( wf.getResy() / resolution );
241    
242                ParameterBlock pb = new ParameterBlock();
243                pb.addSource( image );
244                pb.add( qx ); // The xScale
245                pb.add( qy ); // The yScale
246                pb.add( 0.0F ); // The x translation
247                pb.add( 0.0F ); // The y translation
248                pb.add( interpolation ); // The interpolation
249                // Create the scale operation
250                RenderedOp ro = JAI.create( "scale", pb, null );
251                try {
252                    image = ro.getAsBufferedImage();
253                } catch ( Exception e ) {
254                    e.printStackTrace();
255                }
256    
257                wf = new WorldFile( resolution, resolution, 0, 0, wf.getEnvelope() );
258                int p = file.getName().lastIndexOf( '.' );
259                String fileBaseName = file.getName().substring( 0, p );
260                ImageUtils.saveImage( image, outDir + fileBaseName + '.' + format, 1 );
261                WorldFile.writeWorldFile( wf, outDir + fileBaseName );
262                System.gc();
263            }
264        }
265    
266        private static void printHelp() {
267            System.out.println();
268            System.out.println( "Parameter description for RasterSplitter:" );
269            System.out.println( "-res : desired raster resolution" );
270            System.out.println( "-format : desired image format of result images (mandatory)" );
271            System.out.println( "-outDir : directory where result images shall be stored (mandatory)" );
272    
273            System.out.println( "-rootDir : directory from where images to split will be read (mandatory)" );
274            System.out.println( "-subDirs : (true|false). If 'true' all sub directories of the 'rootDir' " );
275            System.out.println( "            will be searched for images too (optional; default = false)" );
276        }
277    
278        private static boolean validate( Properties map ) {
279            if ( map.getProperty( "-res" ) == null ) {
280                System.out.println( "-res must be set!" );
281                return false;
282            }
283            if ( map.getProperty( "-format" ) == null ) {
284                System.out.println( "-format must be set!" );
285                return false;
286            }
287            if ( map.getProperty( "-outDir" ) == null ) {
288                System.out.println( "-outDir must be set!" );
289                return false;
290            }
291            if ( map.getProperty( "-rootDir" ) == null ) {
292                System.out.println( "-rootDir must be set!" );
293                return false;
294            }
295            if ( map.getProperty( "-subDirs" ) != null && !"true".equals( map.getProperty( "-subDirs" ) )
296                 && !"false".equals( map.getProperty( "-subDirs" ) ) ) {
297                System.out.println( "if -subDirs is set it must be true or false!" );
298                return false;
299            }
300            return true;
301        }
302    
303        /**
304         * @param args
305         * @throws Exception
306         */
307        public static void main( String[] args )
308                                throws Exception {
309            Properties map = new Properties();
310            for ( int i = 0; i < args.length; i += 2 ) {
311                map.put( args[i], args[i + 1] );
312            }
313            if ( !validate( map ) ) {
314                printHelp();
315                return;
316            }
317    
318            String format = map.getProperty( "-format" );
319            String outDir = map.getProperty( "-outDir" );
320            double res = Double.parseDouble( map.getProperty( "-res" ) );
321            Rescaler rescaler = null;
322            if ( map.get( "-dbaseFile" ) != null ) {
323                String dBaseFile = map.getProperty( "-dbaseFile" );
324                String fileColum = map.getProperty( "-fileColumn" );
325                String baseDir = map.getProperty( "-baseDir" );
326                if ( baseDir == null ) {
327                    baseDir = map.getProperty( "-rootDir" );
328                }
329                rescaler = new Rescaler( res, baseDir, outDir, dBaseFile, format, fileColum );
330            } else if ( map.get( "-rootDir" ) != null ) {
331                String rootDir = map.getProperty( "-rootDir" );
332                boolean subDirs = "true".equals( map.get( "-subDirs" ) );
333                rescaler = new Rescaler( res, rootDir, outDir, format, subDirs );
334            } else {
335                LOG.logInfo( map.toString() );
336                System.out.println( "-rootDir or -dbaseFile parameter must be defined" );
337                return;
338            }
339            rescaler.process();
340    
341        }
342    
343    }