001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/io/ecwapi/ECWReader.java $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 004 This file is part of deegree. 005 Copyright (C) 2003 by: 006 IDgis bv, Holten, The Netherlands 007 http://www.idgis.nl 008 009 This library is free software; you can redistribute it and/or 010 modify it under the terms of the GNU Lesser General Public 011 License as published by the Free Software Foundation; either 012 version 2.1 of the License, or (at your option) any later version. 013 014 This library is distributed in the hope that it will be useful, 015 but WITHOUT ANY WARRANTY; without even the implied warranty of 016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 017 Lesser General Public License for more details. 018 019 You should have received a copy of the GNU Lesser General Public 020 License along with this library; if not, write to the Free Software 021 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 022 023 ---------------------------------------------------------------------------*/ 024 package org.deegree.io.ecwapi; 025 026 import java.awt.Graphics; 027 import java.awt.image.BufferedImage; 028 import java.io.File; 029 import java.net.URL; 030 031 import org.deegree.framework.log.ILogger; 032 import org.deegree.framework.log.LoggerFactory; 033 import org.deegree.model.spatialschema.Envelope; 034 035 import com.ermapper.ecw.JNCSException; 036 import com.ermapper.ecw.JNCSFile; 037 038 /** 039 * ECWReader.java 040 * 041 * @author Herman Assink 042 * @author last edited by: $Author: aschmitz $ 043 * @version 1.0 2003-11-06 044 */ 045 046 public class ECWReader { 047 048 private static final ILogger LOG = LoggerFactory.getLogger( ECWReader.class ); 049 050 private static boolean ECW_USE_CACHE = true; 051 052 private boolean usedCacheOnOpen = true; 053 054 private JNCSFile ecwFile; 055 056 /** 057 * read part from ECW-file which falls within env and return this part dimenions width and height 058 * 059 * @param fileName 060 * full pathname of the ECW-file 061 * @throws JNCSException 062 */ 063 public ECWReader( String fileName ) throws JNCSException { 064 065 if ( fileName.toLowerCase().startsWith( "file:/" ) ) { 066 try { 067 File f = new File( new URL( fileName ).getFile() ); 068 fileName = f.getAbsolutePath(); 069 } catch ( Exception e ) { 070 LOG.logDebug( "Stack trace of eaten exception: ", e ); 071 throw new JNCSException( fileName + " is not a valid URL" ); 072 } 073 } 074 LOG.logDebug( "ECWReader: " + fileName ); 075 076 if ( ECW_USE_CACHE ) { 077 this.ecwFile = ECWFileCache.claimAccess( fileName ); 078 usedCacheOnOpen = true; 079 } else { 080 this.ecwFile = new JNCSFile( fileName, false ); 081 usedCacheOnOpen = false; 082 } 083 } 084 085 /** 086 * Decide, if to use the cache. 087 * <p> 088 * Default is TRUE. 089 */ 090 public static void useECWCache( boolean Use ) { 091 ECW_USE_CACHE = Use; 092 } 093 094 /** 095 * Free the memory of the image cache 096 */ 097 public void close() { 098 if ( usedCacheOnOpen ) { 099 ECWFileCache.releaseFile( ecwFile ); 100 } else { 101 ecwFile.close( true ); 102 } 103 } 104 105 /** 106 * retuns the width of the entire image encapsulated in the ECW file 107 * 108 * @return width of the image 109 */ 110 public int getWidth() { 111 return ecwFile.width; 112 } 113 114 /** 115 * retuns the height of the entire image encapsulated in the ECW file 116 * 117 * @return height of the image 118 */ 119 public int getHeight() { 120 return ecwFile.height; 121 } 122 123 /** 124 * read part from ECW-file which falls within env and return this part as BufferedImage with dimenions width and 125 * height 126 * 127 * @param env 128 * bounding box in world coordinates of requested part 129 * @param width 130 * width of the returned image 131 * @param height 132 * height of the returned image 133 */ 134 public BufferedImage getBufferedImage( Envelope env, int width, int height ) 135 throws JNCSException { 136 137 int bandlist[]; 138 int line, pRGBArray[] = null; 139 140 // Setup the view parameters for the ecw file. 141 bandlist = new int[ecwFile.numBands]; 142 for ( int i = 0; i < ecwFile.numBands; i++ ) { 143 bandlist[i] = i; 144 } 145 146 // Check if the envelope is within the area of the ecw-image 147 double dWorldTLXRequest = env.getMin().getX(); 148 double dWorldTLYRequest = env.getMax().getY(); 149 150 double dWorldTLX = dWorldTLXRequest; 151 double dWorldTLY = dWorldTLYRequest; 152 153 LOG.logDebug( "tlx: " + dWorldTLX + " tly: " + dWorldTLY ); 154 155 if ( dWorldTLX < ecwFile.originX ) 156 dWorldTLX = ecwFile.originX; 157 if ( dWorldTLY > ecwFile.originY ) 158 dWorldTLY = ecwFile.originY; 159 160 double dWorldBRXRequest = env.getMax().getX(); 161 double dWorldBRYRequest = env.getMin().getY(); 162 163 double dWorldBRX = dWorldBRXRequest; 164 double dWorldBRY = dWorldBRYRequest; 165 166 LOG.logDebug( "brx: " + dWorldBRX + " bry: " + dWorldBRY ); 167 168 if ( dWorldBRX > ( ecwFile.originX + ( ( ecwFile.width - 1 ) * ecwFile.cellIncrementX ) ) ) // Huh? 169 // ECW 170 // does 171 // not 172 // except 173 // the 174 // full 175 // width 176 dWorldBRX = ecwFile.originX + ( ( ecwFile.width - 1 ) * ecwFile.cellIncrementX ); 177 if ( dWorldBRY < ( ecwFile.originY + ( ecwFile.height * ecwFile.cellIncrementY ) - ( ecwFile.cellIncrementY / 2 ) ) ) 178 dWorldBRY = ecwFile.originY + ( ecwFile.height * ecwFile.cellIncrementY ) - ( ecwFile.cellIncrementY / 2 ); 179 180 // Work out the correct aspect for the setView call. 181 // double dEnvAspect = (dWorldBRX - dWorldTLX) / (dWorldTLY - dWorldBRY); 182 // double dImgAspect = (double) width / (double) height; 183 184 LOG.logDebug( "tlx: " + dWorldTLX + " tly: " + dWorldTLY ); 185 LOG.logDebug( "brx: " + dWorldBRX + " bry: " + dWorldBRY ); 186 LOG.logDebug( "width: " + width + " height: " + height ); 187 188 int nDatasetTLX = (int) Math.round( ( dWorldTLX - ecwFile.originX ) / ecwFile.cellIncrementX ); 189 int nDatasetTLY = (int) Math.round( ( dWorldTLY - ecwFile.originY ) / ecwFile.cellIncrementY ); 190 191 LOG.logDebug( "ptlx: " + nDatasetTLX + " ptly: " + nDatasetTLY ); 192 193 int nDatasetBRX = (int) Math.round( ( dWorldBRX - ecwFile.originX ) / ecwFile.cellIncrementX ); 194 int nDatasetBRY = (int) Math.round( ( dWorldBRY - ecwFile.originY ) / ecwFile.cellIncrementY ); 195 196 LOG.logDebug( "pbrx: " + nDatasetBRX + " pbry: " + nDatasetBRY ); 197 198 if ( nDatasetBRX > ( ecwFile.width - 1 ) ) 199 nDatasetBRX = ecwFile.width - 1; 200 if ( nDatasetBRY > ( ecwFile.height - 1 ) ) 201 nDatasetBRY = ecwFile.height - 1; 202 203 LOG.logDebug( "pbrx: " + nDatasetBRX + " pbry: " + nDatasetBRY ); 204 205 // Check for supersampling 206 int viewWidth = width; 207 int viewHeight = height; 208 if ( ( nDatasetBRX - nDatasetTLX ) < viewWidth || ( nDatasetBRY - nDatasetTLY ) < viewHeight ) { 209 viewWidth = nDatasetBRX - nDatasetTLX; 210 viewHeight = nDatasetBRY - nDatasetTLY; 211 } 212 213 double requestWidth = dWorldBRXRequest - dWorldTLXRequest; 214 double worldWidth = dWorldBRX - dWorldTLX; 215 if ( requestWidth > worldWidth ) { 216 viewWidth *= worldWidth / requestWidth; 217 } 218 219 double requestHeight = dWorldTLYRequest - dWorldBRYRequest; 220 double worldHeight = dWorldTLY - dWorldBRY; 221 if ( requestHeight > worldHeight ) { 222 viewHeight *= worldHeight / requestHeight; 223 } 224 225 if ( viewWidth == 0 ) 226 viewWidth = 1; 227 if ( viewHeight == 0 ) 228 viewHeight = 1; 229 230 LOG.logDebug( "Width: " + width + " Height: " + height ); 231 LOG.logDebug( "viewWidth: " + viewWidth + " viewHeight: " + viewHeight ); 232 233 // Create an image of the ecw file. 234 BufferedImage ecwImage = new BufferedImage( viewWidth, viewHeight, BufferedImage.TYPE_INT_RGB ); 235 pRGBArray = new int[width]; 236 237 // Set the view 238 ecwFile.setView( ecwFile.numBands, bandlist, nDatasetTLX, nDatasetTLY, nDatasetBRX, nDatasetBRY, viewWidth, 239 viewHeight ); 240 241 // Read the scan lines 242 for ( line = 0; line < viewHeight; line++ ) { 243 ecwFile.readLineRGBA( pRGBArray ); 244 ecwImage.setRGB( 0, line, viewWidth, 1, pRGBArray, 0, viewWidth ); 245 } 246 247 if ( width != viewWidth || height != viewHeight ) { 248 LOG.logDebug( "create larger image" ); 249 250 int destX = 0, destY = 0, destWidth = width, destHeight = height; 251 252 if ( requestWidth > worldWidth ) { 253 double pixWidth = requestWidth / width; 254 255 destX = (int) ( ( dWorldTLX - dWorldTLXRequest ) / pixWidth + 0.5 ); 256 destWidth = (int) ( ( dWorldBRX - dWorldTLXRequest ) / pixWidth + 0.5 ); 257 } 258 259 if ( requestHeight > worldHeight ) { 260 double pixHeight = requestHeight / height; 261 262 destY = (int) ( ( dWorldTLYRequest - dWorldTLY ) / pixHeight + 0.5 ); 263 destHeight = (int) ( ( dWorldTLYRequest - dWorldBRY ) / pixHeight + 0.5 ); 264 } 265 266 BufferedImage enlargedImg = new BufferedImage( width, height, BufferedImage.TYPE_INT_RGB ); 267 Graphics g = enlargedImg.getGraphics(); 268 g.drawImage( ecwImage, destX, destY, destWidth, destHeight, 0, 0, viewWidth, viewHeight, null ); 269 ecwImage = enlargedImg; 270 g.dispose(); 271 } 272 273 return ecwImage; 274 275 } 276 }