mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 10:48:00 +00:00
fix a number of issues in ImageCache
- correctly load no_card.jpg when Forge is not run from a bundle - use skinned "unknown" icon when icon not found instead of default card picture - don't redo image resize when an image is resized to a size that is already in the cache, just under a different key
This commit is contained in:
@@ -18,8 +18,10 @@
|
|||||||
package forge;
|
package forge;
|
||||||
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.IOException;
|
import java.io.File;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
@@ -70,22 +72,30 @@ public class ImageCache {
|
|||||||
public static final String PRECON_PREFIX = "p:";
|
public static final String PRECON_PREFIX = "p:";
|
||||||
public static final String TOURNAMENTPACK_PREFIX = "o:";
|
public static final String TOURNAMENTPACK_PREFIX = "o:";
|
||||||
|
|
||||||
static private final LoadingCache<String, BufferedImage> CACHE = CacheBuilder.newBuilder().softValues().build(new ImageLoader());
|
private static final Set<String> _missingIconKeys = new HashSet<String>();
|
||||||
private static final BufferedImage emptyImage = new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB);
|
private static final LoadingCache<String, BufferedImage> _CACHE = CacheBuilder.newBuilder().softValues().build(new ImageLoader());
|
||||||
private static BufferedImage defaultImage = emptyImage;
|
private static final BufferedImage _defaultImage;
|
||||||
static {
|
static {
|
||||||
|
BufferedImage defImage = null;
|
||||||
try {
|
try {
|
||||||
ClassLoader cl = Thread.currentThread().getContextClassLoader();
|
ClassLoader cl = Thread.currentThread().getContextClassLoader();
|
||||||
InputStream isNoCardJpg = cl.getResourceAsStream("no_card.jpg");
|
InputStream isNoCardJpg = cl.getResourceAsStream("no_card.jpg");
|
||||||
defaultImage = ImageIO.read(isNoCardJpg);
|
defImage = ImageIO.read(isNoCardJpg);
|
||||||
} catch (IOException e) {
|
} catch (Exception e) {
|
||||||
// TODO Auto-generated catch block ignores the exception, but sends it to System.err and probably forge.log.
|
// resource not found; perhaps we're running straight from source
|
||||||
e.printStackTrace();
|
try {
|
||||||
|
defImage = ImageIO.read(new File("src/main/resources/no_card.jpg"));
|
||||||
|
} catch (Exception ex) {
|
||||||
|
System.err.println("could not load default card image");
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
_defaultImage = (null == defImage) ? new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB) : defImage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void clear() {
|
public static void clear() {
|
||||||
CACHE.invalidateAll();
|
_CACHE.invalidateAll();
|
||||||
|
_missingIconKeys.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -99,7 +109,7 @@ public class ImageCache {
|
|||||||
} else {
|
} else {
|
||||||
key = card.getImageKey();
|
key = card.getImageKey();
|
||||||
}
|
}
|
||||||
return scaleImage(key, width, height);
|
return scaleImage(key, width, height, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -107,7 +117,7 @@ public class ImageCache {
|
|||||||
* and cannot be loaded from disk. pass -1 for width and/or height to avoid resizing in that dimension.
|
* and cannot be loaded from disk. pass -1 for width and/or height to avoid resizing in that dimension.
|
||||||
*/
|
*/
|
||||||
public static BufferedImage getImage(InventoryItem ii, int width, int height) {
|
public static BufferedImage getImage(InventoryItem ii, int width, int height) {
|
||||||
return scaleImage(getImageKey(ii, false), width, height);
|
return scaleImage(getImageKey(ii, false), width, height, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -115,40 +125,42 @@ public class ImageCache {
|
|||||||
* in the cache and cannot be loaded from disk.
|
* in the cache and cannot be loaded from disk.
|
||||||
*/
|
*/
|
||||||
public static ImageIcon getIcon(IHasIcon ihi) {
|
public static ImageIcon getIcon(IHasIcon ihi) {
|
||||||
BufferedImage i = scaleImage(ihi.getIconImageKey(), -1, -1);
|
String imageKey = ihi.getIconImageKey();
|
||||||
if (null == i) {
|
final BufferedImage i;
|
||||||
|
if (_missingIconKeys.contains(imageKey) ||
|
||||||
|
null == (i = scaleImage(ihi.getIconImageKey(), -1, -1, false))) {
|
||||||
|
_missingIconKeys.add(imageKey);
|
||||||
return FSkin.getIcon(FSkin.InterfaceIcons.ICO_UNKNOWN);
|
return FSkin.getIcon(FSkin.InterfaceIcons.ICO_UNKNOWN);
|
||||||
}
|
}
|
||||||
return new ImageIcon(i);
|
return new ImageIcon(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BufferedImage scaleImage(String key, final int width, final int height) {
|
private static BufferedImage scaleImage(String key, final int width, final int height, boolean useDefaultImage) {
|
||||||
if (StringUtils.isEmpty(key) || (3 > width && -1 != width) || (3 > height && -1 != height)) {
|
if (StringUtils.isEmpty(key) || (3 > width && -1 != width) || (3 > height && -1 != height)) {
|
||||||
// picture too small or key not defined; return a blank
|
// picture too small or key not defined; return a blank
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder rsKey = new StringBuilder(key);
|
String resizedKey = String.format("%s#%dx%d", key, width, height);
|
||||||
rsKey.append("#").append(width).append('x').append(height);
|
|
||||||
String resizedKey = rsKey.toString();
|
|
||||||
|
|
||||||
final BufferedImage cached = CACHE.getIfPresent(resizedKey);
|
final BufferedImage cached = _CACHE.getIfPresent(resizedKey);
|
||||||
if (null != cached) {
|
if (null != cached) {
|
||||||
|
//System.out.println("found cached image: " + resizedKey);
|
||||||
return cached;
|
return cached;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean mayEnlarge = Singletons.getModel().getPreferences().getPrefBoolean(FPref.UI_SCALE_LARGER);
|
|
||||||
BufferedImage original = getImage(key);
|
BufferedImage original = getImage(key);
|
||||||
|
|
||||||
if (null == original) {
|
if (null == original) {
|
||||||
original = defaultImage;
|
if (!useDefaultImage) {
|
||||||
CACHE.put(key, defaultImage); // This instructs cache to give up finding a picture if it was not found once
|
|
||||||
}
|
|
||||||
|
|
||||||
if (original == emptyImage) { // the found image is a placeholder for missing picture?
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// henceforth use a default picture for this key if image not found
|
||||||
|
original = _defaultImage;
|
||||||
|
_CACHE.put(key, _defaultImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean mayEnlarge = Singletons.getModel().getPreferences().getPrefBoolean(FPref.UI_SCALE_LARGER);
|
||||||
double scale = Math.min(
|
double scale = Math.min(
|
||||||
-1 == width ? 1 : (double)width / original.getWidth(),
|
-1 == width ? 1 : (double)width / original.getWidth(),
|
||||||
-1 == height? 1 : (double)height / original.getHeight());
|
-1 == height? 1 : (double)height / original.getHeight());
|
||||||
@@ -162,12 +174,22 @@ public class ImageCache {
|
|||||||
} else {
|
} else {
|
||||||
int destWidth = (int)(original.getWidth() * scale);
|
int destWidth = (int)(original.getWidth() * scale);
|
||||||
int destHeight = (int)(original.getHeight() * scale);
|
int destHeight = (int)(original.getHeight() * scale);
|
||||||
ResampleOp resampler = new ResampleOp(destWidth, destHeight);
|
|
||||||
|
|
||||||
|
// if this scale has been used before, get the cached version instead of rescaling
|
||||||
|
String effectiveResizedKey = String.format("%s#%dx%d", key, destWidth, destHeight);
|
||||||
|
result = _CACHE.getIfPresent(effectiveResizedKey);
|
||||||
|
if (null == result) {
|
||||||
|
ResampleOp resampler = new ResampleOp(destWidth, destHeight);
|
||||||
result = resampler.filter(original, null);
|
result = resampler.filter(original, null);
|
||||||
CACHE.put(resizedKey, result);
|
//System.out.println("caching resized image: " + effectiveResizedKey);
|
||||||
|
_CACHE.put(effectiveResizedKey, result);
|
||||||
|
//} else {
|
||||||
|
// System.out.println("retrieved resized image: " + effectiveResizedKey);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//System.out.println("caching image: " + resizedKey);
|
||||||
|
_CACHE.put(resizedKey, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,7 +198,7 @@ public class ImageCache {
|
|||||||
*/
|
*/
|
||||||
private static BufferedImage getImage(final String key) {
|
private static BufferedImage getImage(final String key) {
|
||||||
try {
|
try {
|
||||||
return ImageCache.CACHE.get(key);
|
return ImageCache._CACHE.get(key);
|
||||||
} catch (final ExecutionException ex) {
|
} catch (final ExecutionException ex) {
|
||||||
if (ex.getCause() instanceof NullPointerException) {
|
if (ex.getCause() instanceof NullPointerException) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
Reference in New Issue
Block a user