Split the runtime-adjustment functionality of ImageManager out. In order to preserve backwards compatibility, the complete functionality including runtime-adjustment can be found in ImageManager which now extends BaseImageManager. The bulk of functionality is now in BaseImageManager and anyone who wants an image manager without the RuntimeAdjustment bits (it uses ClientPrefs and thus isn't friendly in server-land) should use that directly.
git-svn-id: svn+ssh://src.earth.threerings.net/nenya/trunk@433 ed5b42cb-e716-0410-a449-f6a68f950b19
This commit is contained in:
@@ -35,7 +35,7 @@ import com.samskivert.util.Throttle;
|
||||
import com.samskivert.util.Tuple;
|
||||
|
||||
import com.threerings.media.image.Colorization;
|
||||
import com.threerings.media.image.ImageManager;
|
||||
import com.threerings.media.image.BaseImageManager;
|
||||
import com.threerings.util.DirectionCodes;
|
||||
|
||||
import com.threerings.cast.CompositedActionFrames.ComponentFrames;
|
||||
@@ -52,7 +52,7 @@ public class CharacterManager
|
||||
/**
|
||||
* Constructs the character manager.
|
||||
*/
|
||||
public CharacterManager (ImageManager imgr, ComponentRepository crepo)
|
||||
public CharacterManager (BaseImageManager imgr, ComponentRepository crepo)
|
||||
{
|
||||
// keep these around
|
||||
_imgr = imgr;
|
||||
@@ -421,7 +421,7 @@ public class CharacterManager
|
||||
}
|
||||
|
||||
/** The image manager with whom we interact. */
|
||||
protected ImageManager _imgr;
|
||||
protected BaseImageManager _imgr;
|
||||
|
||||
/** The component repository. */
|
||||
protected ComponentRepository _crepo;
|
||||
|
||||
@@ -24,8 +24,8 @@ package com.threerings.cast;
|
||||
import com.samskivert.util.LRUHashMap;
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
import com.threerings.media.image.BaseImageManager;
|
||||
import com.threerings.media.image.Colorization;
|
||||
import com.threerings.media.image.ImageManager;
|
||||
import com.threerings.media.util.MultiFrameImage;
|
||||
|
||||
import com.threerings.cast.CharacterComponent;
|
||||
@@ -65,7 +65,7 @@ public class CompositedActionFrames
|
||||
* source frames and colorization configuration. The actual component
|
||||
* frame images will not be composited until they are requested.
|
||||
*/
|
||||
public CompositedActionFrames (ImageManager imgr, LRUHashMap frameCache,
|
||||
public CompositedActionFrames (BaseImageManager imgr, LRUHashMap frameCache,
|
||||
String action, ComponentFrames[] sources)
|
||||
{
|
||||
// sanity check
|
||||
@@ -177,7 +177,7 @@ public class CompositedActionFrames
|
||||
|
||||
/** The image manager from whom we can obtain prepared volatile images
|
||||
* onto which to render our composited actions. */
|
||||
protected ImageManager _imgr;
|
||||
protected BaseImageManager _imgr;
|
||||
|
||||
/** Used to cache our composited action frame images. */
|
||||
protected LRUHashMap _frameCache;
|
||||
|
||||
@@ -28,7 +28,7 @@ import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Transparency;
|
||||
|
||||
import com.threerings.media.image.ImageManager;
|
||||
import com.threerings.media.image.BaseImageManager;
|
||||
import com.threerings.media.image.Mirage;
|
||||
import com.threerings.media.image.VolatileMirage;
|
||||
|
||||
@@ -40,7 +40,7 @@ import com.threerings.cast.CompositedActionFrames.ComponentFrames;
|
||||
public class CompositedMaskedImage extends CompositedMultiFrameImage
|
||||
{
|
||||
public CompositedMaskedImage (
|
||||
ImageManager imgr, ComponentFrames[] sources, String action,
|
||||
BaseImageManager imgr, ComponentFrames[] sources, String action,
|
||||
int orient)
|
||||
{
|
||||
super(imgr, sources, action, orient);
|
||||
|
||||
@@ -31,7 +31,7 @@ import java.util.Comparator;
|
||||
|
||||
import com.threerings.cast.CompositedActionFrames.ComponentFrames;
|
||||
import com.threerings.cast.bundle.BundledComponentRepository.TileSetFrameImage;
|
||||
import com.threerings.media.image.ImageManager;
|
||||
import com.threerings.media.image.BaseImageManager;
|
||||
import com.threerings.media.image.Mirage;
|
||||
import com.threerings.media.image.VolatileMirage;
|
||||
|
||||
@@ -43,7 +43,7 @@ public class CompositedMultiFrameImage
|
||||
implements TrimmedMultiFrameImage
|
||||
{
|
||||
public CompositedMultiFrameImage (
|
||||
ImageManager imgr, ComponentFrames[] sources,
|
||||
BaseImageManager imgr, ComponentFrames[] sources,
|
||||
String action, int orient)
|
||||
{
|
||||
_imgr = imgr;
|
||||
@@ -190,7 +190,7 @@ public class CompositedMultiFrameImage
|
||||
}
|
||||
|
||||
/** The image manager from whom we load our images. */
|
||||
protected ImageManager _imgr;
|
||||
protected BaseImageManager _imgr;
|
||||
|
||||
/** The action frames from which we obtain our source imagery. */
|
||||
protected ComponentFrames[] _sources;
|
||||
|
||||
@@ -26,7 +26,7 @@ import java.awt.Composite;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
|
||||
import com.threerings.media.image.ImageManager;
|
||||
import com.threerings.media.image.BaseImageManager;
|
||||
import com.threerings.media.image.Mirage;
|
||||
import com.threerings.media.image.VolatileMirage;
|
||||
|
||||
@@ -38,7 +38,7 @@ import com.threerings.cast.CompositedActionFrames.ComponentFrames;
|
||||
*/
|
||||
public class CompositedShadowImage extends CompositedMultiFrameImage
|
||||
{
|
||||
public CompositedShadowImage (ImageManager imgr, ComponentFrames[] sources,
|
||||
public CompositedShadowImage (BaseImageManager imgr, ComponentFrames[] sources,
|
||||
String action, int orient, float shadowAlpha)
|
||||
{
|
||||
super(imgr, sources, action, orient);
|
||||
|
||||
@@ -40,10 +40,10 @@ import com.threerings.resource.FileResourceBundle;
|
||||
import com.threerings.resource.ResourceBundle;
|
||||
import com.threerings.resource.ResourceManager;
|
||||
|
||||
import com.threerings.media.image.BaseImageManager;
|
||||
import com.threerings.media.image.BufferedMirage;
|
||||
import com.threerings.media.image.Colorization;
|
||||
import com.threerings.media.image.ImageDataProvider;
|
||||
import com.threerings.media.image.ImageManager;
|
||||
import com.threerings.media.image.ImageUtil;
|
||||
import com.threerings.media.image.Mirage;
|
||||
|
||||
@@ -85,7 +85,7 @@ public class BundledComponentRepository
|
||||
* resource bundles.
|
||||
*/
|
||||
public BundledComponentRepository (
|
||||
ResourceManager rmgr, ImageManager imgr, String name)
|
||||
ResourceManager rmgr, BaseImageManager imgr, String name)
|
||||
throws IOException
|
||||
{
|
||||
// keep this guy around
|
||||
@@ -261,7 +261,7 @@ public class BundledComponentRepository
|
||||
/**
|
||||
* Constructs an instance that will obtain image data from the specified resource bundle.
|
||||
*/
|
||||
public ResourceBundleProvider (ImageManager imgr, ResourceBundle bundle)
|
||||
public ResourceBundleProvider (BaseImageManager imgr, ResourceBundle bundle)
|
||||
{
|
||||
super(imgr, (String)null);
|
||||
_dprov = this;
|
||||
@@ -486,7 +486,7 @@ public class BundledComponentRepository
|
||||
return _set.getTile(getTileIndex(orient, index));
|
||||
}
|
||||
|
||||
public Mirage getTileMirage(int orient, int index) {
|
||||
public Mirage getTileMirage (int orient, int index) {
|
||||
return _set.getTileMirage(getTileIndex(orient, index));
|
||||
}
|
||||
|
||||
@@ -508,7 +508,7 @@ public class BundledComponentRepository
|
||||
}
|
||||
|
||||
/** We use the image manager to decode and cache images. */
|
||||
protected ImageManager _imgr;
|
||||
protected BaseImageManager _imgr;
|
||||
|
||||
/** A table of action sequences. */
|
||||
protected HashMap _actions;
|
||||
|
||||
@@ -33,7 +33,7 @@ import java.awt.image.BufferedImage;
|
||||
* AWT to determine the optimal image format.
|
||||
*/
|
||||
public class AWTImageCreator
|
||||
implements ImageManager.OptimalImageCreator
|
||||
implements BaseImageManager.OptimalImageCreator
|
||||
{
|
||||
/**
|
||||
* Create an image creator that will rely on the AWT to determine the
|
||||
@@ -53,7 +53,7 @@ public class AWTImageCreator
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface ImageManager.OptimalImageCreator
|
||||
// documentation inherited from interface BaseImageManager.OptimalImageCreator
|
||||
public BufferedImage createImage (int width, int height, int trans)
|
||||
{
|
||||
// DEBUG: override transparency for the moment on all images
|
||||
|
||||
@@ -39,7 +39,7 @@ public class BackedVolatileMirage extends VolatileMirage
|
||||
* Creates a mirage with the supplied regeneration informoation and
|
||||
* prepared image.
|
||||
*/
|
||||
public BackedVolatileMirage (ImageManager imgr, BufferedImage source)
|
||||
public BackedVolatileMirage (BaseImageManager imgr, BufferedImage source)
|
||||
{
|
||||
super(imgr, new Rectangle(0, 0, source.getWidth(), source.getHeight()));
|
||||
_source = source;
|
||||
|
||||
@@ -0,0 +1,538 @@
|
||||
// $Id$
|
||||
|
||||
package com.threerings.media.image;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.samskivert.util.LRUHashMap;
|
||||
import com.samskivert.util.StringUtil;
|
||||
import com.samskivert.util.Throttle;
|
||||
import com.samskivert.util.Tuple;
|
||||
|
||||
import com.threerings.media.Log;
|
||||
import com.threerings.resource.ResourceManager;
|
||||
|
||||
/**
|
||||
* Provides a single point of access for image retrieval and caching. This does not include
|
||||
* any tie-in to runtime adjustments to control caching and mirage creation.
|
||||
*/
|
||||
public class BaseImageManager
|
||||
implements ImageUtil.ImageCreator
|
||||
{
|
||||
/**
|
||||
* Used to identify an image for caching and reconstruction.
|
||||
*/
|
||||
public static class ImageKey
|
||||
{
|
||||
/** The data provider from which this image's data is loaded. */
|
||||
public ImageDataProvider daprov;
|
||||
|
||||
/** The path used to identify the image to the data provider. */
|
||||
public String path;
|
||||
|
||||
protected ImageKey (ImageDataProvider daprov, String path)
|
||||
{
|
||||
this.daprov = daprov;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public int hashCode ()
|
||||
{
|
||||
return path.hashCode() ^ daprov.getIdent().hashCode();
|
||||
}
|
||||
|
||||
public boolean equals (Object other)
|
||||
{
|
||||
if (other == null || !(other instanceof ImageKey)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ImageKey okey = (ImageKey)other;
|
||||
return ((okey.daprov.getIdent().equals(daprov.getIdent())) &&
|
||||
(okey.path.equals(path)));
|
||||
}
|
||||
|
||||
public String toString ()
|
||||
{
|
||||
return daprov.getIdent() + ":" + path;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This interface allows the image manager to create images that are in a format optimal for
|
||||
* rendering to the screen.
|
||||
*/
|
||||
public interface OptimalImageCreator
|
||||
{
|
||||
/**
|
||||
* Requests that a blank image be created that is in a format and of a depth that are
|
||||
* optimal for rendering to the screen.
|
||||
*/
|
||||
public BufferedImage createImage (int width, int height, int trans);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an image manager with the specified {@link ResourceManager} from which it will
|
||||
* obtain its data.
|
||||
*/
|
||||
public BaseImageManager (ResourceManager rmgr, OptimalImageCreator icreator)
|
||||
{
|
||||
_rmgr = rmgr;
|
||||
_icreator = icreator;
|
||||
|
||||
// create our image cache
|
||||
int icsize = getCacheSize();
|
||||
Log.debug("Creating image cache [size=" + icsize + "k].");
|
||||
_ccache = new LRUHashMap(icsize * 1024, new LRUHashMap.ItemSizer() {
|
||||
public int computeSize (Object value) {
|
||||
return (int)((CacheRecord)value).getEstimatedMemoryUsage();
|
||||
}
|
||||
});
|
||||
_ccache.setTracking(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience constructor that creates an {@link AWTImageCreator} for use by the image
|
||||
* manager.
|
||||
*/
|
||||
public BaseImageManager (ResourceManager rmgr, Component context)
|
||||
{
|
||||
this(rmgr, new AWTImageCreator(context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns how much space we're willing to use for caching images.
|
||||
*/
|
||||
public int getCacheSize ()
|
||||
{
|
||||
return DEFAULT_CACHE_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all images out of the cache.
|
||||
*/
|
||||
public void clearCache ()
|
||||
{
|
||||
Log.info("Clearing image manager cache.");
|
||||
|
||||
_ccache.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a buffered image, optimized for display on our graphics device.
|
||||
*/
|
||||
public BufferedImage createImage (int width, int height, int transparency)
|
||||
{
|
||||
return _icreator.createImage(width, height, transparency);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads (and caches) the specified image from the resource manager using the supplied path to
|
||||
* identify the image.
|
||||
*/
|
||||
public BufferedImage getImage (String path)
|
||||
{
|
||||
return getImage(null, path, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like {@link #getImage(String)} but the specified colorizations are applied to the image
|
||||
* before it is returned.
|
||||
*/
|
||||
public BufferedImage getImage (String path, Colorization[] zations)
|
||||
{
|
||||
return getImage(null, path, zations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like {@link #getImage(String)} but the image is loaded from the specified resource set
|
||||
* rathern than the default resource set.
|
||||
*/
|
||||
public BufferedImage getImage (String rset, String path)
|
||||
{
|
||||
return getImage(rset, path, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like {@link #getImage(String,String)} but the specified colorizations are applied to the
|
||||
* image before it is returned.
|
||||
*/
|
||||
public BufferedImage getImage (String rset, String path, Colorization[] zations)
|
||||
{
|
||||
if (StringUtil.isBlank(path)) {
|
||||
String errmsg = "Invalid image path [rset=" + rset + ", path=" + path + "]";
|
||||
throw new IllegalArgumentException(errmsg);
|
||||
}
|
||||
return getImage(getImageKey(rset, path), zations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads (and caches) the specified image from the resource manager using the supplied path to
|
||||
* identify the image.
|
||||
*
|
||||
* <p> Additionally the image is optimized for display in the current graphics
|
||||
* configuration. Consider using {@link #getMirage(ImageKey)} instead of prepared images as
|
||||
* they (some day) will automatically use volatile images to increase performance.
|
||||
*/
|
||||
public BufferedImage getPreparedImage (String path)
|
||||
{
|
||||
return getPreparedImage(null, path, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads (and caches) the specified image from the resource manager, obtaining the image from
|
||||
* the supplied resource set.
|
||||
*
|
||||
* <p> Additionally the image is optimized for display in the current graphics
|
||||
* configuration. Consider using {@link #getMirage(ImageKey)} instead of prepared images as
|
||||
* they (some day) will automatically use volatile images to increase performance.
|
||||
*/
|
||||
public BufferedImage getPreparedImage (String rset, String path)
|
||||
{
|
||||
return getPreparedImage(rset, path, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads (and caches) the specified image from the resource manager, obtaining the image from
|
||||
* the supplied resource set and applying the using the supplied path to identify the image.
|
||||
*
|
||||
* <p> Additionally the image is optimized for display in the current graphics
|
||||
* configuration. Consider using {@link #getMirage(ImageKey,Colorization[])} instead of
|
||||
* prepared images as they (some day) will automatically use volatile images to increase
|
||||
* performance.
|
||||
*/
|
||||
public BufferedImage getPreparedImage (String rset, String path, Colorization[] zations)
|
||||
{
|
||||
BufferedImage image = getImage(rset, path, zations);
|
||||
BufferedImage prepped = null;
|
||||
if (image != null) {
|
||||
prepped = createImage(image.getWidth(), image.getHeight(),
|
||||
image.getColorModel().getTransparency());
|
||||
Graphics2D pg = prepped.createGraphics();
|
||||
pg.drawImage(image, 0, 0, null);
|
||||
pg.dispose();
|
||||
}
|
||||
return prepped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an image key that can be used to fetch the image identified by the specified
|
||||
* resource set and image path.
|
||||
*/
|
||||
public ImageKey getImageKey (String rset, String path)
|
||||
{
|
||||
return getImageKey(getDataProvider(rset), path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an image key that can be used to fetch the image identified by the specified data
|
||||
* provider and image path.
|
||||
*/
|
||||
public ImageKey getImageKey (ImageDataProvider daprov, String path)
|
||||
{
|
||||
return new ImageKey(daprov, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the image identified by the specified key, caching if possible. The image will be
|
||||
* recolored using the supplied colorizations if requested.
|
||||
*/
|
||||
public BufferedImage getImage (ImageKey key, Colorization[] zations)
|
||||
{
|
||||
CacheRecord crec = null;
|
||||
synchronized (_ccache) {
|
||||
crec = (CacheRecord)_ccache.get(key);
|
||||
}
|
||||
if (crec != null) {
|
||||
// Log.info("Cache hit [key=" + key + ", crec=" + crec + "].");
|
||||
return crec.getImage(zations, _ccache);
|
||||
}
|
||||
// Log.info("Cache miss [key=" + key + ", crec=" + crec + "].");
|
||||
|
||||
// load up the raw image
|
||||
BufferedImage image = loadImage(key);
|
||||
if (image == null) {
|
||||
Log.warning("Failed to load image " + key + ".");
|
||||
// create a blank image instead
|
||||
image = new BufferedImage(10, 10, BufferedImage.TYPE_BYTE_INDEXED);
|
||||
}
|
||||
|
||||
// Log.info("Loaded " + key.path + ", image=" + image +
|
||||
// ", size=" + ImageUtil.getEstimatedMemoryUsage(image));
|
||||
|
||||
// create a cache record
|
||||
crec = new CacheRecord(key, image);
|
||||
synchronized (_ccache) {
|
||||
_ccache.put(key, crec);
|
||||
}
|
||||
_keySet.add(key);
|
||||
|
||||
// periodically report our image cache performance
|
||||
reportCachePerformance();
|
||||
|
||||
return crec.getImage(zations, _ccache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a mirage which is an image optimized for display on our current display device and
|
||||
* which will be stored into video memory if possible.
|
||||
*/
|
||||
public Mirage getMirage (String rsrcPath)
|
||||
{
|
||||
return getMirage(getImageKey(_defaultProvider, rsrcPath), null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a mirage which is an image optimized for display on our current display device and
|
||||
* which will be stored into video memory if possible.
|
||||
*/
|
||||
public Mirage getMirage (ImageKey key)
|
||||
{
|
||||
return getMirage(key, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like {@link #getMirage(ImageKey)} but that only the specified subimage of the source image
|
||||
* is used to build the mirage.
|
||||
*/
|
||||
public Mirage getMirage (ImageKey key, Rectangle bounds)
|
||||
{
|
||||
return getMirage(key, bounds, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like {@link #getMirage(ImageKey)} but the supplied colorizations are applied to the source
|
||||
* image before creating the mirage.
|
||||
*/
|
||||
public Mirage getMirage (ImageKey key, Colorization[] zations)
|
||||
{
|
||||
return getMirage(key, null, zations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like {@link #getMirage(ImageKey,Colorization[])} except that the mirage is created using
|
||||
* only the specified subset of the original image.
|
||||
*/
|
||||
public Mirage getMirage (ImageKey key, Rectangle bounds, Colorization[] zations)
|
||||
{
|
||||
BufferedImage src = null;
|
||||
|
||||
float percentageOfDataBuffer = 1;
|
||||
if (bounds == null) {
|
||||
// if they specified no bounds, we need to load up the raw image and determine its
|
||||
// bounds so that we can pass those along to the created mirage
|
||||
src = getImage(key, zations);
|
||||
bounds = new Rectangle(0, 0, src.getWidth(), src.getHeight());
|
||||
|
||||
}
|
||||
|
||||
return new CachedVolatileMirage(this, key, bounds, zations);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the image creator that can be used to create buffered images optimized for rendering
|
||||
* to the screen.
|
||||
*/
|
||||
public OptimalImageCreator getImageCreator ()
|
||||
{
|
||||
return _icreator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data provider configured to obtain image data from the specified resource set.
|
||||
*/
|
||||
protected ImageDataProvider getDataProvider (final String rset)
|
||||
{
|
||||
if (rset == null) {
|
||||
return _defaultProvider;
|
||||
}
|
||||
|
||||
ImageDataProvider dprov = (ImageDataProvider)_providers.get(rset);
|
||||
if (dprov == null) {
|
||||
dprov = new ImageDataProvider() {
|
||||
public BufferedImage loadImage (String path)
|
||||
throws IOException {
|
||||
// first attempt to load the image from the specified resource set
|
||||
try {
|
||||
return _rmgr.getImageResource(rset, path);
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
// fall back to trying the classpath
|
||||
return _rmgr.getImageResource(path);
|
||||
}
|
||||
}
|
||||
|
||||
public String getIdent () {
|
||||
return "rmgr:" + rset;
|
||||
}
|
||||
};
|
||||
_providers.put(rset, dprov);
|
||||
}
|
||||
|
||||
return dprov;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads and returns the image with the specified key from the supplied data provider.
|
||||
*/
|
||||
protected BufferedImage loadImage (ImageKey key)
|
||||
{
|
||||
// if (EventQueue.isDispatchThread()) {
|
||||
// Log.info("Loading image on AWT thread " + key + ".");
|
||||
// }
|
||||
|
||||
BufferedImage image = null;
|
||||
try {
|
||||
Log.debug("Loading image " + key + ".");
|
||||
image = key.daprov.loadImage(key.path);
|
||||
if (image == null) {
|
||||
Log.warning("ImageDataProvider.loadImage(" + key + ") returned null.");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.warning("Unable to load image '" + key + "'.");
|
||||
Log.logStackTrace(e);
|
||||
|
||||
// create a blank image in its stead
|
||||
image = createImage(1, 1, Transparency.OPAQUE);
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports statistics detailing the image manager cache performance and the current size of the
|
||||
* cached images.
|
||||
*/
|
||||
protected void reportCachePerformance ()
|
||||
{
|
||||
if (/* Log.getLevel() != Log.log.DEBUG || */
|
||||
_cacheStatThrottle.throttleOp()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// compute our estimated memory usage
|
||||
long size = 0;
|
||||
|
||||
int[] eff = null;
|
||||
synchronized (_ccache) {
|
||||
Iterator iter = _ccache.values().iterator();
|
||||
while (iter.hasNext()) {
|
||||
size += ((CacheRecord)iter.next()).getEstimatedMemoryUsage();
|
||||
}
|
||||
eff = _ccache.getTrackedEffectiveness();
|
||||
}
|
||||
Log.info("ImageManager LRU [mem=" + (size / 1024) + "k, size=" + _ccache.size() +
|
||||
", hits=" + eff[0] + ", misses=" + eff[1] + ", totalKeys=" + _keySet.size() + "].");
|
||||
}
|
||||
|
||||
/** Maintains a source image and a set of colorized versions in the image cache. */
|
||||
protected static class CacheRecord
|
||||
{
|
||||
public CacheRecord (ImageKey key, BufferedImage source)
|
||||
{
|
||||
_key = key;
|
||||
_source = source;
|
||||
}
|
||||
|
||||
public BufferedImage getImage (Colorization[] zations, LRUHashMap cache)
|
||||
{
|
||||
if (zations == null) {
|
||||
return _source;
|
||||
}
|
||||
|
||||
if (_colorized == null) {
|
||||
_colorized = new ArrayList<Tuple<Colorization[], BufferedImage>>();
|
||||
}
|
||||
|
||||
// we search linearly through our list of colorized copies because it is not likely to
|
||||
// be very long
|
||||
int csize = _colorized.size();
|
||||
for (int ii = 0; ii < csize; ii++) {
|
||||
Tuple<Colorization[], BufferedImage> tup = _colorized.get(ii);
|
||||
Colorization[] tzations = tup.left;
|
||||
if (Arrays.equals(zations, tzations)) {
|
||||
return tup.right;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
BufferedImage cimage = ImageUtil.recolorImage(_source, zations);
|
||||
_colorized.add(new Tuple<Colorization[], BufferedImage>(zations, cimage));
|
||||
cache.adjustSize((int)ImageUtil.getEstimatedMemoryUsage(cimage));
|
||||
return cimage;
|
||||
|
||||
} catch (Exception re) {
|
||||
Log.warning("Failure recoloring image [source" + _key +
|
||||
", zations=" + StringUtil.toString(zations) + ", error=" + re + "].");
|
||||
// return the uncolorized version
|
||||
return _source;
|
||||
}
|
||||
}
|
||||
|
||||
public long getEstimatedMemoryUsage ()
|
||||
{
|
||||
long usage = ImageUtil.getEstimatedMemoryUsage(_source);
|
||||
if (_colorized != null) {
|
||||
for (Tuple<Colorization[], BufferedImage> tup : _colorized) {
|
||||
usage += ImageUtil.getEstimatedMemoryUsage(tup.right);
|
||||
}
|
||||
}
|
||||
return usage;
|
||||
}
|
||||
|
||||
public String toString ()
|
||||
{
|
||||
return "[key=" + _key + ", wid=" + _source.getWidth() + ", hei=" + _source.getHeight() +
|
||||
", ccount=" + ((_colorized == null) ? 0 : _colorized.size()) + "]";
|
||||
}
|
||||
|
||||
protected ImageKey _key;
|
||||
protected BufferedImage _source;
|
||||
protected ArrayList<Tuple<Colorization[], BufferedImage>> _colorized;
|
||||
}
|
||||
|
||||
/** A reference to the resource manager via which we load image data by default. */
|
||||
protected ResourceManager _rmgr;
|
||||
|
||||
/** We use this to create images optimized for rendering. */
|
||||
protected OptimalImageCreator _icreator;
|
||||
|
||||
/** A cache of loaded images. */
|
||||
protected LRUHashMap _ccache;
|
||||
|
||||
/** The set of all keys we've ever seen. */
|
||||
protected HashSet _keySet = new HashSet();
|
||||
|
||||
/** Throttle our cache status logging to once every 300 seconds. */
|
||||
protected Throttle _cacheStatThrottle = new Throttle(1, 300000L);
|
||||
|
||||
/** Our default data provider. */
|
||||
protected ImageDataProvider _defaultProvider = new ImageDataProvider() {
|
||||
public BufferedImage loadImage (String path) throws IOException {
|
||||
return _rmgr.getImageResource(path);
|
||||
}
|
||||
public String getIdent () {
|
||||
return "rmgr:default";
|
||||
}
|
||||
};
|
||||
|
||||
/** Data providers for different resource sets. */
|
||||
protected HashMap _providers = new HashMap();
|
||||
|
||||
/** Default amount of data we'll store in our image cache. */
|
||||
protected static int DEFAULT_CACHE_SIZE = 32768;
|
||||
}
|
||||
@@ -35,7 +35,7 @@ import com.threerings.media.Log;
|
||||
* for some other reason.
|
||||
*
|
||||
* <p> These objects are never created directly, but always obtained from
|
||||
* the {@link ImageManager}.
|
||||
* the {@link BaseImageManager}.
|
||||
*/
|
||||
public class CachedVolatileMirage extends VolatileMirage
|
||||
{
|
||||
@@ -44,7 +44,7 @@ public class CachedVolatileMirage extends VolatileMirage
|
||||
* prepared image.
|
||||
*/
|
||||
protected CachedVolatileMirage (
|
||||
ImageManager imgr, ImageManager.ImageKey source,
|
||||
BaseImageManager imgr, BaseImageManager.ImageKey source,
|
||||
Rectangle bounds, Colorization[] zations)
|
||||
{
|
||||
super(imgr, bounds);
|
||||
@@ -96,7 +96,7 @@ public class CachedVolatileMirage extends VolatileMirage
|
||||
|
||||
/** The key that identifies the image data used to create our volatile
|
||||
* image. */
|
||||
protected ImageManager.ImageKey _source;
|
||||
protected BaseImageManager.ImageKey _source;
|
||||
|
||||
/** Optional colorizations that are applied to our source image when
|
||||
* creating our mirage. */
|
||||
|
||||
@@ -22,324 +22,42 @@
|
||||
package com.threerings.media.image;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.samskivert.swing.RuntimeAdjust;
|
||||
import com.samskivert.util.LRUHashMap;
|
||||
import com.samskivert.util.StringUtil;
|
||||
import com.samskivert.util.Throttle;
|
||||
import com.samskivert.util.Tuple;
|
||||
|
||||
import com.threerings.media.Log;
|
||||
import com.threerings.media.MediaPrefs;
|
||||
import com.threerings.resource.ResourceManager;
|
||||
|
||||
/**
|
||||
* Provides a single point of access for image retrieval and caching.
|
||||
* Provides a single point of access for image retrieval and caching - just like the
|
||||
* BaseImageManager but adds a tie in to the RuntimeAdjust system to control caching and
|
||||
* mirage creation.
|
||||
*/
|
||||
public class ImageManager
|
||||
implements ImageUtil.ImageCreator
|
||||
public class ImageManager extends BaseImageManager
|
||||
{
|
||||
/**
|
||||
* Used to identify an image for caching and reconstruction.
|
||||
*/
|
||||
public static class ImageKey
|
||||
{
|
||||
/** The data provider from which this image's data is loaded. */
|
||||
public ImageDataProvider daprov;
|
||||
|
||||
/** The path used to identify the image to the data provider. */
|
||||
public String path;
|
||||
|
||||
protected ImageKey (ImageDataProvider daprov, String path)
|
||||
{
|
||||
this.daprov = daprov;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public int hashCode ()
|
||||
{
|
||||
return path.hashCode() ^ daprov.getIdent().hashCode();
|
||||
}
|
||||
|
||||
public boolean equals (Object other)
|
||||
{
|
||||
if (other == null || !(other instanceof ImageKey)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ImageKey okey = (ImageKey)other;
|
||||
return ((okey.daprov.getIdent().equals(daprov.getIdent())) &&
|
||||
(okey.path.equals(path)));
|
||||
}
|
||||
|
||||
public String toString ()
|
||||
{
|
||||
return daprov.getIdent() + ":" + path;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This interface allows the image manager to create images that are in a format optimal for
|
||||
* rendering to the screen.
|
||||
*/
|
||||
public interface OptimalImageCreator
|
||||
{
|
||||
/**
|
||||
* Requests that a blank image be created that is in a format and of a depth that are
|
||||
* optimal for rendering to the screen.
|
||||
*/
|
||||
public BufferedImage createImage (int width, int height, int trans);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an image manager with the specified {@link ResourceManager} from which it will
|
||||
* obtain its data.
|
||||
*/
|
||||
public ImageManager (ResourceManager rmgr, OptimalImageCreator icreator)
|
||||
{
|
||||
_rmgr = rmgr;
|
||||
_icreator = icreator;
|
||||
|
||||
// create our image cache
|
||||
int icsize = _cacheSize.getValue();
|
||||
Log.debug("Creating image cache [size=" + icsize + "k].");
|
||||
_ccache = new LRUHashMap(icsize * 1024, new LRUHashMap.ItemSizer() {
|
||||
public int computeSize (Object value) {
|
||||
return (int)((CacheRecord)value).getEstimatedMemoryUsage();
|
||||
}
|
||||
});
|
||||
_ccache.setTracking(true);
|
||||
super(rmgr, icreator);
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience constructor that creates an {@link AWTImageCreator} for use by the image
|
||||
* manager.
|
||||
*/
|
||||
public ImageManager (ResourceManager rmgr, Component context)
|
||||
{
|
||||
this(rmgr, new AWTImageCreator(context));
|
||||
super(rmgr, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all images out of the cache.
|
||||
*/
|
||||
public void clearCache ()
|
||||
@Override
|
||||
public int getCacheSize ()
|
||||
{
|
||||
Log.info("Clearing image manager cache.");
|
||||
|
||||
_ccache.clear();
|
||||
return _cacheSize.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a buffered image, optimized for display on our graphics device.
|
||||
*/
|
||||
public BufferedImage createImage (int width, int height, int transparency)
|
||||
{
|
||||
return _icreator.createImage(width, height, transparency);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads (and caches) the specified image from the resource manager using the supplied path to
|
||||
* identify the image.
|
||||
*/
|
||||
public BufferedImage getImage (String path)
|
||||
{
|
||||
return getImage(null, path, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like {@link #getImage(String)} but the specified colorizations are applied to the image
|
||||
* before it is returned.
|
||||
*/
|
||||
public BufferedImage getImage (String path, Colorization[] zations)
|
||||
{
|
||||
return getImage(null, path, zations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like {@link #getImage(String)} but the image is loaded from the specified resource set
|
||||
* rathern than the default resource set.
|
||||
*/
|
||||
public BufferedImage getImage (String rset, String path)
|
||||
{
|
||||
return getImage(rset, path, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like {@link #getImage(String,String)} but the specified colorizations are applied to the
|
||||
* image before it is returned.
|
||||
*/
|
||||
public BufferedImage getImage (String rset, String path, Colorization[] zations)
|
||||
{
|
||||
if (StringUtil.isBlank(path)) {
|
||||
String errmsg = "Invalid image path [rset=" + rset + ", path=" + path + "]";
|
||||
throw new IllegalArgumentException(errmsg);
|
||||
}
|
||||
return getImage(getImageKey(rset, path), zations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads (and caches) the specified image from the resource manager using the supplied path to
|
||||
* identify the image.
|
||||
*
|
||||
* <p> Additionally the image is optimized for display in the current graphics
|
||||
* configuration. Consider using {@link #getMirage(ImageKey)} instead of prepared images as
|
||||
* they (some day) will automatically use volatile images to increase performance.
|
||||
*/
|
||||
public BufferedImage getPreparedImage (String path)
|
||||
{
|
||||
return getPreparedImage(null, path, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads (and caches) the specified image from the resource manager, obtaining the image from
|
||||
* the supplied resource set.
|
||||
*
|
||||
* <p> Additionally the image is optimized for display in the current graphics
|
||||
* configuration. Consider using {@link #getMirage(ImageKey)} instead of prepared images as
|
||||
* they (some day) will automatically use volatile images to increase performance.
|
||||
*/
|
||||
public BufferedImage getPreparedImage (String rset, String path)
|
||||
{
|
||||
return getPreparedImage(rset, path, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads (and caches) the specified image from the resource manager, obtaining the image from
|
||||
* the supplied resource set and applying the using the supplied path to identify the image.
|
||||
*
|
||||
* <p> Additionally the image is optimized for display in the current graphics
|
||||
* configuration. Consider using {@link #getMirage(ImageKey,Colorization[])} instead of
|
||||
* prepared images as they (some day) will automatically use volatile images to increase
|
||||
* performance.
|
||||
*/
|
||||
public BufferedImage getPreparedImage (String rset, String path, Colorization[] zations)
|
||||
{
|
||||
BufferedImage image = getImage(rset, path, zations);
|
||||
BufferedImage prepped = null;
|
||||
if (image != null) {
|
||||
prepped = createImage(image.getWidth(), image.getHeight(),
|
||||
image.getColorModel().getTransparency());
|
||||
Graphics2D pg = prepped.createGraphics();
|
||||
pg.drawImage(image, 0, 0, null);
|
||||
pg.dispose();
|
||||
}
|
||||
return prepped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an image key that can be used to fetch the image identified by the specified
|
||||
* resource set and image path.
|
||||
*/
|
||||
public ImageKey getImageKey (String rset, String path)
|
||||
{
|
||||
return getImageKey(getDataProvider(rset), path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an image key that can be used to fetch the image identified by the specified data
|
||||
* provider and image path.
|
||||
*/
|
||||
public ImageKey getImageKey (ImageDataProvider daprov, String path)
|
||||
{
|
||||
return new ImageKey(daprov, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the image identified by the specified key, caching if possible. The image will be
|
||||
* recolored using the supplied colorizations if requested.
|
||||
*/
|
||||
public BufferedImage getImage (ImageKey key, Colorization[] zations)
|
||||
{
|
||||
CacheRecord crec = null;
|
||||
synchronized (_ccache) {
|
||||
crec = (CacheRecord)_ccache.get(key);
|
||||
}
|
||||
if (crec != null) {
|
||||
// Log.info("Cache hit [key=" + key + ", crec=" + crec + "].");
|
||||
return crec.getImage(zations, _ccache);
|
||||
}
|
||||
// Log.info("Cache miss [key=" + key + ", crec=" + crec + "].");
|
||||
|
||||
// load up the raw image
|
||||
BufferedImage image = loadImage(key);
|
||||
if (image == null) {
|
||||
Log.warning("Failed to load image " + key + ".");
|
||||
// create a blank image instead
|
||||
image = new BufferedImage(10, 10, BufferedImage.TYPE_BYTE_INDEXED);
|
||||
}
|
||||
|
||||
// Log.info("Loaded " + key.path + ", image=" + image +
|
||||
// ", size=" + ImageUtil.getEstimatedMemoryUsage(image));
|
||||
|
||||
// create a cache record
|
||||
crec = new CacheRecord(key, image);
|
||||
synchronized (_ccache) {
|
||||
_ccache.put(key, crec);
|
||||
}
|
||||
_keySet.add(key);
|
||||
|
||||
// periodically report our image cache performance
|
||||
reportCachePerformance();
|
||||
|
||||
return crec.getImage(zations, _ccache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a mirage which is an image optimized for display on our current display device and
|
||||
* which will be stored into video memory if possible.
|
||||
*/
|
||||
public Mirage getMirage (String rsrcPath)
|
||||
{
|
||||
return getMirage(getImageKey(_defaultProvider, rsrcPath), null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a mirage which is an image optimized for display on our current display device and
|
||||
* which will be stored into video memory if possible.
|
||||
*/
|
||||
public Mirage getMirage (ImageKey key)
|
||||
{
|
||||
return getMirage(key, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like {@link #getMirage(ImageKey)} but that only the specified subimage of the source image
|
||||
* is used to build the mirage.
|
||||
*/
|
||||
public Mirage getMirage (ImageKey key, Rectangle bounds)
|
||||
{
|
||||
return getMirage(key, bounds, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like {@link #getMirage(ImageKey)} but the supplied colorizations are applied to the source
|
||||
* image before creating the mirage.
|
||||
*/
|
||||
public Mirage getMirage (ImageKey key, Colorization[] zations)
|
||||
{
|
||||
return getMirage(key, null, zations);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like {@link #getMirage(ImageKey,Colorization[])} except that the mirage is created using
|
||||
* only the specified subset of the original image.
|
||||
*/
|
||||
@Override
|
||||
public Mirage getMirage (ImageKey key, Rectangle bounds, Colorization[] zations)
|
||||
{
|
||||
// We need to do something more complicated than the BaseImageManager because our
|
||||
// runtime adjustments may affect how we create our mirages.
|
||||
|
||||
BufferedImage src = null;
|
||||
|
||||
float percentageOfDataBuffer = 1;
|
||||
@@ -365,200 +83,10 @@ public class ImageManager
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the image creator that can be used to create buffered images optimized for rendering
|
||||
* to the screen.
|
||||
*/
|
||||
public OptimalImageCreator getImageCreator ()
|
||||
{
|
||||
return _icreator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data provider configured to obtain image data from the specified resource set.
|
||||
*/
|
||||
protected ImageDataProvider getDataProvider (final String rset)
|
||||
{
|
||||
if (rset == null) {
|
||||
return _defaultProvider;
|
||||
}
|
||||
|
||||
ImageDataProvider dprov = (ImageDataProvider)_providers.get(rset);
|
||||
if (dprov == null) {
|
||||
dprov = new ImageDataProvider() {
|
||||
public BufferedImage loadImage (String path)
|
||||
throws IOException {
|
||||
// first attempt to load the image from the specified resource set
|
||||
try {
|
||||
return _rmgr.getImageResource(rset, path);
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
// fall back to trying the classpath
|
||||
return _rmgr.getImageResource(path);
|
||||
}
|
||||
}
|
||||
|
||||
public String getIdent () {
|
||||
return "rmgr:" + rset;
|
||||
}
|
||||
};
|
||||
_providers.put(rset, dprov);
|
||||
}
|
||||
|
||||
return dprov;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads and returns the image with the specified key from the supplied data provider.
|
||||
*/
|
||||
protected BufferedImage loadImage (ImageKey key)
|
||||
{
|
||||
// if (EventQueue.isDispatchThread()) {
|
||||
// Log.info("Loading image on AWT thread " + key + ".");
|
||||
// }
|
||||
|
||||
BufferedImage image = null;
|
||||
try {
|
||||
Log.debug("Loading image " + key + ".");
|
||||
image = key.daprov.loadImage(key.path);
|
||||
if (image == null) {
|
||||
Log.warning("ImageDataProvider.loadImage(" + key + ") returned null.");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.warning("Unable to load image '" + key + "'.");
|
||||
Log.logStackTrace(e);
|
||||
|
||||
// create a blank image in its stead
|
||||
image = createImage(1, 1, Transparency.OPAQUE);
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports statistics detailing the image manager cache performance and the current size of the
|
||||
* cached images.
|
||||
*/
|
||||
protected void reportCachePerformance ()
|
||||
{
|
||||
if (/* Log.getLevel() != Log.log.DEBUG || */
|
||||
_cacheStatThrottle.throttleOp()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// compute our estimated memory usage
|
||||
long size = 0;
|
||||
|
||||
int[] eff = null;
|
||||
synchronized (_ccache) {
|
||||
Iterator iter = _ccache.values().iterator();
|
||||
while (iter.hasNext()) {
|
||||
size += ((CacheRecord)iter.next()).getEstimatedMemoryUsage();
|
||||
}
|
||||
eff = _ccache.getTrackedEffectiveness();
|
||||
}
|
||||
Log.info("ImageManager LRU [mem=" + (size / 1024) + "k, size=" + _ccache.size() +
|
||||
", hits=" + eff[0] + ", misses=" + eff[1] + ", totalKeys=" + _keySet.size() + "].");
|
||||
}
|
||||
|
||||
/** Maintains a source image and a set of colorized versions in the image cache. */
|
||||
protected static class CacheRecord
|
||||
{
|
||||
public CacheRecord (ImageKey key, BufferedImage source)
|
||||
{
|
||||
_key = key;
|
||||
_source = source;
|
||||
}
|
||||
|
||||
public BufferedImage getImage (Colorization[] zations, LRUHashMap cache)
|
||||
{
|
||||
if (zations == null) {
|
||||
return _source;
|
||||
}
|
||||
|
||||
if (_colorized == null) {
|
||||
_colorized = new ArrayList<Tuple<Colorization[], BufferedImage>>();
|
||||
}
|
||||
|
||||
// we search linearly through our list of colorized copies because it is not likely to
|
||||
// be very long
|
||||
int csize = _colorized.size();
|
||||
for (int ii = 0; ii < csize; ii++) {
|
||||
Tuple<Colorization[], BufferedImage> tup = _colorized.get(ii);
|
||||
Colorization[] tzations = tup.left;
|
||||
if (Arrays.equals(zations, tzations)) {
|
||||
return tup.right;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
BufferedImage cimage = ImageUtil.recolorImage(_source, zations);
|
||||
_colorized.add(new Tuple<Colorization[], BufferedImage>(zations, cimage));
|
||||
cache.adjustSize((int)ImageUtil.getEstimatedMemoryUsage(cimage));
|
||||
return cimage;
|
||||
|
||||
} catch (Exception re) {
|
||||
Log.warning("Failure recoloring image [source" + _key +
|
||||
", zations=" + StringUtil.toString(zations) + ", error=" + re + "].");
|
||||
// return the uncolorized version
|
||||
return _source;
|
||||
}
|
||||
}
|
||||
|
||||
public long getEstimatedMemoryUsage ()
|
||||
{
|
||||
long usage = ImageUtil.getEstimatedMemoryUsage(_source);
|
||||
if (_colorized != null) {
|
||||
for (Tuple<Colorization[], BufferedImage> tup : _colorized) {
|
||||
usage += ImageUtil.getEstimatedMemoryUsage(tup.right);
|
||||
}
|
||||
}
|
||||
return usage;
|
||||
}
|
||||
|
||||
public String toString ()
|
||||
{
|
||||
return "[key=" + _key + ", wid=" + _source.getWidth() + ", hei=" + _source.getHeight() +
|
||||
", ccount=" + ((_colorized == null) ? 0 : _colorized.size()) + "]";
|
||||
}
|
||||
|
||||
protected ImageKey _key;
|
||||
protected BufferedImage _source;
|
||||
protected ArrayList<Tuple<Colorization[], BufferedImage>> _colorized;
|
||||
}
|
||||
|
||||
/** A reference to the resource manager via which we load image data by default. */
|
||||
protected ResourceManager _rmgr;
|
||||
|
||||
/** We use this to create images optimized for rendering. */
|
||||
protected OptimalImageCreator _icreator;
|
||||
|
||||
/** A cache of loaded images. */
|
||||
protected LRUHashMap _ccache;
|
||||
|
||||
/** The set of all keys we've ever seen. */
|
||||
protected HashSet _keySet = new HashSet();
|
||||
|
||||
/** Throttle our cache status logging to once every 300 seconds. */
|
||||
protected Throttle _cacheStatThrottle = new Throttle(1, 300000L);
|
||||
|
||||
/** Our default data provider. */
|
||||
protected ImageDataProvider _defaultProvider = new ImageDataProvider() {
|
||||
public BufferedImage loadImage (String path) throws IOException {
|
||||
return _rmgr.getImageResource(path);
|
||||
}
|
||||
public String getIdent () {
|
||||
return "rmgr:default";
|
||||
}
|
||||
};
|
||||
|
||||
/** Data providers for different resource sets. */
|
||||
protected HashMap _providers = new HashMap();
|
||||
|
||||
/** Register our image cache size with the runtime adjustments framework. */
|
||||
protected static RuntimeAdjust.IntAdjust _cacheSize = new RuntimeAdjust.IntAdjust(
|
||||
"Size (in kb of memory used) of the image manager LRU cache [requires restart]",
|
||||
"narya.media.image.cache_size", MediaPrefs.config, 32768);
|
||||
"narya.media.image.cache_size", MediaPrefs.config, DEFAULT_CACHE_SIZE);
|
||||
|
||||
/** Controls whether or not we prepare images or use raw versions. */
|
||||
protected static RuntimeAdjust.BooleanAdjust _prepareImages = new RuntimeAdjust.BooleanAdjust(
|
||||
|
||||
@@ -39,7 +39,7 @@ public abstract class VolatileMirage implements Mirage
|
||||
/**
|
||||
* Informs the base class of its image manager and image bounds.
|
||||
*/
|
||||
protected VolatileMirage (ImageManager imgr, Rectangle bounds)
|
||||
protected VolatileMirage (BaseImageManager imgr, Rectangle bounds)
|
||||
{
|
||||
_imgr = imgr;
|
||||
_bounds = bounds;
|
||||
@@ -186,7 +186,7 @@ public abstract class VolatileMirage implements Mirage
|
||||
}
|
||||
|
||||
/** The image manager with whom we interoperate. */
|
||||
protected ImageManager _imgr;
|
||||
protected BaseImageManager _imgr;
|
||||
|
||||
/** The bounds of the region of our source image which we desire for
|
||||
* this mirage (possibly the whole thing). */
|
||||
|
||||
@@ -24,9 +24,9 @@ package com.threerings.media.tile;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import com.threerings.media.image.BaseImageManager;
|
||||
import com.threerings.media.image.Colorization;
|
||||
import com.threerings.media.image.ImageDataProvider;
|
||||
import com.threerings.media.image.ImageManager;
|
||||
import com.threerings.media.image.Mirage;
|
||||
|
||||
/**
|
||||
@@ -35,13 +35,13 @@ import com.threerings.media.image.Mirage;
|
||||
*/
|
||||
public class IMImageProvider implements ImageProvider
|
||||
{
|
||||
public IMImageProvider (ImageManager imgr, ImageDataProvider dprov)
|
||||
public IMImageProvider (BaseImageManager imgr, ImageDataProvider dprov)
|
||||
{
|
||||
_imgr = imgr;
|
||||
_dprov = dprov;
|
||||
}
|
||||
|
||||
public IMImageProvider (ImageManager imgr, String rset)
|
||||
public IMImageProvider (BaseImageManager imgr, String rset)
|
||||
{
|
||||
_imgr = imgr;
|
||||
_rset = rset;
|
||||
@@ -59,12 +59,12 @@ public class IMImageProvider implements ImageProvider
|
||||
return _imgr.getMirage(getImageKey(path), bounds, zations);
|
||||
}
|
||||
|
||||
protected final ImageManager.ImageKey getImageKey (String path)
|
||||
protected final BaseImageManager.ImageKey getImageKey (String path)
|
||||
{
|
||||
return (_dprov == null) ? _imgr.getImageKey(_rset, path) : _imgr.getImageKey(_dprov, path);
|
||||
}
|
||||
|
||||
protected ImageManager _imgr;
|
||||
protected BaseImageManager _imgr;
|
||||
protected ImageDataProvider _dprov;
|
||||
protected String _rset;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import java.util.HashMap;
|
||||
import com.samskivert.io.PersistenceException;
|
||||
|
||||
import com.threerings.media.Log;
|
||||
import com.threerings.media.image.ImageManager;
|
||||
import com.threerings.media.image.BaseImageManager;
|
||||
|
||||
/**
|
||||
* The tile manager provides a simplified interface for retrieving and
|
||||
@@ -55,7 +55,7 @@ public class TileManager
|
||||
* @param imgr the image manager via which the tile manager will
|
||||
* decode and cache images.
|
||||
*/
|
||||
public TileManager (ImageManager imgr)
|
||||
public TileManager (BaseImageManager imgr)
|
||||
{
|
||||
_imgr = imgr;
|
||||
_defaultProvider = new IMImageProvider(_imgr, (String)null);
|
||||
@@ -242,7 +242,7 @@ public class TileManager
|
||||
}
|
||||
|
||||
/** The entity through which we decode and cache images. */
|
||||
protected ImageManager _imgr;
|
||||
protected BaseImageManager _imgr;
|
||||
|
||||
/** A cache of tilesets that have been loaded by hand. */
|
||||
protected HashMap _handcache = new HashMap();
|
||||
|
||||
@@ -30,7 +30,7 @@ import com.threerings.resource.ResourceBundle;
|
||||
import com.threerings.resource.ResourceManager;
|
||||
|
||||
import com.threerings.media.Log;
|
||||
import com.threerings.media.image.ImageManager;
|
||||
import com.threerings.media.image.BaseImageManager;
|
||||
import com.threerings.media.tile.IMImageProvider;
|
||||
import com.threerings.media.tile.NoSuchTileSetException;
|
||||
import com.threerings.media.tile.TileSet;
|
||||
@@ -57,7 +57,7 @@ public class BundledTileSetRepository
|
||||
* loading our tile data.
|
||||
*/
|
||||
public BundledTileSetRepository (final ResourceManager rmgr,
|
||||
final ImageManager imgr,
|
||||
final BaseImageManager imgr,
|
||||
final String name)
|
||||
{
|
||||
_imgr = imgr;
|
||||
@@ -222,7 +222,7 @@ public class BundledTileSetRepository
|
||||
}
|
||||
|
||||
/** The image manager via which we load our images. */
|
||||
protected ImageManager _imgr;
|
||||
protected BaseImageManager _imgr;
|
||||
|
||||
/** A mapping from tileset id to tileset. */
|
||||
protected HashIntMap _idmap;
|
||||
|
||||
@@ -30,8 +30,8 @@ import java.util.HashMap;
|
||||
import com.samskivert.util.CheapIntMap;
|
||||
import com.samskivert.util.QuickSort;
|
||||
|
||||
import com.threerings.media.image.BaseImageManager;
|
||||
import com.threerings.media.image.BufferedMirage;
|
||||
import com.threerings.media.image.ImageManager;
|
||||
import com.threerings.media.image.ImageUtil;
|
||||
|
||||
import com.threerings.media.tile.NoSuchTileSetException;
|
||||
@@ -53,7 +53,7 @@ public class AutoFringer
|
||||
* Constructs an instance that will fringe according to the rules in
|
||||
* the supplied fringe configuration.
|
||||
*/
|
||||
public AutoFringer (FringeConfiguration fringeconf, ImageManager imgr,
|
||||
public AutoFringer (FringeConfiguration fringeconf, BaseImageManager imgr,
|
||||
TileManager tmgr)
|
||||
{
|
||||
_fringeconf = fringeconf;
|
||||
@@ -399,7 +399,7 @@ public class AutoFringer
|
||||
}
|
||||
}
|
||||
|
||||
protected ImageManager _imgr;
|
||||
protected BaseImageManager _imgr;
|
||||
protected TileManager _tmgr;
|
||||
protected FringeConfiguration _fringeconf;
|
||||
protected CheapIntMap _fringers = new CheapIntMap(16);
|
||||
|
||||
@@ -29,7 +29,7 @@ import com.samskivert.io.StreamUtil;
|
||||
import com.threerings.resource.ResourceManager;
|
||||
import com.threerings.util.CompiledConfig;
|
||||
|
||||
import com.threerings.media.image.ImageManager;
|
||||
import com.threerings.media.image.BaseImageManager;
|
||||
import com.threerings.media.tile.TileManager;
|
||||
|
||||
import com.threerings.miso.Log;
|
||||
@@ -47,7 +47,7 @@ public class MisoTileManager extends TileManager
|
||||
* @param imgr the image manager via which the tile manager will
|
||||
* decode and cache images.
|
||||
*/
|
||||
public MisoTileManager (ResourceManager rmgr, ImageManager imgr)
|
||||
public MisoTileManager (ResourceManager rmgr, BaseImageManager imgr)
|
||||
{
|
||||
super(imgr);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user