Index: src/org/openstreetmap/josm/actions/AddImageryLayerAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/AddImageryLayerAction.java	(revision 4717)
+++ src/org/openstreetmap/josm/actions/AddImageryLayerAction.java	(working copy)
@@ -11,7 +11,7 @@
 import org.openstreetmap.josm.data.imagery.ImageryInfo;
 import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryType;
 import org.openstreetmap.josm.gui.layer.ImageryLayer;
-import org.openstreetmap.josm.tools.ImageRequest;
+import org.openstreetmap.josm.tools.ImageProvider;
 
 public class AddImageryLayerAction extends JosmAction implements AdaptableAction {
 
@@ -27,7 +27,7 @@
         // change toolbar icon from if specified
         try {
             if (info.getIcon() != null) {
-                ImageIcon i = new ImageRequest().setOptional(true).setName(info.getIcon()).
+                ImageIcon i = new ImageProvider(info.getIcon()).setOptional(true).
                         setMaxHeight(MAX_ICON_SIZE).setMaxWidth(MAX_ICON_SIZE).get();
                 if (i != null) {
                     putValue(Action.SMALL_ICON, i);
Index: src/org/openstreetmap/josm/tools/ImageRequest.java
===================================================================
--- src/org/openstreetmap/josm/tools/ImageRequest.java	(revision 4717)
+++ src/org/openstreetmap/josm/tools/ImageRequest.java	(working copy)
@@ -1,106 +0,0 @@
-// License: GPL. For details, see LICENSE file.
-package org.openstreetmap.josm.tools;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
-
-import java.awt.Dimension;
-import java.io.File;
-import java.util.Collection;
-import javax.swing.ImageIcon;
-
-/**
- * Alternative way to request an image.
- * E.g.
- *
- * ImageIcon icon = new ImageRequest().setName(imgName).setWidth(100).setHeight(120).get();
- *
- * or in funky double-brace style
- *
- * ImageIcon icon = new ImageRequest(){{name=imgName; width=100; height=120;}}.get();
- */
-public class ImageRequest {
-    protected Collection<String> dirs;
-    protected String id;
-    protected String subdir;
-    protected String name;
-    protected File archive;
-    protected int width = -1;
-    protected int height = -1;
-    protected int maxWidth = -1;
-    protected int maxHeight = -1;
-    protected boolean sanitize;
-    protected boolean optional;
-
-    public ImageRequest setDirs(Collection<String> dirs) {
-        this.dirs = dirs;
-        return this;
-    }
-
-    public ImageRequest setId(String id) {
-        this.id = id;
-        return this;
-    }
-
-    public ImageRequest setSubdir(String subdir) {
-        this.subdir = subdir;
-        return this;
-    }
-
-    public ImageRequest setName(String name) {
-        this.name = name;
-        return this;
-    }
-
-    public ImageRequest setArchive(File archive) {
-        this.archive = archive;
-        return this;
-    }
-
-    public ImageRequest setWidth(int width) {
-        this.width = width;
-        return this;
-    }
-
-    public ImageRequest setHeight(int height) {
-        this.height = height;
-        return this;
-    }
-
-    public ImageRequest setMaxWidth(int maxWidth) {
-        this.maxWidth = maxWidth;
-        return this;
-    }
-
-    public ImageRequest setMaxHeight(int maxHeight) {
-        this.maxHeight = maxHeight;
-        return this;
-    }
-
-    public ImageRequest setSanitize(boolean sanitize) {
-        this.sanitize = sanitize;
-        return this;
-    }
-
-    public ImageRequest setOptional(boolean optional) {
-        this.optional = optional;
-        return this;
-    }
-
-    public ImageIcon get() {
-        ImageResource ir = ImageProvider.getIfAvailableImpl(dirs, id, subdir, name, archive);
-        if (ir == null) {
-            if (!optional) {
-                String ext = name.indexOf('.') != -1 ? "" : ".???";
-                throw new RuntimeException(tr("Fatal: failed to locate image ''{0}''. This is a serious configuration problem. JOSM will stop working.", name + ext));
-            } else {
-                System.out.println(tr("Failed to locate image ''{0}''", name));
-                return null;
-            }
-        }
-        if (maxWidth != -1 || maxHeight != -1)
-            return ir.getImageIconBounded(new Dimension(maxWidth, maxHeight), sanitize);
-        else 
-            return ir.getImageIcon(new Dimension(width, height), sanitize);
-    }
-    
-}
Index: src/org/openstreetmap/josm/tools/ImageProvider.java
===================================================================
--- src/org/openstreetmap/josm/tools/ImageProvider.java	(revision 4717)
+++ src/org/openstreetmap/josm/tools/ImageProvider.java	(working copy)
@@ -54,12 +54,19 @@
 
 /**
  * Helper class to support the application with images.
+ *
+ * How to use:
+ *
+ * <code>ImageIcon icon = new ImageProvider(name).setMaxWidth(24).setMaxHeight(24).get();</code>
+ * (there are more options, see below)
+ *
+ * short form:
+ * <code>ImageIcon icon = ImageProvider.get(name);</code>
+ *
  * @author imi
  */
 public class ImageProvider {
 
-    private static SVGUniverse svgUniverse;
-
     /**
      * Position of an overlay icon
      * @author imi
@@ -73,12 +80,161 @@
         OTHER   // everything else, e.g. png, gif (must be supported by Java)
     }
 
+    protected Collection<String> dirs;
+    protected String id;
+    protected String subdir;
+    protected String name;
+    protected File archive;
+    protected int width = -1;
+    protected int height = -1;
+    protected int maxWidth = -1;
+    protected int maxHeight = -1;
+    protected boolean sanitize;
+    protected boolean optional;
+
+    private static SVGUniverse svgUniverse;
+
     /**
      * The icon cache
      */
     private static Map<String, ImageResource> cache = new HashMap<String, ImageResource>();
 
     /**
+     * @param subdir    Subdirectory the image lies in.
+     * @param name      The name of the image. If it does not end with '.png' or '.svg',
+     *                  both extensions are tried.
+     */
+    public ImageProvider(String subdir, String name) {
+        this.subdir = subdir;
+        this.name = name;
+    }
+
+    public ImageProvider(String name) {
+        this.name = name;
+    }
+
+    /**
+     * Directories to look for the image.
+     */
+    public ImageProvider setDirs(Collection<String> dirs) {
+        this.dirs = dirs;
+        return this;
+    }
+
+    /**
+     * An id used for caching. Id is not used for cache if name starts with http://. (URL is unique anyway.)
+     */
+    public ImageProvider setId(String id) {
+        this.id = id;
+        return this;
+    }
+
+    /**
+     * A zip file where the image is located.
+     */
+    public ImageProvider setArchive(File archive) {
+        this.archive = archive;
+        return this;
+    }
+
+    /**
+     * The dimensions of the image.
+     *
+     * If not specified, the original size of the image is used.
+     * The width part of the dimension can be -1. Then it will only set the height but
+     * keep the aspect ratio. (And the other way around.)
+     */
+    public ImageProvider setSize(Dimension size) {
+        this.width = size.width;
+        this.height = size.height;
+        return this;
+    }
+
+    /**
+     * see setSize
+     */
+    public ImageProvider setWidth(int width) {
+        this.width = width;
+        return this;
+    }
+
+    /**
+     * see setSize
+     */
+    public ImageProvider setHeight(int height) {
+        this.height = height;
+        return this;
+    }
+
+    /**
+     * The maximum size of the image.
+     *
+     * It will shrink the image if necessary, but keep the aspect ratio.
+     * The given width or height can be -1 which means this direction is not bounded.
+     *
+     * 'size' and 'maxSize' are not compatible, you should set only one of them.
+     */
+    public ImageProvider setMaxSize(Dimension maxSize) {
+        this.maxWidth = maxSize.width;
+        this.maxHeight = maxSize.height;
+        return this;
+    }
+
+    /**
+     * see setMaxSize
+     */
+    public ImageProvider setMaxWidth(int maxWidth) {
+        this.maxWidth = maxWidth;
+        return this;
+    }
+
+    /**
+     * see setMaxSize
+     */
+    public ImageProvider setMaxHeight(int maxHeight) {
+        this.maxHeight = maxHeight;
+        return this;
+    }
+
+    /**
+     * Set true, if the image should be repainted to a new BufferedImage in order to work around certain issues.
+     */
+    public ImageProvider setSanitize(boolean sanitize) {
+        this.sanitize = sanitize;
+        return this;
+    }
+
+    /**
+     * The image URL comes from user data and the image may be missing.
+     *
+     * Set true, if JOSM should *not* throw a RuntimeException in case the image cannot be located.
+     */
+    public ImageProvider setOptional(boolean optional) {
+        this.optional = optional;
+        return this;
+    }
+
+    /**
+     * Execute the image request.
+     */
+    public ImageIcon get() {
+        ImageResource ir = getIfAvailableImpl();
+        if (ir == null) {
+            if (!optional) {
+                String ext = name.indexOf('.') != -1 ? "" : ".???";
+                throw new RuntimeException(tr("Fatal: failed to locate image ''{0}''. This is a serious configuration problem. JOSM will stop working.", name + ext));
+            } else {
+                System.out.println(tr("Failed to locate image ''{0}''", name));
+                return null;
+            }
+        }
+        if (maxWidth != -1 || maxHeight != -1)
+            return ir.getImageIconBounded(new Dimension(maxWidth, maxHeight), sanitize);
+        else
+            return ir.getImageIcon(new Dimension(width, height), sanitize);
+    }
+
+    /**
      * Return an image from the specified location. Throws a RuntimeException if
      * the image cannot be located.
      *
@@ -87,31 +243,22 @@
      * @return The requested Image.
      */
     public static ImageIcon get(String subdir, String name) {
-        ImageIcon icon = getIfAvailable(subdir, name);
-        if (icon == null) {
-            String ext = name.indexOf('.') != -1 ? "" : ".???";
-            throw new RuntimeException(tr(
-                    "Fatal: failed to locate image ''{0}''. This is a serious configuration problem. JOSM will stop working.",
-                    name+ext));
-        }
-        return icon;
+        return new ImageProvider(subdir, name).get();
     }
 
-    /**
-     * Shortcut for get("", name);
-     */
     public static ImageIcon get(String name) {
-        return get("", name);
+        return new ImageProvider(name).get();
     }
 
     public static ImageIcon getIfAvailable(String name) {
-        return getIfAvailable((Collection<String>) null, null, "", name);
+        return new ImageProvider(name).setOptional(true).get();
     }
 
     public static ImageIcon getIfAvailable(String subdir, String name) {
-        return getIfAvailable((Collection<String>) null, null, subdir, name);
+        return new ImageProvider(subdir, name).setOptional(true).get();
     }
 
+    @Deprecated
     public static ImageIcon getIfAvailable(String[] dirs, String id, String subdir, String name) {
         return getIfAvailable(Arrays.asList(dirs), id, subdir, name);
     }
@@ -121,18 +268,22 @@
      * is found. Use this, if the image to retrieve is optional. Nevertheless a warning will
      * be printed on the console if the image could not be found.
      */
+    @Deprecated
     public static ImageIcon getIfAvailable(Collection<String> dirs, String id, String subdir, String name) {
         return getIfAvailable(dirs, id, subdir, name, null);
     }
 
+    @Deprecated
     public static ImageIcon getIfAvailable(Collection<String> dirs, String id, String subdir, String name, File archive) {
         return getIfAvailable(dirs, id, subdir, name, archive, false);
     }
 
+    @Deprecated
     public static ImageIcon getIfAvailable(Collection<String> dirs, String id, String subdir, String name, File archive, boolean sanitize) {
         return getIfAvailable(dirs, id, subdir, name, archive, null, sanitize);
     }
 
+    @Deprecated
     public static ImageIcon getIfAvailable(Collection<String> dirs, String id, String subdir, String name, File archive, Dimension dim, boolean sanitize) {
         return getIfAvailable(dirs, id, subdir, name, archive, dim, null, sanitize);
     }
@@ -158,15 +309,17 @@
      * @param sanitize  If the image should be repainted to a new BufferedImage to work
      *                  around certain issues.
      */
+    @Deprecated
     public static ImageIcon getIfAvailable(Collection<String> dirs, String id, String subdir, String name,
             File archive, Dimension dim, Dimension maxSize, boolean sanitize) {
-        ImageResource ir = getIfAvailableImpl(dirs, id, subdir, name, archive);
-        if (ir == null)
-            return null;
-        if (maxSize != null)
-            return ir.getImageIconBounded(maxSize, sanitize);
-        else
-            return ir.getImageIcon(dim == null ? ImageResource.DEFAULT_DIMENSION : dim, sanitize);
+        ImageProvider p = new ImageProvider(subdir, name).setDirs(dirs).setId(id).setArchive(archive).setSanitize(sanitize).setOptional(true);
+        if (dim != null) {
+            p.setSize(dim);
+        }
+        if (maxSize != null) {
+            p.setMaxSize(maxSize);
+        }
+        return p.get();
     }
 
     /**
@@ -176,7 +329,7 @@
     private static final Pattern dataUrlPattern = Pattern.compile(
             "^data:([a-zA-Z]+/[a-zA-Z+]+)?(;base64)?,(.+)$");
 
-    static ImageResource getIfAvailableImpl(Collection<String> dirs, String id, String subdir, String name, File archive) {
+    private ImageResource getIfAvailableImpl() {
         if (name == null)
             return null;
 
Index: src/org/openstreetmap/josm/plugins/ReadRemotePluginInformationTask.java
===================================================================
--- src/org/openstreetmap/josm/plugins/ReadRemotePluginInformationTask.java	(revision 4717)
+++ src/org/openstreetmap/josm/plugins/ReadRemotePluginInformationTask.java	(working copy)
@@ -243,7 +243,11 @@
         }
         for (PluginInformation pi : availablePlugins) {
             if (pi.icon == null && pi.iconPath != null) {
-                pi.icon = ImageProvider.getIfAvailable(null, null, null, pi.name+".jar/"+pi.iconPath, destFile);
+                pi.icon = new ImageProvider(pi.name+".jar/"+pi.iconPath)
+                                .setArchive(destFile)
+                                .setMaxWidth(24)
+                                .setMaxHeight(24)
+                                .setOptional(true).get();
             }
         }
     }
Index: src/org/openstreetmap/josm/plugins/PluginInformation.java
===================================================================
--- src/org/openstreetmap/josm/plugins/PluginInformation.java	(revision 4717)
+++ src/org/openstreetmap/josm/plugins/PluginInformation.java	(working copy)
@@ -190,7 +190,7 @@
         iconPath = attr.getValue("Plugin-Icon");
         if (iconPath != null && file != null) {
             // extract icon from the plugin jar file
-            icon = ImageProvider.getIfAvailable(null, null, null, iconPath, file);
+            icon = new ImageProvider(iconPath).setArchive(file).setMaxWidth(24).setMaxHeight(24)setOptional(true).get();
         }
         if(oldcheck && mainversion > Version.getInstance().getVersion())
         {
Index: src/org/openstreetmap/josm/plugins/ReadLocalPluginInformationTask.java
===================================================================
--- src/org/openstreetmap/josm/plugins/ReadLocalPluginInformationTask.java	(revision 4717)
+++ src/org/openstreetmap/josm/plugins/ReadLocalPluginInformationTask.java	(working copy)
@@ -120,7 +120,11 @@
             monitor.setCustomText(tr("Processing file ''{0}''", fname));
             for (PluginInformation pi : availablePlugins.values()) {
                 if (pi.icon == null && pi.iconPath != null) {
-                    pi.icon = ImageProvider.getIfAvailable(null, null, null, pi.name+".jar/"+pi.iconPath, f);
+                    pi.icon = new ImageProvider(pi.name+".jar/"+pi.iconPath)
+                                    .setArchive(f)
+                                    .setMaxWidth(24)
+                                    .setMaxHeight(24)
+                                    .setOptional(true).get();
                 }
             }
             monitor.worked(1);
Index: src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java
===================================================================
--- src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java	(revision 4717)
+++ src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java	(working copy)
@@ -88,7 +88,14 @@
 
     public static ImageIcon getIcon(IconReference ref, int width, int height, boolean sanitize) {
         final String namespace = ref.source.getPrefName();
-        ImageIcon i = ImageProvider.getIfAvailable(getIconSourceDirs(ref.source), "mappaint."+namespace, null, ref.iconName, ref.source.zipIcons, width == -1 && height == -1 ? null : new Dimension(width, height), sanitize);
+        ImageIcon i = new ImageProvider(ref.iconName)
+                .setDirs(getIconSourceDirs(ref.source))
+                .setId("mappaint."+namespace)
+                .setArchive(ref.source.zipIcons)
+                .setWidth(width)
+                .setHeight(height)
+                .setSanitize(sanitize)
+                .setOptional(true).get();
         if(i == null)
         {
             System.out.println("Mappaint style \""+namespace+"\" ("+ref.source.getDisplayString()+") icon \"" + ref.iconName + "\" not found.");
@@ -106,7 +113,12 @@
      *  can be null if the defaults are turned off by user
      */
     public static ImageIcon getNoIcon_Icon(StyleSource source, boolean sanitize) {
-        return ImageProvider.getIfAvailable(getIconSourceDirs(source), "mappaint."+source.getPrefName(), null, "misc/no_icon.png", source.zipIcons, sanitize);
+        return new ImageProvider("misc/no_icon.png")
+                .setDirs(getIconSourceDirs(source))
+                .setId("mappaint."+source.getPrefName())
+                .setArchive(source.zipIcons)
+                .setSanitize(sanitize)
+                .setOptional(true).get();
     }
 
     private static List<String> getIconSourceDirs(StyleSource source) {
Index: src/org/openstreetmap/josm/gui/tagging/TaggingPreset.java
===================================================================
--- src/org/openstreetmap/josm/gui/tagging/TaggingPreset.java	(revision 4717)
+++ src/org/openstreetmap/josm/gui/tagging/TaggingPreset.java	(working copy)
@@ -1057,7 +1057,7 @@
      */
     public void setIcon(String iconName) {
         Collection<String> s = Main.pref.getCollection("taggingpreset.icon.sources", null);
-        ImageIcon icon = ImageProvider.getIfAvailable(s, "presets", null, iconName, zipIcons);
+        ImageIcon icon = new ImageProvider(iconName).setDirs(s).setId("presets").setArchive(zipIcons).setOptional(true).get();
         if (icon == null)
         {
             System.out.println("Could not get presets icon " + iconName);
Index: src/org/openstreetmap/josm/io/session/OsmDataSessionExporter.java
===================================================================
--- src/org/openstreetmap/josm/io/session/OsmDataSessionExporter.java	(revision 4717)
+++ src/org/openstreetmap/josm/io/session/OsmDataSessionExporter.java	(working copy)
@@ -44,7 +44,7 @@
 import org.openstreetmap.josm.io.OsmWriterFactory;
 import org.openstreetmap.josm.io.session.SessionWriter.ExportSupport;
 import org.openstreetmap.josm.tools.GBC;
-import org.openstreetmap.josm.tools.ImageRequest;
+import org.openstreetmap.josm.tools.ImageProvider;
 
 public class OsmDataSessionExporter implements SessionLayerExporter {
 
@@ -68,7 +68,7 @@
 
     private class LayerSaveAction extends AbstractAction {
         public LayerSaveAction() {
-            putValue(SMALL_ICON, new ImageRequest().setName("save").setWidth(16).get());
+            putValue(SMALL_ICON, new ImageProvider("save").setWidth(16).get());
             putValue(SHORT_DESCRIPTION, tr("Layer contains unsaved data - save to file."));
             updateEnabledState();
         }
