|
|
|
stutte
|
Find enclosed the updated files
ECWReader.java ECWFileCache.java Greetings Jens //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/io/ecwapi/ECWReader.java $ /*---------------- FILE HEADER ------------------------------------------ This file is part of deegree. Copyright (C) 2003 by: IDgis bv, Holten, The Netherlands http://www.idgis.nl This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ---------------------------------------------------------------------------*/ package org.deegree.io.ecwapi; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.File; import java.net.URL; import org.deegree.framework.log.ILogger; import org.deegree.framework.log.LoggerFactory; import org.deegree.model.spatialschema.Envelope; import com.ermapper.ecw.JNCSException; import com.ermapper.ecw.JNCSFile; /** * ECWReader.java * * @author Herman Assink * @author last edited by: $Author: mschneider $ * @version 1.0 2003-11-06 */ public class ECWReader { private static final ILogger LOG = LoggerFactory.getLogger( ECWReader.class ); private static boolean ECW_USE_CACHE = true; private boolean usedCacheOnOpen = true; private JNCSFile ecwFile; /** * read part from ECW-file which falls within env and return this part dimenions width and * height * * @param fileName * full pathname of the ECW-file */ public ECWReader( String fileName ) throws JNCSException { if ( fileName.toLowerCase().startsWith( "file:/" ) ) { try { File f = new File( new URL( fileName ).getFile() ); fileName = f.getAbsolutePath(); } catch ( Exception e ) { new JNCSException( fileName + " is not a valid URL" ); } } LOG.logDebug( "ECWReader: " + fileName ); if ( ECW_USE_CACHE ) { this.ecwFile = ECWFileCache.claimAccess( fileName ); usedCacheOnOpen = true; } else { this.ecwFile = new JNCSFile( fileName, false ); usedCacheOnOpen = false; } } /** * Decide, if to use the cache. * <p> * Default is TRUE. */ public static void useECWCache( boolean Use ) { ECW_USE_CACHE = Use; } /** * Free the memory of the image cache */ public void close() { if ( usedCacheOnOpen ) { ECWFileCache.releaseFile( ecwFile ); } else { ecwFile.close( true ); } } /** * retuns the width of the entire image encapsulated in the ECW file * * @return width of the image */ public int getWidth() { return ecwFile.width; } /** * retuns the height of the entire image encapsulated in the ECW file * * @return height of the image */ public int getHeight() { return ecwFile.height; } /** * read part from ECW-file which falls within env and return this part as BufferedImage with * dimenions width and height * * @param env * bounding box in world coordinates of requested part * @param width * width of the returned image * @param height * height of the returned image */ public BufferedImage getBufferedImage( Envelope env, int width, int height ) throws JNCSException { int bandlist[]; int line, pRGBArray[] = null; // Setup the view parameters for the ecw file. bandlist = new int[ecwFile.numBands]; for ( int i = 0; i < ecwFile.numBands; i++ ) { bandlist[i] = i; } // Check if the envelope is within the area of the ecw-image double dWorldTLXRequest = env.getMin().getX(); double dWorldTLYRequest = env.getMax().getY(); double dWorldTLX = dWorldTLXRequest; double dWorldTLY = dWorldTLYRequest; LOG.logDebug( "tlx: " + dWorldTLX + " tly: " + dWorldTLY ); if ( dWorldTLX < ecwFile.originX ) dWorldTLX = ecwFile.originX; if ( dWorldTLY > ecwFile.originY ) dWorldTLY = ecwFile.originY; double dWorldBRXRequest = env.getMax().getX(); double dWorldBRYRequest = env.getMin().getY(); double dWorldBRX = dWorldBRXRequest; double dWorldBRY = dWorldBRYRequest; LOG.logDebug( "brx: " + dWorldBRX + " bry: " + dWorldBRY ); if ( dWorldBRX > ( ecwFile.originX + ( ( ecwFile.width - 1 ) * ecwFile.cellIncrementX ) ) ) // Huh? // ECW // does // not // except // the // full // width dWorldBRX = ecwFile.originX + ( ( ecwFile.width - 1 ) * ecwFile.cellIncrementX ); if ( dWorldBRY < ( ecwFile.originY + ( ecwFile.height * ecwFile.cellIncrementY ) - ( ecwFile.cellIncrementY / 2 ) ) ) dWorldBRY = ecwFile.originY + ( ecwFile.height * ecwFile.cellIncrementY ) - ( ecwFile.cellIncrementY / 2 ); // Work out the correct aspect for the setView call. // double dEnvAspect = (dWorldBRX - dWorldTLX) / (dWorldTLY - dWorldBRY); // double dImgAspect = (double) width / (double) height; LOG.logDebug( "tlx: " + dWorldTLX + " tly: " + dWorldTLY ); LOG.logDebug( "brx: " + dWorldBRX + " bry: " + dWorldBRY ); LOG.logDebug( "width: " + width + " height: " + height ); int nDatasetTLX = (int) Math.round( ( dWorldTLX - ecwFile.originX ) / ecwFile.cellIncrementX ); int nDatasetTLY = (int) Math.round( ( dWorldTLY - ecwFile.originY ) / ecwFile.cellIncrementY ); LOG.logDebug( "ptlx: " + nDatasetTLX + " ptly: " + nDatasetTLY ); int nDatasetBRX = (int) Math.round( ( dWorldBRX - ecwFile.originX ) / ecwFile.cellIncrementX ); int nDatasetBRY = (int) Math.round( ( dWorldBRY - ecwFile.originY ) / ecwFile.cellIncrementY ); LOG.logDebug( "pbrx: " + nDatasetBRX + " pbry: " + nDatasetBRY ); if ( nDatasetBRX > ( ecwFile.width - 1 ) ) nDatasetBRX = ecwFile.width - 1; if ( nDatasetBRY > ( ecwFile.height - 1 ) ) nDatasetBRY = ecwFile.height - 1; LOG.logDebug( "pbrx: " + nDatasetBRX + " pbry: " + nDatasetBRY ); // Check for supersampling int viewWidth = width; int viewHeight = height; if ( ( nDatasetBRX - nDatasetTLX ) < viewWidth || ( nDatasetBRY - nDatasetTLY ) < viewHeight ) { viewWidth = nDatasetBRX - nDatasetTLX; viewHeight = nDatasetBRY - nDatasetTLY; } double requestWidth = dWorldBRXRequest - dWorldTLXRequest; double worldWidth = dWorldBRX - dWorldTLX; if ( requestWidth > worldWidth) { viewWidth *= worldWidth / requestWidth; } double requestHeight = dWorldTLYRequest - dWorldBRYRequest; double worldHeight = dWorldTLY - dWorldBRY; if ( requestHeight > worldHeight) { viewHeight *= worldHeight / requestHeight; } if ( viewWidth == 0 ) viewWidth = 1; if ( viewHeight == 0 ) viewHeight = 1; LOG.logDebug( "Width: " + width + " Height: " + height ); LOG.logDebug( "viewWidth: " + viewWidth + " viewHeight: " + viewHeight ); // Create an image of the ecw file. BufferedImage ecwImage = new BufferedImage( viewWidth, viewHeight, BufferedImage.TYPE_INT_RGB ); synchronized (ecwFile) { // Set the view // We correct the missing last cell for some zoom scales (ECW bug?) by reading an extra cell on the right pRGBArray = new int[viewWidth]; ecwFile.setView( ecwFile.numBands, bandlist, nDatasetTLX, nDatasetTLY, nDatasetBRX , nDatasetBRY, viewWidth, viewHeight ); // Read the scan lines for ( line = 0; line < viewHeight; line++ ) { ecwFile.readLineRGBA( pRGBArray ); ecwImage.setRGB( 0, line, viewWidth, 1, pRGBArray, 0, viewWidth ); } } if ( width != viewWidth || height != viewHeight ) { LOG.logDebug( "create larger image" ); int destX = 0, destY = 0, destWidth = width, destHeight = height; if ( requestWidth > worldWidth) { double pixWidth = requestWidth / width; destX = (int)( ( dWorldTLX - dWorldTLXRequest ) / pixWidth + 0.5 ); destWidth = (int)( ( dWorldBRX - dWorldTLXRequest ) / pixWidth + 0.5 ); } if ( requestHeight > worldHeight) { double pixHeight = requestHeight / height; destY = (int)( ( dWorldTLYRequest - dWorldTLY ) / pixHeight + 0.5 ); destHeight = (int)( ( dWorldTLYRequest - dWorldBRY ) / pixHeight + 0.5 ); } BufferedImage enlargedImg = new BufferedImage( width, height, BufferedImage.TYPE_INT_RGB ); Graphics g = enlargedImg.getGraphics(); g.drawImage( ecwImage, destX, destY, destWidth, destHeight, 0, 0, viewWidth, viewHeight, null ); ecwImage = enlargedImg; g.dispose(); } return ecwImage; } } //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/io/ecwapi/ECWFileCache.java $ /*---------------- FILE HEADER ------------------------------------------ This file is part of deegree. Copyright (C) 2007 by: Planetek Italia s.r.l, Bari, Italia http://www.planetek.it This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ---------------------------------------------------------------------------*/ package org.deegree.io.ecwapi; import java.util.HashSet; import java.util.Hashtable; import java.util.Properties; import java.io.InputStream; import org.deegree.framework.log.ILogger; import org.deegree.framework.log.LoggerFactory; import com.ermapper.ecw.JNCSException; import com.ermapper.ecw.JNCSFile; import java.io.IOException; import java.util.Random; /** * * * * @version $Revision: 10660 $ * @author <a href="mailto:[hidden email]">Jens Stutte</a> * @author last edited by: $Author: apoth $ * * @version 1.0. $Revision: 10660 $, $Date: 2008-03-24 22:39:54 +0100 (lun, 24 mar 2008) $ * * @since 2.0 */ public class ECWFileCache { private static final ILogger LOG = LoggerFactory.getLogger( ECWFileCache.class ); private static Hashtable<String, ECWFile> ECWNamedFileCache = new Hashtable<String, ECWFile>(); public static long EXPIRATION_PERIOD_MS = 600000; public static long MAX_WAIT_THREAD = 1000; private static class CleanThread extends Thread { @Override public void run() { while (true) { try {Thread.sleep(EXPIRATION_PERIOD_MS);} catch (InterruptedException ie) {} closeExpired(false); } } } private static CleanThread cleaner; /* Load the configuration if any */ static { InputStream is = ECWFileCache.class.getResourceAsStream( "/ecwcache.properties" ); if (is == null) is = ECWFileCache.class.getResourceAsStream( "ecwcache.properties" ); if ( is != null ) { LOG.logInfo("Found ecwcache.properties file"); Properties props = new Properties(); try { props.load( is ); is.close(); String buf = props.getProperty( "expirationPeriodMs" ); if (buf != null) { EXPIRATION_PERIOD_MS = Integer.parseInt( buf ); LOG.logInfo("Set expirationPeriodMs = " + EXPIRATION_PERIOD_MS); } } catch ( IOException e ) { } } cleaner = new CleanThread(); cleaner.start(); } // A private inner class that describes a cache entry private static class ECWFile { java.util.Date LastAccess; JNCSFile myFile; int useCounter; ECWFile( String fileName ) throws JNCSException { myFile = new JNCSFile( fileName, false ); LastAccess = new java.util.Date(); ECWNamedFileCache.put(fileName, this); useCounter = 0; } } // Retrieve the thread id. private static long getThreadId() { return Thread.currentThread().getId(); } // look for a cached instance of this file reference // if not found, returns null. private static ECWFile findCachedInstance(String fileName) throws JNCSException { synchronized ( ECWNamedFileCache ) { ECWFile file = ECWNamedFileCache.get( fileName ); if (file == null) { file = new ECWFile( fileName ); } return file; } } // lock the file for the current thread, opens new instance // if nothing present in cache // CAUTION: This function may block for an undefined amount of time, if other // threads block the desired resources. private static ECWFile useFile( String fileName ) throws JNCSException { ECWFile ret = findCachedInstance(fileName); ret.LastAccess = new java.util.Date(); ret.useCounter++; return ret; } // release file for use private static void unuseFile( ECWFile file ) { synchronized ( ECWNamedFileCache ) { if ( file != null ) { file.useCounter--; } } } // close (and delete) file access instance private static void closeFile( ECWFile file ) { if (file.useCounter > 0) { throw new RuntimeException("ECWApi: Attempt to close a file that is owned by a different thread."); } synchronized ( ECWNamedFileCache ) { ECWNamedFileCache.remove( file.myFile.fileName ); file.myFile.close( true ); } } // Find and close expired cache entries. // If forceDeleteUnused is set, the oldest unused file reference will be // closed, otherwise only expired entries will be closed. private static boolean closeExpired(boolean forceDeleteUnused) { boolean ret = false; synchronized ( ECWNamedFileCache ) { ECWFile oldest = null; int numOpen = 0; ECWFile[] fa = ECWNamedFileCache.values().toArray( new ECWFile[ECWNamedFileCache.size()] ); java.util.Date now = new java.util.Date(); LOG.logDebug("closeExpired: Currently we have " + fa.length + " ECW file handles open."); for ( int i = 0; i < fa.length; i++ ) { if ( fa[i].useCounter <= 0 ) { if ( now.getTime() - fa[i].LastAccess.getTime() > EXPIRATION_PERIOD_MS ) { LOG.logDebug("closeExpired: Closing " + fa[i] + " ECW file handle for expiration."); closeFile( fa[i] ); ret = true; } } } } return ret; } /** * Claim access to an ECW file. * <p> * If there is a non-expired instance in the cache, re-use this. Otherwise adds a new * one to the cache. * <p> * CAUTION: This cache DOES NOT HANDLE NESTED claims/releases ! This means, that after having * called claimAcces, you MUST call releaseFile before ANY OTHER OPERATION ON THE CACHE within * the same thread. * <p> * CAUTION: All accesses to the JNCSFile instance have to be synchronized! * See ECWReader.getBufferedImage. * <p> */ public static JNCSFile claimAccess( String fileName ) throws JNCSException { closeExpired(false); ECWFile f = useFile( fileName ); return f.myFile; } /** * Release access to an ECW file. * <p> * Unuses the cache entry. Calls also the expiration method for cleanup of the instances that * exceed MaxNumOpen. */ public static void releaseFile( JNCSFile myfile ) { unuseFile( ECWNamedFileCache.get( myfile ) ); closeExpired(false); } /** * Set expiration period * <p> * Set the time in milliseconds that a cache entry remains valid. Calls also the expiration * method for cleanup. * <p> * Default value: 600000 */ public static void setExpirationPeriod( long MilliSecs ) { EXPIRATION_PERIOD_MS = MilliSecs; closeExpired(false); } } ------------------------------------------------------------------------------ Come build with us! The BlackBerry® Developer Conference in SF, CA is the only developer event you need to attend this year. Jumpstart your developing skills, take BlackBerry mobile applications to market and stay ahead of the curve. Join us from November 9-12, 2009. Register now! http://p.sf.net/sfu/devconf _______________________________________________ deegree-devel mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/deegree-devel |
||||||||||||||||
| Free Embeddable Forum Powered by Nabble | Help |