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 }