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