/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package mage.client.util; import com.google.common.base.Function; import com.google.common.collect.MapMaker; import com.mortennobel.imagescaling.ResampleOp; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.Transparency; import java.awt.image.BufferedImage; import java.util.Map; /** * * @author user */ public final class TransformedImageCache { private final static class Key { final int width; final int height; final double angle; public Key(int width, int height, double angle) { this.width = width; this.height = height; this.angle = angle; } @Override public int hashCode() { int hash = 3; hash = 53 * hash + this.width; hash = 53 * hash + this.height; hash = 53 * hash + (int) (Double.doubleToLongBits(this.angle) ^ (Double.doubleToLongBits(this.angle) >>> 32)); return hash; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Key other = (Key) obj; if (this.width != other.width) { return false; } if (this.height != other.height) { return false; } if (Double.doubleToLongBits(this.angle) != Double.doubleToLongBits(other.angle)) { return false; } return true; } } private static final Map<Key, Map<BufferedImage, BufferedImage>> IMAGE_CACHE; static { // TODO: can we use a single map? IMAGE_CACHE = ImageCaches.register(new MapMaker().softValues().makeComputingMap((Function<Key, Map<BufferedImage, BufferedImage>>) key -> new MapMaker().weakKeys().softValues().makeComputingMap(image -> { if (key.width != image.getWidth() || key.height != image.getHeight()) { image = resizeImage(image, key.width, key.height); } if (key.angle != 0.0) { image = rotateImage(image, key.angle); } return image; }))); } private static BufferedImage rotateImage(BufferedImage image, double angle) { double sin = Math.abs(Math.sin(angle)), cos = Math.abs(Math.cos(angle)); int width = image.getWidth(), height = image.getHeight(); int newWidth = (int) Math.floor(width * cos + height * sin), newHeight = (int) Math.floor(height * cos + width * sin); GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice gs = ge.getDefaultScreenDevice(); GraphicsConfiguration gc = gs.getDefaultConfiguration(); BufferedImage result = gc.createCompatibleImage(newWidth, newHeight, Transparency.TRANSLUCENT); Graphics2D g = result.createGraphics(); g.translate((newWidth - width) / 2, (newHeight - height) / 2); g.rotate(angle, width / 2, height / 2); g.drawRenderedImage(image, null); g.dispose(); return result; } private static BufferedImage resizeImage(BufferedImage original, int width, int height) { ResampleOp resampleOp = new ResampleOp(width, height); BufferedImage image = resampleOp.filter(original, null); return image; } public static BufferedImage getResizedImage(BufferedImage image, int width, int height) { return getRotatedResizedImage(image, width, height, 0.0); } public static BufferedImage getRotatedImage(BufferedImage image, double angle) { return getRotatedResizedImage(image, -1, -1, angle); } public static BufferedImage getRotatedResizedImage(BufferedImage image, int width, int height, double angle) { int imageWidth = image.getWidth(); int imageHeight = image.getHeight(); if (angle == 0.0 && (width < 0 || imageWidth == width) && (height < 0 || imageHeight == height)) { return image; } int resWidth; int resHeight; if (width < 0 && height < 0) { resWidth = imageWidth; resHeight = imageHeight; } else if ((height < 0) || (width >= 0 && imageHeight * width <= imageWidth * height)) { resWidth = width; resHeight = imageHeight * width / imageWidth; } else { resWidth = imageWidth * height / imageHeight; resHeight = height; } if (angle == 0.0 && imageWidth == resWidth && imageHeight == resHeight) { return image; } if (resWidth < 3) { resWidth = 3; } if (resHeight < 3) { resHeight = 3; } return IMAGE_CACHE.get(new Key(resWidth, resHeight, angle)).get(image); } }