Changeset 6172 in josm for trunk/src/org/openstreetmap/josm/tools
- Timestamp:
- 2013-08-21T18:15:12+02:00 (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/tools/ImageProvider.java
r6151 r6172 4 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 5 6 import java.awt.Component;7 6 import java.awt.Cursor; 8 7 import java.awt.Dimension; … … 83 82 } 84 83 84 /** 85 * Supported image types 86 */ 85 87 public static enum ImageType { 86 SVG, // scalable vector graphics 87 OTHER // everything else, e.g. png, gif (must be supported by Java) 88 /** Scalable vector graphics */ 89 SVG, 90 /** Everything else, e.g. png, gif (must be supported by Java) */ 91 OTHER 88 92 } 89 93 … … 107 111 * The icon cache 108 112 */ 109 private static Map<String, ImageResource> cache = new HashMap<String, ImageResource>(); 110 111 private final static ExecutorService imageFetcher = Executors.newSingleThreadExecutor(); 113 private static final Map<String, ImageResource> cache = new HashMap<String, ImageResource>(); 114 115 /** 116 * Caches the image data for rotated versions of the same image. 117 */ 118 private static final Map<Image, Map<Long, ImageResource>> rotateCache = new HashMap<Image, Map<Long, ImageResource>>(); 119 120 private static final ExecutorService imageFetcher = Executors.newSingleThreadExecutor(); 112 121 113 122 public interface ImageCallback { … … 116 125 117 126 /** 127 * Constructs a new {@code ImageProvider} from a filename in a given directory. 118 128 * @param subdir subdirectory the image lies in 119 129 * @param name the name of the image. If it does not end with '.png' or '.svg', … … 125 135 } 126 136 137 /** 138 * Constructs a new {@code ImageProvider} from a filename. 139 * @param name the name of the image. If it does not end with '.png' or '.svg', 140 * both extensions are tried. 141 */ 127 142 public ImageProvider(String name) { 128 143 this.name = name; … … 131 146 /** 132 147 * Directories to look for the image. 148 * @param dirs The directories to look for. 149 * @return the current object, for convenience 133 150 */ 134 151 public ImageProvider setDirs(Collection<String> dirs) { … … 141 158 * If name starts with <tt>http://</tt> Id is not used for the cache. 142 159 * (A URL is unique anyway.) 160 * @return the current object, for convenience 143 161 */ 144 162 public ImageProvider setId(String id) { … … 151 169 * 152 170 * (optional) 171 * @return the current object, for convenience 153 172 */ 154 173 public ImageProvider setArchive(File archive) { … … 163 182 * 164 183 * (optional) 184 * @return the current object, for convenience 165 185 */ 166 186 public ImageProvider setInArchiveDir(String inArchiveDir) { … … 175 195 * The width part of the dimension can be -1. Then it will only set the height but 176 196 * keep the aspect ratio. (And the other way around.) 197 * @return the current object, for convenience 177 198 */ 178 199 public ImageProvider setSize(Dimension size) { … … 184 205 /** 185 206 * @see #setSize 207 * @return the current object, for convenience 186 208 */ 187 209 public ImageProvider setWidth(int width) { … … 192 214 /** 193 215 * @see #setSize 216 * @return the current object, for convenience 194 217 */ 195 218 public ImageProvider setHeight(int height) { … … 205 228 * 206 229 * 'size' and 'maxSize' are not compatible, you should set only one of them. 230 * @return the current object, for convenience 207 231 */ 208 232 public ImageProvider setMaxSize(Dimension maxSize) { … … 214 238 /** 215 239 * Convenience method, see {@link #setMaxSize(Dimension)}. 240 * @return the current object, for convenience 216 241 */ 217 242 public ImageProvider setMaxSize(int maxSize) { … … 221 246 /** 222 247 * @see #setMaxSize 248 * @return the current object, for convenience 223 249 */ 224 250 public ImageProvider setMaxWidth(int maxWidth) { … … 229 255 /** 230 256 * @see #setMaxSize 257 * @return the current object, for convenience 231 258 */ 232 259 public ImageProvider setMaxHeight(int maxHeight) { … … 253 280 * 254 281 * In combination with setOptional(true); 282 * @return the current object, for convenience 255 283 */ 256 284 public ImageProvider setSuppressWarnings(boolean suppressWarnings) { … … 261 289 /** 262 290 * Add a collection of additional class loaders to search image for. 291 * @return the current object, for convenience 263 292 */ 264 293 public ImageProvider setAdditionalClassLoaders(Collection<ClassLoader> additionalClassLoaders) { … … 388 417 } 389 418 } catch (UnsupportedEncodingException ex) { 390 throw new RuntimeException(ex.getMessage(), ex);391 } catch (IOException ex) {392 419 throw new RuntimeException(ex.getMessage(), ex); 393 420 } … … 482 509 483 510 private static ImageResource getIfAvailableHttp(String url, ImageType type) { 511 MirroredInputStream is = null; 484 512 try { 485 MirroredInputStreamis = new MirroredInputStream(url,513 is = new MirroredInputStream(url, 486 514 new File(Main.pref.getCacheDirectory(), "images").getPath()); 487 515 switch (type) { … … 501 529 } catch (IOException e) { 502 530 return null; 531 } finally { 532 Utils.close(is); 503 533 } 504 534 } … … 791 821 * Creates a rotated version of the input image. 792 822 * 793 * @param c The component to get properties useful for painting, e.g. the foreground or794 * background color.795 823 * @param img the image to be rotated. 796 824 * @param rotatedAngle the rotated angle, in degree, clockwise. It could be any double but we 797 * will mod it with 360 before using it. 825 * will mod it with 360 before using it. More over for caching performance, it will be rounded to 826 * an entire value between 0 and 360. 798 827 * 799 828 * @return the image after rotating. 800 */ 801 public static Image createRotatedImage(Component c, Image img, double rotatedAngle) { 802 // convert rotatedAngle to a value from 0 to 360 803 double originalAngle = rotatedAngle % 360; 829 * @since 6172 830 */ 831 public static Image createRotatedImage(Image img, double rotatedAngle) { 832 return createRotatedImage(img, rotatedAngle, ImageResource.DEFAULT_DIMENSION); 833 } 834 835 /** 836 * Creates a rotated version of the input image, scaled to the given dimension. 837 * 838 * @param img the image to be rotated. 839 * @param rotatedAngle the rotated angle, in degree, clockwise. It could be any double but we 840 * will mod it with 360 before using it. More over for caching performance, it will be rounded to 841 * an entire value between 0 and 360. 842 * @param dimension The requested dimensions. Use (-1,-1) for the original size 843 * and (width, -1) to set the width, but otherwise scale the image proportionally. 844 * @return the image after rotating and scaling. 845 * @since 6172 846 */ 847 public static Image createRotatedImage(Image img, double rotatedAngle, Dimension dimension) { 848 CheckParameterUtil.ensureParameterNotNull(img, "img"); 849 850 // convert rotatedAngle to an integer value from 0 to 360 851 Long originalAngle = Math.round(rotatedAngle % 360); 804 852 if (rotatedAngle != 0 && originalAngle == 0) { 805 originalAngle = 360.0; 806 } 807 808 // convert originalAngle to a value from 0 to 90 809 double angle = originalAngle % 90; 810 if (originalAngle != 0.0 && angle == 0.0) { 811 angle = 90.0; 812 } 813 814 double radian = Math.toRadians(angle); 815 816 new ImageIcon(img); // load completely 817 int iw = img.getWidth(null); 818 int ih = img.getHeight(null); 819 int w; 820 int h; 821 822 if ((originalAngle >= 0 && originalAngle <= 90) || (originalAngle > 180 && originalAngle <= 270)) { 823 w = (int) (iw * Math.sin(DEGREE_90 - radian) + ih * Math.sin(radian)); 824 h = (int) (iw * Math.sin(radian) + ih * Math.sin(DEGREE_90 - radian)); 825 } else { 826 w = (int) (ih * Math.sin(DEGREE_90 - radian) + iw * Math.sin(radian)); 827 h = (int) (ih * Math.sin(radian) + iw * Math.sin(DEGREE_90 - radian)); 828 } 829 BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); 830 Graphics g = image.getGraphics(); 831 Graphics2D g2d = (Graphics2D) g.create(); 832 833 // calculate the center of the icon. 834 int cx = iw / 2; 835 int cy = ih / 2; 836 837 // move the graphics center point to the center of the icon. 838 g2d.translate(w / 2, h / 2); 839 840 // rotate the graphics about the center point of the icon 841 g2d.rotate(Math.toRadians(originalAngle)); 842 843 g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); 844 g2d.drawImage(img, -cx, -cy, c); 845 846 g2d.dispose(); 847 new ImageIcon(image); // load completely 848 return image; 853 originalAngle = 360L; 854 } 855 856 ImageResource imageResource = null; 857 858 synchronized (rotateCache) { 859 Map<Long, ImageResource> cacheByAngle = rotateCache.get(img); 860 if (cacheByAngle == null) { 861 rotateCache.put(img, cacheByAngle = new HashMap<Long, ImageResource>()); 862 } 863 864 imageResource = cacheByAngle.get(originalAngle); 865 866 if (imageResource == null) { 867 // convert originalAngle to a value from 0 to 90 868 double angle = originalAngle % 90; 869 if (originalAngle != 0.0 && angle == 0.0) { 870 angle = 90.0; 871 } 872 873 double radian = Math.toRadians(angle); 874 875 new ImageIcon(img); // load completely 876 int iw = img.getWidth(null); 877 int ih = img.getHeight(null); 878 int w; 879 int h; 880 881 if ((originalAngle >= 0 && originalAngle <= 90) || (originalAngle > 180 && originalAngle <= 270)) { 882 w = (int) (iw * Math.sin(DEGREE_90 - radian) + ih * Math.sin(radian)); 883 h = (int) (iw * Math.sin(radian) + ih * Math.sin(DEGREE_90 - radian)); 884 } else { 885 w = (int) (ih * Math.sin(DEGREE_90 - radian) + iw * Math.sin(radian)); 886 h = (int) (ih * Math.sin(radian) + iw * Math.sin(DEGREE_90 - radian)); 887 } 888 Image image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); 889 cacheByAngle.put(originalAngle, imageResource = new ImageResource(image)); 890 Graphics g = image.getGraphics(); 891 Graphics2D g2d = (Graphics2D) g.create(); 892 893 // calculate the center of the icon. 894 int cx = iw / 2; 895 int cy = ih / 2; 896 897 // move the graphics center point to the center of the icon. 898 g2d.translate(w / 2, h / 2); 899 900 // rotate the graphics about the center point of the icon 901 g2d.rotate(Math.toRadians(originalAngle)); 902 903 g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); 904 g2d.drawImage(img, -cx, -cy, null); 905 906 g2d.dispose(); 907 new ImageIcon(image); // load completely 908 } 909 return imageResource.getImageIcon(dimension).getImage(); 910 } 911 } 912 913 /** 914 * Creates a scaled down version of the input image to fit maximum dimensions. (Keeps aspect ratio) 915 * 916 * @param img the image to be scaled down. 917 * @param maxSize the maximum size in pixels (both for width and height) 918 * 919 * @return the image after scaling. 920 * @since 6172 921 */ 922 public static Image createBoundedImage(Image img, int maxSize) { 923 return new ImageResource(img).getImageIconBounded(new Dimension(maxSize, maxSize)).getImage(); 849 924 } 850 925 … … 886 961 Graphics2D g = img.createGraphics(); 887 962 g.setClip(0, 0, width, height); 888 if (scaleX != null ) {963 if (scaleX != null && scaleY != null) { 889 964 g.scale(scaleX, scaleY); 890 965 }
Note:
See TracChangeset
for help on using the changeset viewer.