Index: trunk/src/org/openstreetmap/josm/gui/dialogs/properties/TagEditHelper.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/properties/TagEditHelper.java	(revision 16836)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/properties/TagEditHelper.java	(revision 16838)
@@ -32,5 +32,4 @@
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.EnumSet;
 import java.util.Iterator;
 import java.util.List;
@@ -71,7 +70,5 @@
 import org.openstreetmap.josm.command.SequenceCommand;
 import org.openstreetmap.josm.data.UndoRedoHandler;
-import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.DataSet;
-import org.openstreetmap.josm.data.osm.INode;
 import org.openstreetmap.josm.data.osm.OsmDataManager;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
@@ -100,4 +97,5 @@
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.OsmPrimitiveImageProvider;
 import org.openstreetmap.josm.tools.PlatformManager;
 import org.openstreetmap.josm.tools.Shortcut;
@@ -695,19 +693,7 @@
         protected Optional<ImageIcon> findIcon(String key, String value) {
             final Iterator<OsmPrimitive> osmPrimitiveIterator = sel.iterator();
-            final OsmPrimitive virtual = (osmPrimitiveIterator.hasNext() ? osmPrimitiveIterator.next().getType() : OsmPrimitiveType.NODE)
-                    .newInstance(0, false);
-            if (virtual instanceof INode) {
-                ((INode) virtual).setCoor(LatLon.ZERO);
-            }
-            virtual.put(key, value);
-            try {
-                final ImageIcon padded = ImageProvider.getPadded(virtual, ImageProvider.ImageSizes.LARGEICON.getImageDimension(),
-                        EnumSet.of(ImageProvider.GetPaddedOptions.NO_DEFAULT, ImageProvider.GetPaddedOptions.NO_DEPRECATED));
-                return Optional.ofNullable(padded);
-            } catch (Exception e) {
-                Logging.warn("Failed to find icon for {0} {1}={2}", virtual.getType(), key, value);
-                Logging.warn(e);
-                return Optional.empty();
-            }
+            final OsmPrimitiveType type = osmPrimitiveIterator.hasNext() ? osmPrimitiveIterator.next().getType() : OsmPrimitiveType.NODE;
+            return OsmPrimitiveImageProvider.getResource(key, value, type)
+                    .map(resource -> resource.getPaddedIcon(ImageProvider.ImageSizes.LARGEICON.getImageDimension()));
         }
 
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java	(revision 16836)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/MapPaintStyles.java	(revision 16838)
@@ -7,5 +7,4 @@
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.EnumSet;
 import java.util.LinkedList;
 import java.util.List;
@@ -14,7 +13,5 @@
 import javax.swing.SwingUtilities;
 
-import org.openstreetmap.josm.data.coor.LatLon;
-import org.openstreetmap.josm.data.osm.DataSet;
-import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
 import org.openstreetmap.josm.data.osm.Tag;
 import org.openstreetmap.josm.data.preferences.sources.MapPaintPrefHelper;
@@ -30,4 +27,5 @@
 import org.openstreetmap.josm.tools.ListenerList;
 import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.OsmPrimitiveImageProvider;
 import org.openstreetmap.josm.tools.Stopwatch;
 import org.openstreetmap.josm.tools.Utils;
@@ -238,22 +236,12 @@
      * @param tag The tag to look an icon for
      * @return {@code null} if no icon found
-     * @deprecated use {@link ImageProvider#getPadded}
+     * @deprecated use {@link OsmPrimitiveImageProvider#getResource}
      */
     @Deprecated
     public static ImageIcon getNodeIcon(Tag tag) {
         if (tag != null) {
-            DataSet ds = new DataSet();
-            Node virtualNode = new Node(LatLon.ZERO);
-            virtualNode.put(tag.getKey(), tag.getValue());
-            MapCSSStyleSource.STYLE_SOURCE_LOCK.readLock().lock();
-            try {
-                // Add primitive to dataset to avoid DataIntegrityProblemException when evaluating selectors
-                ds.addPrimitive(virtualNode);
-                return ImageProvider.getPadded(virtualNode, ImageProvider.ImageSizes.SMALLICON.getImageDimension(),
-                        EnumSet.of(ImageProvider.GetPaddedOptions.NO_PRESETS, ImageProvider.GetPaddedOptions.NO_DEFAULT));
-            } finally {
-                ds.removePrimitive(virtualNode);
-                MapCSSStyleSource.STYLE_SOURCE_LOCK.readLock().unlock();
-            }
+            return OsmPrimitiveImageProvider.getResource(tag.getKey(), tag.getValue(), OsmPrimitiveType.NODE)
+                    .map(resource -> resource.getPaddedIcon(ImageProvider.ImageSizes.SMALLICON.getImageDimension()))
+                    .orElse(null);
         }
         return null;
Index: trunk/src/org/openstreetmap/josm/tools/ImageProvider.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/ImageProvider.java	(revision 16836)
+++ trunk/src/org/openstreetmap/josm/tools/ImageProvider.java	(revision 16838)
@@ -35,6 +35,4 @@
 import java.util.Base64;
 import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
 import java.util.EnumMap;
 import java.util.HashMap;
@@ -45,5 +43,4 @@
 import java.util.Map;
 import java.util.Objects;
-import java.util.Optional;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ConcurrentHashMap;
@@ -67,15 +64,6 @@
 
 import org.openstreetmap.josm.data.Preferences;
-import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
-import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
-import org.openstreetmap.josm.gui.mappaint.Range;
-import org.openstreetmap.josm.gui.mappaint.StyleElementList;
-import org.openstreetmap.josm.gui.mappaint.styleelement.MapImage;
-import org.openstreetmap.josm.gui.mappaint.styleelement.NodeElement;
-import org.openstreetmap.josm.gui.mappaint.styleelement.StyleElement;
-import org.openstreetmap.josm.gui.tagging.presets.TaggingPreset;
-import org.openstreetmap.josm.gui.tagging.presets.TaggingPresets;
 import org.openstreetmap.josm.io.CachedFile;
 import org.openstreetmap.josm.spi.preferences.Config;
@@ -1539,29 +1527,4 @@
 
     /**
-     * Options used in {@link #getPadded(OsmPrimitive, Dimension, Collection)}.
-     * @since 15889
-     */
-    public enum GetPaddedOptions {
-        /**
-         * Exclude icon indicating deprecated tag usage.
-         */
-        NO_DEPRECATED,
-        /**
-         * Exclude default icon for {@link OsmPrimitiveType} from {@link #get(OsmPrimitiveType)}
-         */
-        NO_DEFAULT,
-        /**
-         * Exclude tagging preset icons.
-         */
-        NO_PRESETS,
-        /**
-         * Exclude tagging preset icons for {@linkplain OsmPrimitiveType#WAY ways}.
-         */
-        NO_WAY_PRESETS;
-
-        private static final Collection<GetPaddedOptions> DEFAULT = Collections.singleton(GetPaddedOptions.NO_WAY_PRESETS);
-    }
-
-    /**
      * Returns an {@link ImageIcon} for the given OSM object, at the specified size.
      * This is a slow operation.
@@ -1572,81 +1535,9 @@
      */
     public static ImageIcon getPadded(OsmPrimitive primitive, Dimension iconSize) {
-        return getPadded(primitive, iconSize, GetPaddedOptions.DEFAULT);
-    }
-
-    /**
-     * Returns an {@link ImageIcon} for the given OSM object, at the specified size.
-     * This is a slow operation.
-     * @param primitive Object for which an icon shall be fetched. The icon is chosen based on tags.
-     * @param iconSize Target size of icon. Icon is padded if required.
-     * @param options zero or more {@linkplain GetPaddedOptions options}.
-     * @return Icon for {@code primitive} that fits in cell or {@code null}.
-     * @since 15889
-     */
-    public static ImageIcon getPadded(OsmPrimitive primitive, Dimension iconSize, Collection<GetPaddedOptions> options) {
         if (iconSize.width <= 0 || iconSize.height <= 0) {
             return null;
         }
-
-        // Check if the current styles have special icon for tagged objects.
-        if (primitive.isTagged()) {
-            ImageIcon icon = getTaggedPadded(primitive, iconSize, options);
-            if (icon != null) {
-                return icon;
-            }
-        }
-
-        // Check if the presets have icons for nodes/relations.
-        if (primitive.isTagged() && (!options.contains(GetPaddedOptions.NO_WAY_PRESETS) || OsmPrimitiveType.WAY != primitive.getType())) {
-            final Optional<ImageIcon> icon = TaggingPresets.getMatchingPresets(primitive).stream()
-                    .sorted(Comparator.comparing(p -> (p.iconName != null && p.iconName.contains("multipolygon"))
-                            || p.types == null || p.types.isEmpty() ? Integer.MAX_VALUE : p.types.size()))
-                    .map(TaggingPreset::getImageResource)
-                    .filter(Objects::nonNull)
-                    .map(resource -> resource.getPaddedIcon(iconSize))
-                    .findFirst();
-            if (icon.isPresent()) {
-                return icon.get();
-            }
-        }
-
-        // Use generic default icon.
-        return options.contains(GetPaddedOptions.NO_DEFAULT)
-                ? null
-                : new ImageProvider("data", primitive.getDisplayType().getAPIName()).getResource().getPaddedIcon(iconSize);
-    }
-
-    /**
-     * Computes a new padded icon for the given tagged primitive, using map paint styles.
-     * This is a slow operation.
-     * @param primitive tagged OSM primitive
-     * @param iconSize icon size in pixels
-     * @param options zero or more {@linkplain GetPaddedOptions options}.
-     * @return a new padded icon for the given tagged primitive, or null
-     */
-    private static ImageIcon getTaggedPadded(OsmPrimitive primitive, Dimension iconSize, Collection<GetPaddedOptions> options) {
-        Pair<StyleElementList, Range> nodeStyles;
-        DataSet ds = primitive.getDataSet();
-        if (ds != null) {
-            ds.getReadLock().lock();
-        }
-        try {
-            nodeStyles = MapPaintStyles.getStyles().generateStyles(primitive, 100, false);
-        } finally {
-            if (ds != null) {
-                ds.getReadLock().unlock();
-            }
-        }
-        for (StyleElement style : nodeStyles.a) {
-            if (style instanceof NodeElement) {
-                NodeElement nodeStyle = (NodeElement) style;
-                MapImage icon = nodeStyle.mapImage;
-                if (icon != null && icon.getImageResource() != null &&
-                        (icon.name == null || !options.contains(GetPaddedOptions.NO_DEPRECATED) || !icon.name.contains("deprecated"))) {
-                    return icon.getImageResource().getPaddedIcon(iconSize);
-                }
-            }
-        }
-        return null;
+        ImageResource resource = OsmPrimitiveImageProvider.getResource(primitive, OsmPrimitiveImageProvider.Options.DEFAULT);
+        return resource != null ? resource.getPaddedIcon(iconSize) : null;
     }
 
Index: trunk/src/org/openstreetmap/josm/tools/OsmPrimitiveImageProvider.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/OsmPrimitiveImageProvider.java	(revision 16838)
+++ trunk/src/org/openstreetmap/josm/tools/OsmPrimitiveImageProvider.java	(revision 16838)
@@ -0,0 +1,156 @@
+// License: GPL. For details, see LICENSE file.
+
+package org.openstreetmap.josm.tools;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.EnumSet;
+import java.util.Objects;
+import java.util.Optional;
+
+import javax.swing.ImageIcon;
+
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.INode;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
+import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
+import org.openstreetmap.josm.gui.mappaint.Range;
+import org.openstreetmap.josm.gui.mappaint.StyleElementList;
+import org.openstreetmap.josm.gui.mappaint.styleelement.MapImage;
+import org.openstreetmap.josm.gui.mappaint.styleelement.NodeElement;
+import org.openstreetmap.josm.gui.mappaint.styleelement.StyleElement;
+import org.openstreetmap.josm.gui.tagging.presets.TaggingPreset;
+import org.openstreetmap.josm.gui.tagging.presets.TaggingPresets;
+
+/**
+ * An {@link ImageProvider} for {@link org.openstreetmap.josm.data.osm.OsmPrimitive}
+ *
+ * @since 16838 (extracted from ImageProvider)
+ */
+public final class OsmPrimitiveImageProvider {
+
+    private OsmPrimitiveImageProvider() {
+        // private constructor
+    }
+
+    /**
+     * Returns an {@link ImageIcon} for the given OSM object, at the specified size.
+     * This is a slow operation.
+     * @param primitive Object for which an icon shall be fetched. The icon is chosen based on tags.
+     * @param options zero or more {@linkplain Options options}.
+     * @return Icon for {@code primitive} that fits in cell or {@code null}.
+     * @since 15889
+     */
+    public static ImageResource getResource(OsmPrimitive primitive, Collection<Options> options) {
+        // Check if the current styles have special icon for tagged objects.
+        if (primitive.isTagged()) {
+            ImageResource icon = getResourceFromMapPaintStyles(primitive, options);
+            if (icon != null) {
+                return icon;
+            }
+        }
+
+        // Check if the presets have icons for nodes/relations.
+        if (primitive.isTagged() && (!options.contains(Options.NO_WAY_PRESETS) || OsmPrimitiveType.WAY != primitive.getType())) {
+            final Optional<ImageResource> icon = TaggingPresets.getMatchingPresets(primitive).stream()
+                    .sorted(Comparator.comparing(p -> (p.iconName != null && p.iconName.contains("multipolygon"))
+                            || p.types == null || p.types.isEmpty() ? Integer.MAX_VALUE : p.types.size()))
+                    .map(TaggingPreset::getImageResource)
+                    .filter(Objects::nonNull)
+                    .findFirst();
+            if (icon.isPresent()) {
+                return icon.get();
+            }
+        }
+
+        // Use generic default icon.
+        return options.contains(Options.NO_DEFAULT)
+                ? null
+                : new ImageProvider("data", primitive.getDisplayType().getAPIName()).getResource();
+    }
+
+    /**
+     * Computes a new padded icon for the given tagged primitive, using map paint styles.
+     * This is a slow operation.
+     * @param primitive tagged OSM primitive
+     * @param options zero or more {@linkplain Options options}.
+     * @return a new padded icon for the given tagged primitive, or null
+     */
+    private static ImageResource getResourceFromMapPaintStyles(OsmPrimitive primitive, Collection<Options> options) {
+        Pair<StyleElementList, Range> nodeStyles;
+        DataSet ds = primitive.getDataSet();
+        if (ds != null) {
+            ds.getReadLock().lock();
+        }
+        try {
+            nodeStyles = MapPaintStyles.getStyles().generateStyles(primitive, 100, false);
+        } finally {
+            if (ds != null) {
+                ds.getReadLock().unlock();
+            }
+        }
+        for (StyleElement style : nodeStyles.a) {
+            if (style instanceof NodeElement) {
+                NodeElement nodeStyle = (NodeElement) style;
+                MapImage icon = nodeStyle.mapImage;
+                if (icon != null && icon.getImageResource() != null &&
+                        (icon.name == null || !options.contains(Options.NO_DEPRECATED) || !icon.name.contains("deprecated"))) {
+                    return icon.getImageResource();
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Searches for an icon for the given key/value and primitiveType
+     * @param key The tag key
+     * @param value The tag value
+     * @param primitiveType The type of the primitive
+     * @return an icon for the given key/value and primitiveType
+     */
+    public static Optional<ImageResource> getResource(String key, String value, OsmPrimitiveType primitiveType) {
+        final OsmPrimitive virtual = primitiveType
+                .newInstance(0, false);
+        if (virtual instanceof INode) {
+            ((INode) virtual).setCoor(LatLon.ZERO);
+        }
+        virtual.put(key, value);
+        try {
+            final ImageResource padded = getResource(virtual, EnumSet.of(Options.NO_DEFAULT, Options.NO_DEPRECATED));
+            return Optional.ofNullable(padded);
+        } catch (Exception e) {
+            Logging.warn("Failed to find icon for {0} {1}={2}", virtual.getType(), key, value);
+            Logging.warn(e);
+            return Optional.empty();
+        }
+    }
+
+    /**
+     * Options used in {@link #getResource(OsmPrimitive, Collection)}.
+     * @since 15889
+     */
+    public enum Options {
+        /**
+         * Exclude icon indicating deprecated tag usage.
+         */
+        NO_DEPRECATED,
+        /**
+         * Exclude default icon for {@link OsmPrimitiveType} from {@link #get(OsmPrimitiveType)}
+         */
+        NO_DEFAULT,
+        /**
+         * Exclude tagging preset icons.
+         */
+        NO_PRESETS,
+        /**
+         * Exclude tagging preset icons for {@linkplain OsmPrimitiveType#WAY ways}.
+         */
+        NO_WAY_PRESETS;
+
+        static final Collection<Options> DEFAULT = Collections.singleton(Options.NO_WAY_PRESETS);
+    }
+}
