001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_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 }