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 }