package com.bc.ceres.swing.figure.support; import com.bc.ceres.core.Assert; import com.bc.ceres.grender.Rendering; import com.bc.ceres.swing.figure.FigureStyle; import com.bc.ceres.swing.figure.Symbol; import javax.swing.ImageIcon; import java.awt.Color; import java.awt.Graphics2D; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.net.URL; /** * A symbol that uses an icon image. * * @author Norman Fomferra * @since Ceres 0.13 */ public class ImageSymbol implements Symbol { private static final Color BGCOLOR = new Color(0, 0, 0, 0); private final String resourcePath; private final BufferedImage image; private final double refX; private final double refY; public static ImageSymbol createIcon(String imageResourcePath) { return createIcon(imageResourcePath, ImageSymbol.class); } public static ImageSymbol createIcon(String imageResourcePath, Class callerClass) { BufferedImage image = loadBufferedImage(imageResourcePath, callerClass); return new ImageSymbol(imageResourcePath, image, 0.5 * image.getWidth(), 0.5 * image.getHeight()); } public static ImageSymbol createIcon(String imageResourcePath, double refX, double refY) { return createIcon(imageResourcePath, refX, refY, ImageSymbol.class); } public static ImageSymbol createIcon(String imageResourcePath, double refX, double refY, Class callerClass) { BufferedImage image = loadBufferedImage(imageResourcePath, callerClass); return new ImageSymbol(imageResourcePath, image, refX, refY); } private ImageSymbol( String resourcePath, BufferedImage image, double refX, double refY) { this.resourcePath = resourcePath; this.image = image; this.refX = refX; this.refY = refY; } public String getResourcePath() { return resourcePath; } public BufferedImage getImage() { return image; } /** * @return The X-coordinate of the reference point. */ public double getRefX() { return refX; } /** * @return The Y-coordinate of the reference point. */ public double getRefY() { return refY; } @Override public void draw(Rendering rendering, FigureStyle style) { try { rendering.getGraphics().translate(-refX, -refY); // improvement: we could check if we have to filter the image, e.g. to display in different colours rendering.getGraphics().drawRenderedImage(image, null); } finally { rendering.getGraphics().translate(+refX, +refY); } } @Override public boolean isHitBy(double x, double y) { int ix = (int) Math.round(x + refX); int iy = (int) Math.round(y + refY); return ix >= 0 && ix < image.getWidth() && iy >= 0 && iy < image.getHeight() && (image.getRGB(ix, iy) & 0xff000000) != 0; } @Override public Rectangle2D getBounds() { return new Rectangle2D.Double(-refX, -refY, image.getWidth(), image.getHeight()); } private static BufferedImage loadBufferedImage(String imageResourcePath, Class callerClass) { URL resource = callerClass.getResource(imageResourcePath); Assert.argument(resource != null, "imageResourcePath: resource not found: " + imageResourcePath); ImageIcon imageIcon = new ImageIcon(resource); BufferedImage image = new BufferedImage(imageIcon.getIconWidth(), imageIcon.getIconHeight(), BufferedImage.TYPE_INT_ARGB); Graphics2D graphics = image.createGraphics(); graphics.drawImage(imageIcon.getImage(), 0, 0, BGCOLOR, imageIcon.getImageObserver()); graphics.dispose(); return image; } }