001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/tools/raster/RasterSplitter.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.image.BufferedImage;
039 import java.io.File;
040 import java.io.FilenameFilter;
041 import java.net.URI;
042 import java.util.ArrayList;
043 import java.util.List;
044 import java.util.Properties;
045
046 import javax.media.jai.TiledImage;
047
048 import org.deegree.datatypes.QualifiedName;
049 import org.deegree.framework.log.ILogger;
050 import org.deegree.framework.log.LoggerFactory;
051 import org.deegree.framework.util.ImageUtils;
052 import org.deegree.framework.util.StringTools;
053 import org.deegree.io.dbaseapi.DBaseFile;
054 import org.deegree.model.coverage.grid.WorldFile;
055 import org.deegree.model.spatialschema.Envelope;
056 import org.deegree.model.spatialschema.GeometryFactory;
057 import org.deegree.ogcbase.CommonNamespaces;
058
059 /**
060 *
061 *
062 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
063 * @author last edited by: $Author: mschneider $
064 *
065 * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
066 */
067 public class RasterSplitter {
068
069 private static final ILogger LOG = LoggerFactory.getLogger( RasterSplitter.class );
070
071 private static final URI DEEGREEAPP = CommonNamespaces.buildNSURI( "http://www.deegree.org/app" );
072
073 private static final String APP_PREFIX = "app";
074
075 private String outDir;
076
077 private int tileWidth = 0;
078
079 private int tileHeight = 0;
080
081 private String format;
082
083 private List<String> fileList;
084
085 /**
086 *
087 * @param rootDir
088 * @param outDir
089 * @param tileWidth
090 * @param tileHeight
091 * @param format
092 * @param subDirs
093 */
094 RasterSplitter( String rootDir, String outDir, int tileWidth, int tileHeight, String format, boolean subDirs ) {
095 this.outDir = outDir;
096 this.format = format;
097 this.tileWidth = tileWidth;
098 this.tileHeight = tileHeight;
099 fileList = getFileList( rootDir, subDirs );
100 }
101
102 /**
103 * @param rootDir
104 * @param outDir
105 * @param tileWidth
106 * @param tileHeight
107 * @param dBase
108 * @param format
109 * @param fileColumn
110 * @throws Exception
111 */
112 RasterSplitter( String rootDir, String outDir, int tileWidth, int tileHeight, String dBase, String format,
113 String fileColumn ) throws Exception {
114
115 this.outDir = outDir;
116 this.format = format;
117 this.tileWidth = tileWidth;
118 this.tileHeight = tileHeight;
119 fileList = getFileList( dBase, fileColumn, rootDir );
120 }
121
122 /**
123 * splits all files identified by the root dir or dbase file
124 *
125 * @throws Exception
126 */
127 public void perform()
128 throws Exception {
129 for ( int i = 0; i < fileList.size(); i++ ) {
130 System.out.print( "processing: " + fileList.get( i ) );
131 splitFile( fileList.get( i ) );
132 }
133 }
134
135 /**
136 * returns the list of image map files to consider read from a dbase file defined by the dbase
137 * parameter
138 *
139 * @param dbaseFile
140 * name of the dbase file
141 * @param fileColumn
142 * name of the column containing the image map files names
143 * @param baseDir
144 * name of the directory where the image map files are stored if this parameter is
145 * <code>null</code> it is assumed that the image map files are full referenced
146 * within the dbase
147 * @return the list of image map files to consider read from a dbase file defined by the dbase
148 * parameter
149 * @throws Exception
150 */
151 private static List<String> getFileList( String dBaseFile, String fileColumn, String baseDir )
152 throws Exception {
153
154 System.out.println( "reading file list ..." );
155
156 // handle dbase file extension and file location/reading problems
157 if ( dBaseFile.endsWith( ".dbf" ) ) {
158 dBaseFile = dBaseFile.substring( 0, dBaseFile.lastIndexOf( "." ) );
159 }
160 DBaseFile dbf = new DBaseFile( dBaseFile );
161
162 // sort dbase file contents chronologicaly (oldest first)
163 int cnt = dbf.getRecordNum();
164
165 Object[] mapItems = new Object[cnt];
166 QualifiedName fileC = new QualifiedName( APP_PREFIX, fileColumn.toUpperCase(), DEEGREEAPP );
167
168 for ( int i = 0; i < cnt; i++ ) {
169 // name of map file
170 mapItems[i] = dbf.getFRow( i + 1 ).getDefaultProperty( fileC ).getValue();
171 }
172
173 // extract names of image files from dBase file and attach them to rootDir
174 if ( baseDir == null ) {
175 baseDir = "";
176 } else if ( !baseDir.endsWith( "/" ) && !baseDir.endsWith( "\\" ) ) {
177 baseDir = baseDir + '/';
178 }
179 List<String> imageFiles = new ArrayList<String>( mapItems.length );
180 for ( int i = 0; i < mapItems.length; i++ ) {
181 if ( mapItems[i] != null ) {
182 imageFiles.add( baseDir + mapItems[i] );
183 }
184 }
185
186 return imageFiles;
187 }
188
189 /**
190 * returns the list of image map files to consider read from a defined root directory.
191 *
192 * @param rootDir
193 * root directory where to read image map files
194 * @param subdirs
195 * true if subdirectories of the root directory shall be parsed for image maps too
196 * @return the list of image map files to consider read from a defined root directory.
197 */
198 private static List<String> getFileList( String rootDir, boolean subdirs ) {
199 System.out.println( "reading file list ..." );
200 List<String> list = new ArrayList<String>( 10000 );
201 File file = new File( rootDir );
202 String[] entries = file.list( new DFileFilter() );
203 if ( entries != null ) {
204 for ( int i = 0; i < entries.length; i++ ) {
205 File entry = new File( rootDir + '/' + entries[i] );
206 if ( entry.isDirectory() && subdirs ) {
207 list = readSubDirs( entry, list );
208 } else {
209 list.add( rootDir + '/' + entries[i] );
210 }
211 }
212 }
213 return list;
214 }
215
216 /**
217 *
218 * @param file
219 * @param list
220 * @return a list of strings
221 */
222 private static List<String> readSubDirs( File file, List<String> list ) {
223
224 String[] entries = file.list( new DFileFilter() );
225 if ( entries != null ) {
226 for ( int i = 0; i < entries.length; i++ ) {
227 File entry = new File( file.getAbsolutePath() + '/' + entries[i] );
228 if ( entry.isDirectory() ) {
229 list = readSubDirs( entry, list );
230 } else {
231 list.add( file.getAbsolutePath() + '/' + entries[i] );
232 }
233 }
234 }
235 return list;
236 }
237
238 private void splitFile( String inFile )
239 throws Exception {
240
241 System.out.println( "processing: " + inFile );
242 BufferedImage bi = ImageUtils.loadImage( inFile );
243 WorldFile wf = WorldFile.readWorldFile( inFile, WorldFile.TYPE.CENTER, bi.getWidth(), bi.getHeight() );
244 TiledImage ti = new TiledImage( bi, tileWidth, tileHeight );
245
246 int cntx = bi.getWidth() / tileWidth;
247 if ( cntx * tileWidth < bi.getWidth() ) {
248 cntx++;
249 }
250 int cnty = bi.getHeight() / tileHeight;
251 if ( cnty * tileHeight < bi.getHeight() ) {
252 cnty++;
253 }
254
255 int p = inFile.lastIndexOf( '/' );
256 String base = inFile.substring( p + 1, inFile.length() );
257 base = StringTools.replace( base, ".", "_", true );
258
259 double res = wf.getResx();
260 Envelope env = wf.getEnvelope();
261 for ( int i = 0; i < cntx; i++ ) {
262 for ( int j = 0; j < cnty; j++ ) {
263 String s = StringTools.concat( 200, "processing tile: ", i, ' ', j, " of ", cntx, '/', cnty, "\r" );
264 System.out.print( s );
265 System.gc();
266 int w = tileWidth;
267 int h = tileHeight;
268 if ( i * tileWidth + tileWidth > bi.getWidth() ) {
269 w = bi.getWidth() - i * tileWidth;
270 }
271 if ( i * tileHeight + tileHeight > bi.getHeight() ) {
272 h = bi.getHeight() - i * tileHeight;
273 }
274 if ( w > 0 && h > 0 ) {
275 BufferedImage sub = ti.getSubImage( i * tileWidth, j * tileHeight, w, h ).getAsBufferedImage();
276 double x1 = env.getMin().getX() + i * tileWidth * res;
277 double y1 = env.getMax().getY() - ( j + 1 ) * tileHeight * res;
278 double x2 = env.getMin().getX() + ( i + 1 ) * tileWidth * res;
279 double y2 = env.getMax().getY() - j * tileHeight * res;
280 ;
281 Envelope subEnv = GeometryFactory.createEnvelope( x1, y1, x2, y2, null );
282 WorldFile subWf = new WorldFile( res, res, 0, 0, subEnv );
283 s = StringTools.concat( 300, outDir, '/', base, '_', i, '_', j, '.', format );
284 ImageUtils.saveImage( sub, s, 1 );
285 s = StringTools.concat( 300, outDir, '/', base, '_', i, '_', j );
286 WorldFile.writeWorldFile( subWf, s );
287 }
288 }
289 }
290 bi = null;
291 System.gc();
292 }
293
294 private static void printHelp() {
295 System.out.println();
296 System.out.println( "Parameter description for RasterSplitter:" );
297 System.out.println( "-tileWidth : desired width of result images (mandatory)" );
298 System.out.println( "-tileHeight : desired width of result images (mandatory)" );
299 System.out.println( "-format : desired image format of result images (mandatory)" );
300 System.out.println( "-outDir : directory where result images shall be stored (mandatory)" );
301
302 System.out.println( "-rootDir : directory from where images to split will be read (mandatory)" );
303 System.out.println( "-subDirs : (true|false). If 'true' all sub directories of the 'rootDir' " );
304 System.out.println( " will be searched for images too (optional; default = false)" );
305 }
306
307 private static boolean validate( Properties map ) {
308 if ( map.getProperty( "-tileWidth" ) == null ) {
309 System.out.println( "-tileWidth must be set!" );
310 return false;
311 }
312 if ( map.getProperty( "-tileHeight" ) == null ) {
313 System.out.println( "-tileHeight must be set!" );
314 return false;
315 }
316 if ( map.getProperty( "-format" ) == null ) {
317 System.out.println( "-format must be set!" );
318 return false;
319 }
320 if ( map.getProperty( "-outDir" ) == null ) {
321 System.out.println( "-outDir must be set!" );
322 return false;
323 }
324 if ( map.getProperty( "-rootDir" ) == null ) {
325 System.out.println( "-rootDir must be set!" );
326 return false;
327 }
328 if ( map.getProperty( "-subDirs" ) != null && !"true".equals( map.getProperty( "-subDirs" ) )
329 && !"false".equals( map.getProperty( "-subDirs" ) ) ) {
330 System.out.println( "if -subDirs is set it must be true or false!" );
331 return false;
332 }
333 return true;
334 }
335
336 /**
337 *
338 * @param args
339 * @throws Exception
340 */
341 public static void main( String[] args )
342 throws Exception {
343
344 Properties map = new Properties();
345 for ( int i = 0; i < args.length; i += 2 ) {
346 map.put( args[i], args[i + 1] );
347 }
348 if ( !validate( map ) ) {
349 printHelp();
350 return;
351 }
352
353 int tileWidth = Integer.parseInt( map.getProperty( "-tileWidth" ) );
354 int tileHeight = Integer.parseInt( map.getProperty( "-tileHeight" ) );
355 String format = map.getProperty( "-format" );
356 String outDir = map.getProperty( "-outDir" );
357
358 RasterSplitter rs = null;
359 if ( map.get( "-dbaseFile" ) != null ) {
360 String dBaseFile = map.getProperty( "-dbaseFile" );
361 String fileColum = map.getProperty( "-fileColumn" );
362 String baseDir = map.getProperty( "-baseDir" );
363 if ( baseDir == null ) {
364 baseDir = map.getProperty( "-rootDir" );
365 }
366 rs = new RasterSplitter( baseDir, outDir, tileWidth, tileHeight, dBaseFile, format, fileColum );
367 } else if ( map.get( "-rootDir" ) != null ) {
368 String rootDir = map.getProperty( "-rootDir" );
369 boolean subDirs = "true".equals( map.get( "-subDirs" ) );
370 rs = new RasterSplitter( rootDir, outDir, tileWidth, tileHeight, format, subDirs );
371
372 } else {
373 LOG.logInfo( map.toString() );
374 System.out.println( "-rootDir or -dbaseFile parameter must be defined" );
375 return;
376 }
377 rs.perform();
378 }
379
380 /**
381 * class: official version of a FilenameFilter
382 */
383 static class DFileFilter implements FilenameFilter {
384
385 private List<String> extensions = null;
386
387 /**
388 *
389 */
390 public DFileFilter() {
391 extensions = new ArrayList<String>();
392 extensions.add( "JPEG" );
393 extensions.add( "JPG" );
394 extensions.add( "BMP" );
395 extensions.add( "PNG" );
396 extensions.add( "GIF" );
397 extensions.add( "TIF" );
398 extensions.add( "TIFF" );
399 extensions.add( "GEOTIFF" );
400 }
401
402 /**
403 * @return the String "*.*"
404 */
405 public String getDescription() {
406 return "*.*";
407 }
408
409 /*
410 * (non-Javadoc)
411 *
412 * @see java.io.FilenameFilter#accept(java.io.File, java.lang.String)
413 */
414 public boolean accept( java.io.File file, String name ) {
415 int pos = name.lastIndexOf( "." );
416 String ext = name.substring( pos + 1 ).toUpperCase();
417 if ( file.isDirectory() ) {
418 String s = file.getAbsolutePath() + '/' + name;
419 File tmp = new File( s );
420 if ( tmp.isDirectory() ) {
421 return true;
422 }
423 }
424 return extensions.contains( ext );
425 }
426 }
427 }