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 }