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