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 }