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