001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/model/coverage/grid/WorldFile.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 Aennchenstraße 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.model.coverage.grid; 044 045 import java.awt.image.BufferedImage; 046 import java.io.BufferedReader; 047 import java.io.File; 048 import java.io.FileReader; 049 import java.io.FileWriter; 050 import java.io.IOException; 051 import java.io.PrintWriter; 052 053 import javax.media.jai.JAI; 054 import javax.media.jai.RenderedOp; 055 056 import org.deegree.framework.log.ILogger; 057 import org.deegree.framework.log.LoggerFactory; 058 import org.deegree.model.spatialschema.Envelope; 059 import org.deegree.model.spatialschema.GeometryFactory; 060 061 import com.sun.media.jai.codec.FileSeekableStream; 062 063 /** 064 * class representation of a ESRI world file. A world file may defines bounding coordinates centered 065 * on the outter pixel (e.g. ESRI software) or outside the bounding pixels (e.g.Oracle spatial). 066 * Reading a worldfile this must be considered so the type of a worldfile must be passed. For this a 067 * <code>enum</code> named <code>TYPE</code> ist defined. 068 * 069 * 070 * @version $Revision: 9343 $ 071 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 072 * @author last edited by: $Author: apoth $ 073 * 074 * @version $Revision: 9343 $, $Date: 2007-12-27 14:30:32 +0100 (Do, 27 Dez 2007) $ 075 */ 076 public class WorldFile { 077 078 private static ILogger LOG = LoggerFactory.getLogger( WorldFile.class ); 079 080 private double resx; 081 082 private double resy; 083 084 private double rotation1; 085 086 private double rotation2; 087 088 private Envelope envelope; 089 090 /** 091 * <code>TYPE</code> enumerates the world file types. 092 * 093 * @author <a href="mailto:schmitz@lat-lon.de">Andreas Schmitz</a> 094 * @author last edited by: $Author: apoth $ 095 * 096 * @version $Revision: 9343 $, $Date: 2007-12-27 14:30:32 +0100 (Do, 27 Dez 2007) $ 097 */ 098 public enum TYPE { 099 100 /** 101 * Coordinates denote pixel centers. 102 */ 103 CENTER, 104 105 /** 106 * Coordinates denote outer edges. 107 */ 108 OUTER 109 110 } 111 112 /** 113 * @return a class represention of a ESRI world file 114 * @param filename 115 * name of the image/raster file inclusing path and extension 116 * @param type 117 * @throws IOException 118 */ 119 public static WorldFile readWorldFile( String filename, TYPE type ) 120 throws IOException { 121 122 FileSeekableStream fss = new FileSeekableStream( filename ); 123 RenderedOp rop = JAI.create( "stream", fss ); 124 int iw = ( (Integer) rop.getProperty( "image_width" ) ).intValue(); 125 int ih = ( (Integer) rop.getProperty( "image_height" ) ).intValue(); 126 127 return readWorldFile( filename, type, iw, ih ); 128 129 } 130 131 /** 132 * @param name 133 * @return true, if the name ends with .tfw, .wld, .jgw, .gfw, .gifw, .pgw or .pngw. 134 */ 135 public static boolean hasWorldfileSuffix( String name ) { 136 String lname = name.toLowerCase(); 137 return lname.endsWith( ".tfw" ) || lname.endsWith( ".wld" ) || lname.endsWith( ".jgw" ) 138 || lname.endsWith( ".gfw" ) || lname.endsWith( ".gifw" ) || lname.endsWith( ".pgw" ) 139 || lname.endsWith( ".pngw" ); 140 } 141 142 /** 143 * @return a class represention of a ESRI world file 144 * @param filename 145 * name of the image/raster file inclusing path and extension 146 * @param type 147 * @param width 148 * image width in pixel 149 * @param height 150 * image height in pixel 151 * @throws IOException 152 */ 153 public static WorldFile readWorldFile( String filename, TYPE type, int width, int height ) 154 throws IOException { 155 // Gets the substring beginning at the specified beginIndex (0) - the beginning index, 156 // inclusive - and extends to the character at index endIndex (position of '.') - the 157 // ending index, exclusive. 158 159 String fname = null; 160 int pos = filename.lastIndexOf( "." ); 161 filename = filename.substring( 0, pos ); 162 163 // Look for corresponding worldfiles. 164 if ( ( new File( filename + ".tfw" ) ).exists() ) { 165 fname = filename + ".tfw"; 166 } else if ( ( new File( filename + ".wld" ) ).exists() ) { 167 fname = filename + ".wld"; 168 } else if ( ( new File( filename + ".jgw" ) ).exists() ) { 169 fname = filename + ".jgw"; 170 } else if ( ( new File( filename + ".jpgw" ) ).exists() ) { 171 fname = filename + ".jpgw"; 172 } else if ( ( new File( filename + ".gfw" ) ).exists() ) { 173 fname = filename + ".gfw"; 174 } else if ( ( new File( filename + ".gifw" ) ).exists() ) { 175 fname = filename + ".gifw"; 176 } else if ( ( new File( filename + ".pgw" ) ).exists() ) { 177 fname = filename + ".pgw"; 178 } else if ( ( new File( filename + ".pngw" ) ).exists() ) { 179 fname = filename + ".pngw"; 180 } else { 181 throw new IOException( "Not a world file for: " + filename ); 182 } 183 184 // Reads character files. 185 // The constructors of this class (FileReader) assume that the default character 186 // encoding and the default byte-buffer size are appropriate. 187 // The BufferedReader reads text from a character-input stream, buffering characters 188 // so as to provide for the efficient reading of characters. 189 BufferedReader br = new BufferedReader( new FileReader( fname ) ); 190 String s = null; 191 int cnt = 0; 192 double d1 = 0; 193 double d2 = 0; 194 double d3 = 0; 195 double d4 = 0; 196 double d7 = 0; 197 double d8 = 0; 198 while ( ( s = br.readLine() ) != null ) { 199 cnt++; 200 s = s.trim(); 201 switch ( cnt ) { 202 case 1: 203 // spatial resolution x direction 204 d1 = Double.parseDouble( s.replace( ',', '.' ) ); 205 break; 206 case 2: 207 // rotation1 208 d7 = Double.parseDouble( s.replace( ',', '.' ) ); 209 break; 210 case 3: 211 // rotation2 212 d8 = Double.parseDouble( s.replace( ',', '.' ) ); 213 break; 214 case 4: 215 // spatial resolution y direction 216 d2 = Double.parseDouble( s.replace( ',', '.' ) ); 217 break; 218 case 5: 219 // minimum x coordinate 220 d3 = Double.parseDouble( s.replace( ',', '.' ) ); 221 break; 222 case 6: 223 // maximum y coordinate 224 d4 = Double.parseDouble( s.replace( ',', '.' ) ); 225 break; 226 } 227 } 228 br.close(); 229 230 double d5 = d3 + ( ( width - 1 ) * d1 ); 231 double d6 = d4 + ( ( height - 1 ) * d2 ); 232 double resx = Math.abs( d1 ); 233 double resy = Math.abs( d2 ); 234 double ymax = d4; 235 double ymin = d6; 236 double xmax = d5; 237 double xmin = d3; 238 239 if ( type == TYPE.OUTER ) { 240 LOG.logDebug( xmin + " " + ymin + " " + xmax + " " + ymax ); 241 xmin = xmin + resx / 2d; 242 ymin = ymin - resy / 2d; 243 xmax = xmin + resx * ( width - 1 ); 244 ymax = ymin + resy * ( height - 1 ); 245 } 246 247 Envelope envelope = GeometryFactory.createEnvelope( xmin, ymin, xmax, ymax, null ); 248 249 return new WorldFile( resx, resy, d7, d8, envelope ); 250 } 251 252 /** 253 * returns a class represention of a ESRI world file 254 * 255 * @param filename 256 * name of the image/raster file inclusing path and extension 257 * @param type 258 * world file type 259 * @param image 260 * image/raster the worldfile belongs too 261 * @return a class represention of a ESRI world file 262 * @throws IOException 263 */ 264 public static WorldFile readWorldFile( String filename, TYPE type, BufferedImage image ) 265 throws IOException { 266 267 return readWorldFile( filename, type, image.getWidth(), image.getHeight() ); 268 } 269 270 /** 271 * writes a WorldFile 272 * 273 * @param wf 274 * @param fileBaseName 275 * @throws IOException 276 */ 277 public static void writeWorldFile( WorldFile wf, String fileBaseName ) 278 throws IOException { 279 280 Envelope env = wf.envelope; 281 282 StringBuffer sb = new StringBuffer( 200 ); 283 284 sb.append( wf.resx ).append( "\n" ).append( 0.0 ).append( "\n" ).append( 0.0 ); 285 sb.append( "\n" ).append( ( -1 ) * wf.resy ).append( "\n" ).append( env.getMin().getX() ); 286 sb.append( "\n" ).append( env.getMax().getY() ).append( "\n" ); 287 288 File f = new File( fileBaseName + ".wld" ); 289 290 FileWriter fw = new FileWriter( f ); 291 PrintWriter pw = new PrintWriter( fw ); 292 293 pw.print( sb.toString() ); 294 295 pw.close(); 296 fw.close(); 297 } 298 299 /** 300 * 301 * @param resx 302 * resolution x-direction 303 * @param resy 304 * resolution y-direction (negative value) 305 * @param rotation1 306 * first rotation parameter 307 * @param rotation2 308 * second rotation parameter 309 * @param envelope 310 * the envelope of the worldfile 311 */ 312 public WorldFile( double resx, double resy, double rotation1, double rotation2, Envelope envelope ) { 313 this.resx = resx; 314 this.resy = resy; 315 this.rotation1 = rotation1; 316 this.rotation2 = rotation2; 317 this.envelope = envelope; 318 } 319 320 /** 321 * returns the envelope described by a word file 322 * 323 * @return the envelope described by a word file 324 */ 325 public Envelope getEnvelope() { 326 return envelope; 327 } 328 329 /** 330 * returns the x-resolution described by a word file 331 * 332 * @return the x-resolution described by a word file 333 */ 334 public double getResx() { 335 return resx; 336 } 337 338 /** 339 * returns the y-resolution described by a word file 340 * 341 * @return the y-resolution described by a word file 342 */ 343 public double getResy() { 344 return resy; 345 } 346 347 /** 348 * returns the first rotation described by a word file 349 * 350 * @return the first rotation described by a word file 351 */ 352 public double getRotation1() { 353 return rotation1; 354 } 355 356 /** 357 * returns the second rotation described by a word file 358 * 359 * @return the second rotation described by a word file 360 */ 361 public double getRotation2() { 362 return rotation2; 363 } 364 365 @Override 366 public String toString() { 367 StringBuffer sb = new StringBuffer( 200 ); 368 sb.append( "envelope: " ).append( envelope ).append( "\n" ); 369 sb.append( "resx: " ).append( resx ).append( "\n" ); 370 sb.append( "resy: " ).append( resy ).append( "\n" ); 371 sb.append( "rotation1: " ).append( rotation1 ).append( "\n" ); 372 sb.append( "rotation2: " ).append( rotation2 ); 373 return sb.toString(); 374 } 375 376 }