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