001    //$HeadURL$
002    /*----------------    FILE HEADER  ------------------------------------------
003     This file is part of deegree.
004     Copyright (C) 2001-2008 by:
005     Department of Geography, University of Bonn
006     http://www.giub.uni-bonn.de/deegree/
007     lat/lon GmbH
008     http://www.lat-lon.de
009    
010     This library is free software; you can redistribute it and/or
011     modify it under the terms of the GNU Lesser General Public
012     License as published by the Free Software Foundation; either
013     version 2.1 of the License, or (at your option) any later version.
014     This library is distributed in the hope that it will be useful,
015     but WITHOUT ANY WARRANTY; without even the implied warranty of
016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017     Lesser General Public License for more details.
018     You should have received a copy of the GNU Lesser General Public
019     License along with this library; if not, write to the Free Software
020     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
021     Contact:
022    
023     Andreas Poth
024     lat/lon GmbH
025     Aennchenstr. 19
026     53177 Bonn
027     Germany
028     E-Mail: poth@lat-lon.de
029    
030     Prof. Dr. Klaus Greve
031     Department of Geography
032     University of Bonn
033     Meckenheimer Allee 166
034     53115 Bonn
035     Germany
036     E-Mail: greve@giub.uni-bonn.de
037     ---------------------------------------------------------------------------*/
038    
039    package org.deegree.tools.raster;
040    
041    import java.awt.image.BufferedImage;
042    import java.awt.image.renderable.ParameterBlock;
043    import java.io.File;
044    import java.net.URI;
045    import java.util.ArrayList;
046    import java.util.List;
047    import java.util.Properties;
048    
049    import javax.media.jai.Interpolation;
050    import javax.media.jai.InterpolationBilinear;
051    import javax.media.jai.JAI;
052    import javax.media.jai.RenderedOp;
053    
054    import org.deegree.datatypes.QualifiedName;
055    import org.deegree.framework.log.ILogger;
056    import org.deegree.framework.log.LoggerFactory;
057    import org.deegree.framework.util.ConvenienceFileFilter;
058    import org.deegree.framework.util.ImageUtils;
059    import org.deegree.io.dbaseapi.DBaseFile;
060    import org.deegree.model.coverage.grid.WorldFile;
061    import org.deegree.ogcbase.CommonNamespaces;
062    
063    /**
064     * 
065     * 
066     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
067     * @author last edited by: $Author: poth $
068     * 
069     * @version. $Revision: 6251 $, $Date: 2007-03-19 16:59:28 +0100 (Mo, 19 Mrz 2007) $
070     */
071    public class Rescaler {
072    
073        private static final ILogger LOG = LoggerFactory.getLogger( Rescaler.class );
074    
075        private static final URI DEEGREEAPP = CommonNamespaces.buildNSURI( "http://www.deegree.org/app" );
076    
077        private static final String APP_PREFIX = "app";
078    
079        private String outDir;
080    
081        private String format;
082        
083        private Interpolation interpolation = new InterpolationBilinear();
084    
085        private List<String> fileList;
086    
087        private double resolution = 0;
088    
089        /**
090         * 
091         * @param resolution
092         * @param rootDir
093         * @param outDir
094         * @param format
095         * @param subDirs
096         */
097        Rescaler( double resolution, String rootDir, String outDir, String format, boolean subDirs ) {
098            this.resolution = resolution;
099            this.outDir = outDir;
100            this.format = format;
101            fileList = getFileList( rootDir, subDirs );
102        }
103    
104        /**
105         * 
106         * @param resolution
107         * @param rootDir
108         * @param outDir
109         * @param dBase
110         * @param format
111         * @param fileColumn
112         * @throws Exception
113         */
114        Rescaler( double resolution, String rootDir, String outDir, String dBase, String format, String fileColumn )
115                                throws Exception {
116            this.resolution = resolution;
117            this.outDir = outDir;
118            this.format = format;
119            fileList = getFileList( dBase, fileColumn, rootDir );
120        }
121    
122        /**
123         * returns the list of image map files to consider read from a dbase file defined by the dbase
124         * parameter
125         * 
126         * @param dbaseFile
127         *            name of the dbase file
128         * @param fileColumn
129         *            name of the column containing the image map files names
130         * @param baseDir
131         *            name of the directory where the image map files are stored if this parameter is
132         *            <code>null</code> it is assumed that the image map files are full referenced
133         *            within the dbase
134         * @return the list of image map files to consider read from a dbase file defined by the dbase
135         *         parameter
136         * @throws Exception
137         */
138        private static List<String> getFileList( String dBaseFile, String fileColumn, String baseDir )
139                                throws Exception {
140    
141            // handle dbase file extension and file location/reading problems
142            if ( dBaseFile.endsWith( ".dbf" ) ) {
143                dBaseFile = dBaseFile.substring( 0, dBaseFile.lastIndexOf( "." ) );
144            }
145            DBaseFile dbf = new DBaseFile( dBaseFile );
146    
147            // sort dbase file contents chronologicaly (oldest first)
148            int cnt = dbf.getRecordNum();
149    
150            Object[] mapItems = new Object[cnt];
151            QualifiedName fileC = new QualifiedName( APP_PREFIX, fileColumn.toUpperCase(), DEEGREEAPP );
152    
153            for ( int i = 0; i < cnt; i++ ) {
154                // name of map file
155                mapItems[i] = dbf.getFRow( i + 1 ).getDefaultProperty( fileC ).getValue();
156            }
157    
158            // extract names of image files from dBase file and attach them to rootDir
159            if ( baseDir == null ) {
160                baseDir = "";
161            } else if ( !baseDir.endsWith( "/" ) && !baseDir.endsWith( "\\" ) ) {
162                baseDir = baseDir + '/';
163            }
164            List<String> imageFiles = new ArrayList<String>( mapItems.length );
165            for ( int i = 0; i < mapItems.length; i++ ) {
166                if ( mapItems[i] != null ) {
167                    imageFiles.add( baseDir + mapItems[i] );
168                }
169            }
170    
171            return imageFiles;
172        }
173    
174        /**
175         * returns the list of image map files to consider read from a defined root directory.
176         * 
177         * @param rootDir
178         *            root directory where to read image map files
179         * @param subdirs
180         *            true if subdirectories of the root directory shall be parsed for image maps too
181         * @return the list of image map files to consider read from a defined root directory.
182         */
183        private static List<String> getFileList( String rootDir, boolean subdirs ) {
184            List<String> list = new ArrayList<String>( 10000 );
185            File file = new File( rootDir );
186            List<String> extensions = new ArrayList<String>();
187            extensions.add( "JPEG" );
188            extensions.add( "JPG" );
189            extensions.add( "BMP" );
190            extensions.add( "PNG" );
191            extensions.add( "GIF" );
192            extensions.add( "TIF" );
193            extensions.add( "TIFF" );
194            extensions.add( "GEOTIFF" );
195            ConvenienceFileFilter cff = new ConvenienceFileFilter( extensions, true );
196            String[] entries = file.list( cff );
197            if ( entries != null ) {
198                for ( int i = 0; i < entries.length; i++ ) {
199                    File entry = new File( rootDir + '/' + entries[i] );
200                    if ( entry.isDirectory() && subdirs ) {
201                        list = readSubDirs( entry, list, cff );
202                    } else {
203                        list.add( rootDir + '/' + entries[i] );
204                    }
205                }
206            }
207            return list;
208        }
209    
210        /**
211         * 
212         * @param file
213         * @param list
214         * @return
215         */
216        private static List<String> readSubDirs( File file, List<String> list, ConvenienceFileFilter cff ) {
217    
218            String[] entries = file.list( cff );
219            if ( entries != null ) {
220                for ( int i = 0; i < entries.length; i++ ) {
221                    File entry = new File( file.getAbsolutePath() + '/' + entries[i] );
222                    if ( entry.isDirectory() ) {
223                        list = readSubDirs( entry, list, cff );
224                    } else {
225                        list.add( file.getAbsolutePath() + '/' + entries[i] );
226                    }
227                }
228            }
229            return list;
230        }
231    
232        /**
233         * 
234         * @throws Exception
235         */
236        public void process()
237                                throws Exception {
238            for ( int i = 0; i < fileList.size(); i++ ) {
239                System.out.print( fileList.get( i ) + "\r" );
240                File file = new File( fileList.get( i ) );
241                BufferedImage image = ImageUtils.loadImage( file );
242                WorldFile wf = WorldFile.readWorldFile( fileList.get( i ), WorldFile.TYPE.CENTER, image.getWidth(),
243                                                        image.getHeight() );
244                float qx = (float)(wf.getResx()/resolution);
245                float qy = (float)(wf.getResy()/resolution);
246                
247                ParameterBlock pb = new ParameterBlock();
248                pb.addSource( image );
249                pb.add( qx ); // The xScale
250                pb.add( qy ); // The yScale
251                pb.add( 0.0F ); // The x translation
252                pb.add( 0.0F ); // The y translation
253                pb.add( interpolation ); // The interpolation
254                // Create the scale operation
255                RenderedOp ro = JAI.create( "scale", pb, null );
256                try {
257                    image = ro.getAsBufferedImage();
258                } catch ( Exception e ) {
259                    e.printStackTrace();            
260                }
261                
262                wf = new WorldFile( resolution, resolution, 0, 0, wf.getEnvelope() );
263                int p = file.getName().lastIndexOf( '.' );
264                String fileBaseName = file.getName().substring( 0, p );
265                ImageUtils.saveImage( image, outDir + fileBaseName + '.' + format, 1 );            
266                WorldFile.writeWorldFile( wf, outDir + fileBaseName );
267                System.gc();
268            }
269        }
270    
271        private static void printHelp() {
272            System.out.println();
273            System.out.println( "Parameter description for RasterSplitter:" );
274            System.out.println( "-res : desired raster resolution" );
275            System.out.println( "-format : desired image format of result images (mandatory)" );
276            System.out.println( "-outDir : directory where result images shall be stored (mandatory)" );
277    
278            System.out.println( "-rootDir : directory from where images to split will be read (mandatory)" );
279            System.out.println( "-subDirs : (true|false). If 'true' all sub directories of the 'rootDir' " );
280            System.out.println( "            will be searched for images too (optional; default = false)" );
281        }
282    
283        private static boolean validate( Properties map ) {
284            if ( map.getProperty( "-res" ) == null ) {
285                System.out.println( "-res must be set!" );
286                return false;
287            }
288            if ( map.getProperty( "-format" ) == null ) {
289                System.out.println( "-format must be set!" );
290                return false;
291            }
292            if ( map.getProperty( "-outDir" ) == null ) {
293                System.out.println( "-outDir must be set!" );
294                return false;
295            }
296            if ( map.getProperty( "-rootDir" ) == null ) {
297                System.out.println( "-rootDir must be set!" );
298                return false;
299            }
300            if ( map.getProperty( "-subDirs" ) != null && !"true".equals( map.getProperty( "-subDirs" ) )
301                 && !"false".equals( map.getProperty( "-subDirs" ) ) ) {
302                System.out.println( "if -subDirs is set it must be true or false!" );
303                return false;
304            }
305            return true;
306        }
307    
308        /**
309         * @param args
310         * @throws Exception 
311         */
312        public static void main( String[] args ) throws Exception {
313            Properties map = new Properties();
314            for ( int i = 0; i < args.length; i += 2 ) {
315                map.put( args[i], args[i + 1] );
316            }
317            if ( !validate( map ) ) {
318                printHelp();
319                return;
320            }
321    
322            String format = map.getProperty( "-format" );
323            String outDir = map.getProperty( "-outDir" );
324            double res = Double.parseDouble( map.getProperty( "-res" ) );
325            Rescaler rescaler = null;
326            if ( map.get( "-dbaseFile" ) != null ) {
327                String dBaseFile = map.getProperty( "-dbaseFile" );
328                String fileColum = map.getProperty( "-fileColumn" );
329                String baseDir = map.getProperty( "-baseDir" );
330                if ( baseDir == null ) {
331                    baseDir = map.getProperty( "-rootDir" );
332                }
333                rescaler = new Rescaler( res, baseDir, outDir, dBaseFile, format, fileColum );
334            } else if ( map.get( "-rootDir" ) != null ) {
335                String rootDir = map.getProperty( "-rootDir" );
336                boolean subDirs = "true".equals( map.get( "-subDirs" ) );
337                rescaler = new Rescaler( res, rootDir, outDir, format, subDirs );
338            } else {
339                LOG.logInfo( map.toString() );
340                System.out.println( "-rootDir or -dbaseFile parameter must be defined" );
341                return;
342            }
343            rescaler.process();
344    
345        }
346    
347    }