001 // License: GPL. For details, see LICENSE file.
002 package org.openstreetmap.josm.tools;
003
004 import com.kitfox.svg.SVGDiagram;
005
006 import java.awt.Dimension;
007 import java.awt.Image;
008 import java.awt.image.BufferedImage;
009 import java.util.HashMap;
010 import javax.swing.ImageIcon;
011
012 /**
013 * Holds data for one particular image.
014 * It can be backed by a svg or raster image.
015 *
016 * In the first case, 'svg' is not null and in the latter case, 'imgCache' has
017 * at least one entry for the key DEFAULT_DIMENSION.
018 */
019 class ImageResource {
020
021 /**
022 * Caches the image data for resized versions of the same image.
023 */
024 private HashMap<Dimension, BufferedImage> imgCache = new HashMap<Dimension, BufferedImage>();
025 private SVGDiagram svg;
026 public static final Dimension DEFAULT_DIMENSION = new Dimension(-1, -1);
027
028 public ImageResource(BufferedImage img) {
029 CheckParameterUtil.ensureParameterNotNull(img);
030 imgCache.put(DEFAULT_DIMENSION, img);
031 }
032
033 public ImageResource(SVGDiagram svg) {
034 CheckParameterUtil.ensureParameterNotNull(svg);
035 this.svg = svg;
036 }
037
038 public ImageIcon getImageIcon() {
039 return getImageIcon(DEFAULT_DIMENSION);
040 }
041
042 /**
043 * Get an ImageIcon object for the image of this resource
044 * @param dim The requested dimensions. Use (-1,-1) for the original size
045 * and (width, -1) to set the width, but otherwise scale the image
046 * proportionally.
047 */
048 public ImageIcon getImageIcon(Dimension dim) {
049 if (dim.width < -1 || dim.width == 0 || dim.height < -1 || dim.height == 0)
050 throw new IllegalArgumentException();
051 BufferedImage img = imgCache.get(dim);
052 if (img != null) {
053 return new ImageIcon(img);
054 }
055 if (svg != null) {
056 img = ImageProvider.createImageFromSvg(svg, dim);
057 imgCache.put(dim, img);
058 return new ImageIcon(img);
059 } else {
060 BufferedImage base = imgCache.get(DEFAULT_DIMENSION);
061 if (base == null) throw new AssertionError();
062
063 int width = dim.width;
064 int height = dim.height;
065 ImageIcon icon = new ImageIcon(base);
066 if (width == -1) {
067 width = icon.getIconWidth() * height / icon.getIconHeight();
068 } else if (height == -1) {
069 height = icon.getIconHeight() * width / icon.getIconWidth();
070 }
071 Image i = icon.getImage().getScaledInstance(width, height, Image.SCALE_SMOOTH);
072 img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
073 img.getGraphics().drawImage(i, 0, 0, null);
074 imgCache.put(dim, img);
075 return new ImageIcon(img);
076 }
077 }
078
079 /**
080 * Get image icon with a certain maximum size. The image is scaled down
081 * to fit maximum dimensions. (Keeps aspect ratio)
082 *
083 * @param maxSize The maximum size. One of the dimensions (widht or height) can be -1,
084 * which means it is not bounded.
085 */
086 public ImageIcon getImageIconBounded(Dimension maxSize) {
087 if (maxSize.width < -1 || maxSize.width == 0 || maxSize.height < -1 || maxSize.height == 0)
088 throw new IllegalArgumentException();
089 float realWidth;
090 float realHeight;
091 if (svg != null) {
092 realWidth = svg.getWidth();
093 realHeight = svg.getHeight();
094 } else {
095 BufferedImage base = imgCache.get(DEFAULT_DIMENSION);
096 if (base == null) throw new AssertionError();
097 ImageIcon icon = new ImageIcon(base);
098 realWidth = icon.getIconWidth();
099 realHeight = icon.getIconHeight();
100 }
101 int maxWidth = maxSize.width;
102 int maxHeight = maxSize.height;
103
104 if (realWidth <= maxWidth) {
105 maxWidth = -1;
106 }
107 if (realHeight <= maxHeight) {
108 maxHeight = -1;
109 }
110
111 if (maxWidth == -1 && maxHeight == -1)
112 return getImageIcon(DEFAULT_DIMENSION);
113 else if (maxWidth == -1)
114 return getImageIcon(new Dimension(-1, maxHeight));
115 else if (maxHeight == -1)
116 return getImageIcon(new Dimension(maxWidth, -1));
117 else
118 if (realWidth / maxWidth > realHeight / maxHeight)
119 return getImageIcon(new Dimension(maxWidth, -1));
120 else
121 return getImageIcon(new Dimension(-1, maxHeight));
122 }
123 }