001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_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: mschneider $ 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 058 * height 059 * 060 * @param fileName 061 * full pathname of the ECW-file 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 new JNCSException( fileName + " is not a valid URL" ); 071 } 072 } 073 LOG.logDebug( "ECWReader: " + fileName ); 074 075 if ( ECW_USE_CACHE ) { 076 this.ecwFile = ECWFileCache.claimAccess( fileName ); 077 usedCacheOnOpen = true; 078 } else { 079 this.ecwFile = new JNCSFile( fileName, false ); 080 usedCacheOnOpen = false; 081 } 082 } 083 084 /** 085 * Decide, if to use the cache. 086 * <p> 087 * Default is TRUE. 088 */ 089 public static void useECWCache( boolean Use ) { 090 ECW_USE_CACHE = Use; 091 } 092 093 /** 094 * Free the memory of the image cache 095 */ 096 public void close() { 097 if ( usedCacheOnOpen ) { 098 ECWFileCache.releaseFile( ecwFile ); 099 } else { 100 ecwFile.close( true ); 101 } 102 } 103 104 /** 105 * retuns the width of the entire image encapsulated in the ECW file 106 * 107 * @return width of the image 108 */ 109 public int getWidth() { 110 return ecwFile.width; 111 } 112 113 /** 114 * retuns the height of the entire image encapsulated in the ECW file 115 * 116 * @return height of the image 117 */ 118 public int getHeight() { 119 return ecwFile.height; 120 } 121 122 /** 123 * read part from ECW-file which falls within env and return this part as BufferedImage with 124 * dimenions width and height 125 * 126 * @param env 127 * bounding box in world coordinates of requested part 128 * @param width 129 * width of the returned image 130 * @param height 131 * height of the returned image 132 */ 133 public BufferedImage getBufferedImage( Envelope env, int width, int height ) 134 throws JNCSException { 135 136 int bandlist[]; 137 int line, pRGBArray[] = null; 138 139 // Setup the view parameters for the ecw file. 140 bandlist = new int[ecwFile.numBands]; 141 for ( int i = 0; i < ecwFile.numBands; i++ ) { 142 bandlist[i] = i; 143 } 144 145 // Check if the envelope is within the area of the ecw-image 146 double dWorldTLXRequest = env.getMin().getX(); 147 double dWorldTLYRequest = env.getMax().getY(); 148 149 double dWorldTLX = dWorldTLXRequest; 150 double dWorldTLY = dWorldTLYRequest; 151 152 LOG.logDebug( "tlx: " + dWorldTLX + " tly: " + dWorldTLY ); 153 154 if ( dWorldTLX < ecwFile.originX ) 155 dWorldTLX = ecwFile.originX; 156 if ( dWorldTLY > ecwFile.originY ) 157 dWorldTLY = ecwFile.originY; 158 159 double dWorldBRXRequest = env.getMax().getX(); 160 double dWorldBRYRequest = env.getMin().getY(); 161 162 double dWorldBRX = dWorldBRXRequest; 163 double dWorldBRY = dWorldBRYRequest; 164 165 LOG.logDebug( "brx: " + dWorldBRX + " bry: " + dWorldBRY ); 166 167 if ( dWorldBRX > ( ecwFile.originX + ( ( ecwFile.width - 1 ) * ecwFile.cellIncrementX ) ) ) // Huh? 168 // ECW 169 // does 170 // not 171 // except 172 // the 173 // full 174 // width 175 dWorldBRX = ecwFile.originX + ( ( ecwFile.width - 1 ) * ecwFile.cellIncrementX ); 176 if ( dWorldBRY < ( ecwFile.originY + ( ecwFile.height * ecwFile.cellIncrementY ) - ( ecwFile.cellIncrementY / 2 ) ) ) 177 dWorldBRY = ecwFile.originY + ( ecwFile.height * ecwFile.cellIncrementY ) - ( ecwFile.cellIncrementY / 2 ); 178 179 // Work out the correct aspect for the setView call. 180 // double dEnvAspect = (dWorldBRX - dWorldTLX) / (dWorldTLY - dWorldBRY); 181 // double dImgAspect = (double) width / (double) height; 182 183 LOG.logDebug( "tlx: " + dWorldTLX + " tly: " + dWorldTLY ); 184 LOG.logDebug( "brx: " + dWorldBRX + " bry: " + dWorldBRY ); 185 LOG.logDebug( "width: " + width + " height: " + height ); 186 187 int nDatasetTLX = (int) Math.round( ( dWorldTLX - ecwFile.originX ) / ecwFile.cellIncrementX ); 188 int nDatasetTLY = (int) Math.round( ( dWorldTLY - ecwFile.originY ) / ecwFile.cellIncrementY ); 189 190 LOG.logDebug( "ptlx: " + nDatasetTLX + " ptly: " + nDatasetTLY ); 191 192 int nDatasetBRX = (int) Math.round( ( dWorldBRX - ecwFile.originX ) / ecwFile.cellIncrementX ); 193 int nDatasetBRY = (int) Math.round( ( dWorldBRY - ecwFile.originY ) / ecwFile.cellIncrementY ); 194 195 LOG.logDebug( "pbrx: " + nDatasetBRX + " pbry: " + nDatasetBRY ); 196 197 if ( nDatasetBRX > ( ecwFile.width - 1 ) ) 198 nDatasetBRX = ecwFile.width - 1; 199 if ( nDatasetBRY > ( ecwFile.height - 1 ) ) 200 nDatasetBRY = ecwFile.height - 1; 201 202 LOG.logDebug( "pbrx: " + nDatasetBRX + " pbry: " + nDatasetBRY ); 203 204 // Check for supersampling 205 int viewWidth = width; 206 int viewHeight = height; 207 if ( ( nDatasetBRX - nDatasetTLX ) < viewWidth || ( nDatasetBRY - nDatasetTLY ) < viewHeight ) { 208 viewWidth = nDatasetBRX - nDatasetTLX; 209 viewHeight = nDatasetBRY - nDatasetTLY; 210 } 211 212 double requestWidth = dWorldBRXRequest - dWorldTLXRequest; 213 double worldWidth = dWorldBRX - dWorldTLX; 214 if ( requestWidth > worldWidth) { 215 viewWidth *= worldWidth / requestWidth; 216 } 217 218 double requestHeight = dWorldTLYRequest - dWorldBRYRequest; 219 double worldHeight = dWorldTLY - dWorldBRY; 220 if ( requestHeight > worldHeight) { 221 viewHeight *= worldHeight / requestHeight; 222 } 223 224 if ( viewWidth == 0 ) 225 viewWidth = 1; 226 if ( viewHeight == 0 ) 227 viewHeight = 1; 228 229 LOG.logDebug( "Width: " + width + " Height: " + height ); 230 LOG.logDebug( "viewWidth: " + viewWidth + " viewHeight: " + viewHeight ); 231 232 // Create an image of the ecw file. 233 BufferedImage ecwImage = new BufferedImage( viewWidth, viewHeight, BufferedImage.TYPE_INT_RGB ); 234 pRGBArray = new int[width]; 235 236 // Set the view 237 ecwFile.setView( ecwFile.numBands, bandlist, nDatasetTLX, nDatasetTLY, nDatasetBRX, nDatasetBRY, viewWidth, 238 viewHeight ); 239 240 // Read the scan lines 241 for ( line = 0; line < viewHeight; line++ ) { 242 ecwFile.readLineRGBA( pRGBArray ); 243 ecwImage.setRGB( 0, line, viewWidth, 1, pRGBArray, 0, viewWidth ); 244 } 245 246 if ( width != viewWidth || height != viewHeight ) { 247 LOG.logDebug( "create larger image" ); 248 249 int destX = 0, 250 destY = 0, 251 destWidth = width, 252 destHeight = height; 253 254 if ( requestWidth > worldWidth) { 255 double pixWidth = requestWidth / width; 256 257 destX = (int)( ( dWorldTLX - dWorldTLXRequest ) / pixWidth + 0.5 ); 258 destWidth = (int)( ( dWorldBRX - dWorldTLXRequest ) / pixWidth + 0.5 ); 259 } 260 261 262 if ( requestHeight > worldHeight) { 263 double pixHeight = requestHeight / height; 264 265 destY = (int)( ( dWorldTLYRequest - dWorldTLY ) / pixHeight + 0.5 ); 266 destHeight = (int)( ( dWorldTLYRequest - dWorldBRY ) / pixHeight + 0.5 ); 267 } 268 269 BufferedImage enlargedImg = new BufferedImage( width, height, BufferedImage.TYPE_INT_RGB ); 270 Graphics g = enlargedImg.getGraphics(); 271 g.drawImage( ecwImage, destX, destY, destWidth, destHeight, 0, 0, viewWidth, viewHeight, null ); 272 ecwImage = enlargedImg; 273 g.dispose(); 274 } 275 276 return ecwImage; 277 278 } 279 }