diff --git a/src/org/openstreetmap/josm/gui/preferences/SourceEditor.java b/src/org/openstreetmap/josm/gui/preferences/SourceEditor.java
index 9c83d9c1f3..e8d05084ad 100644
--- a/src/org/openstreetmap/josm/gui/preferences/SourceEditor.java
+++ b/src/org/openstreetmap/josm/gui/preferences/SourceEditor.java
@@ -1336,7 +1336,7 @@ public abstract class SourceEditor extends JPanel {
                         sourceEntry.active ? SOURCE_ENTRY_ACTIVE_BACKGROUND_COLOR.get() : SOURCE_ENTRY_INACTIVE_BACKGROUND_COLOR.get());
                 }
                 final ImageSizes size = ImageSizes.TABLE;
-                setIcon(value.icon == null ? ImageProvider.getEmpty(size) : value.icon.getImageIconBounded(size.getImageDimension()));
+                setIcon(value.icon == null ? ImageProvider.getEmpty(size) : value.icon.getPaddedIcon(size.getImageDimension()));
             }
             return this;
         }
diff --git a/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPreset.java b/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPreset.java
index fac625b775..651f30e17c 100644
--- a/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPreset.java
+++ b/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPreset.java
@@ -290,8 +290,8 @@ public class TaggingPreset extends AbstractAction implements ActiveLayerChangeLi
             .thenAcceptAsync(result -> {
                 if (result != null) {
                     // Pre-render off EDT to avoid flooding the event queue with expensive SVG rendering
-                    ImageIcon small = result.getImageIcon(ImageProvider.ImageSizes.SMALLICON.getImageDimension());
-                    ImageIcon large = result.getImageIcon(ImageProvider.ImageSizes.LARGEICON.getImageDimension());
+                    ImageIcon small = result.getPaddedIcon(ImageProvider.ImageSizes.SMALLICON.getImageDimension());
+                    ImageIcon large = result.getPaddedIcon(ImageProvider.ImageSizes.LARGEICON.getImageDimension());
                     GuiHelper.runInEDT(() -> {
                         try {
                             putValue(Action.SMALL_ICON, small);
diff --git a/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetItem.java b/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetItem.java
index 737e2fd449..cc03e36299 100644
--- a/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetItem.java
+++ b/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetItem.java
@@ -4,6 +4,7 @@ package org.openstreetmap.josm.gui.tagging.presets;
 import static org.openstreetmap.josm.tools.I18n.tr;
 import static org.openstreetmap.josm.tools.I18n.trc;
 
+import java.awt.Dimension;
 import java.io.File;
 import java.util.Arrays;
 import java.util.Collection;
@@ -28,6 +29,8 @@ import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionList;
 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionManager;
 import org.openstreetmap.josm.gui.util.LruCache;
 import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
+import org.openstreetmap.josm.tools.ImageResource;
 import org.openstreetmap.josm.tools.Logging;
 import org.openstreetmap.josm.tools.Utils;
 import org.xml.sax.SAXException;
@@ -150,16 +153,15 @@ public abstract class TaggingPresetItem {
      * Loads a tagging preset icon
      * @param iconName the icon name
      * @param zipIcons zip file where the image is located
-     * @param maxSize maximum image size (or null)
-     * @return the requested image or null if the request failed
+     * @param maxSize maximum image size (or null for the default small icon size)
+     * @return the requested image, centered in a square of {@code maxSize}, or null if the request failed
      */
     public static ImageIcon loadImageIcon(String iconName, File zipIcons, Integer maxSize) {
         final Collection<String> s = TaggingPresets.ICON_SOURCES.get();
-        ImageProvider imgProv = new ImageProvider(iconName).setDirs(s).setId("presets").setArchive(zipIcons).setOptional(true);
-        if (maxSize != null && maxSize > 0) {
-            imgProv.setMaxSize(maxSize);
-        }
-        return imgProv.get();
+        final int size = maxSize != null && maxSize > 0 ? maxSize : ImageSizes.SMALLICON.getVirtualWidth();
+        ImageResource resource = new ImageProvider(iconName).setDirs(s).setId("presets").setArchive(zipIcons).setOptional(true)
+                .getResource();
+        return resource == null ? null : resource.getPaddedIcon(new Dimension(size, size));
     }
 
     /**
diff --git a/src/org/openstreetmap/josm/gui/tagging/presets/items/ComboMultiSelect.java b/src/org/openstreetmap/josm/gui/tagging/presets/items/ComboMultiSelect.java
index 541fb26114..5d43e2f7cc 100644
--- a/src/org/openstreetmap/josm/gui/tagging/presets/items/ComboMultiSelect.java
+++ b/src/org/openstreetmap/josm/gui/tagging/presets/items/ComboMultiSelect.java
@@ -5,6 +5,7 @@ import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.Component;
 import java.awt.Font;
+import java.awt.image.BufferedImage;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
@@ -13,9 +14,12 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.TreeMap;
 import java.util.stream.Collectors;
 
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
 import javax.swing.JLabel;
 import javax.swing.JList;
 import javax.swing.JPanel;
@@ -142,7 +146,14 @@ public abstract class ComboMultiSelect extends KeyedItem {
             if (value.getCount() > 0) {
                 l.setFont(l.getFont().deriveFont(Font.ITALIC + Font.BOLD));
             }
-            l.setIcon(value.getIcon());
+            Icon icon = value.getIcon();
+            if (icon == null && value.cms != null) {
+                // use a blank icon if other entries have one, so that all texts line up
+                icon = value.cms.presetListEntries.stream().map(PresetListEntry::getIcon).filter(Objects::nonNull).findFirst()
+                        .map(i -> new ImageIcon(new BufferedImage(i.getIconWidth(), i.getIconHeight(), BufferedImage.TYPE_INT_ARGB)))
+                        .orElse(null);
+            }
+            l.setIcon(icon);
             l.setToolTipText(value.getToolTipText(key));
             return l;
         }
diff --git a/src/org/openstreetmap/josm/tools/ImageResizeMode.java b/src/org/openstreetmap/josm/tools/ImageResizeMode.java
index 638c70f157..58036e555d 100644
--- a/src/org/openstreetmap/josm/tools/ImageResizeMode.java
+++ b/src/org/openstreetmap/josm/tools/ImageResizeMode.java
@@ -94,8 +94,9 @@ enum ImageResizeMode {
             prepareGraphics(icon, bufferedImage, g);
             renderer.accept(g);
         } else if (sourceIcon != null) {
-            sourceIcon = sourceIcon.getScaledInstance(real.width, real.height, Image.SCALE_SMOOTH);
-            g.drawImage(sourceIcon, 0, 0, null);
+            final Dimension scaled = this == PADDED ? AUTO.computeDimension(real, icon) : real;
+            sourceIcon = sourceIcon.getScaledInstance(scaled.width, scaled.height, Image.SCALE_SMOOTH);
+            g.drawImage(sourceIcon, (real.width - scaled.width) / 2, (real.height - scaled.height) / 2, null);
         } else {
             throw new IllegalArgumentException("renderer or sourceIcon");
         }
diff --git a/test/unit/org/openstreetmap/josm/gui/tagging/presets/items/ComboTest.java b/test/unit/org/openstreetmap/josm/gui/tagging/presets/items/ComboTest.java
index 408adc4605..c0084ad860 100644
--- a/test/unit/org/openstreetmap/josm/gui/tagging/presets/items/ComboTest.java
+++ b/test/unit/org/openstreetmap/josm/gui/tagging/presets/items/ComboTest.java
@@ -6,6 +6,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.awt.Color;
 
+import javax.swing.JLabel;
+import javax.swing.JList;
 import javax.swing.JPanel;
 
 import org.junit.jupiter.api.Test;
@@ -16,6 +18,7 @@ import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetItemTest;
 import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
 import org.openstreetmap.josm.testutils.annotations.I18n;
 import org.openstreetmap.josm.testutils.annotations.Main;
+import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
 
 /**
  * Unit tests of {@link Combo} class.
@@ -123,6 +126,26 @@ class ComboTest implements TaggingPresetItemTest {
         KeyedItem.LAST_VALUES.clear();
     }
 
+    /**
+     * Entry icons are centered in a square and entries without an icon get a blank one, so that the texts line up.
+     */
+    @Test
+    void testIconAlignment() {
+        final Combo combo = getInstance();
+        combo.key = "highway";
+        PresetListEntry trunk = new PresetListEntry("trunk", combo);
+        trunk.icon = "presets/transport/way/way_trunk.svg";
+        combo.addListEntry(trunk);
+        combo.addListEntry(new PresetListEntry("busway", combo));
+        combo.addToPanel(new JPanel(), TaggingPresetItemGuiSupport.create(false));
+        JList<PresetListEntry> list = new JList<>();
+        for (PresetListEntry entry : combo.presetListEntries) {
+            JLabel label = (JLabel) combo.combobox.getRenderer().getListCellRendererComponent(list, entry, 0, false, false);
+            assertEquals(ImageSizes.SMALLICON.getAdjustedWidth(), label.getIcon().getIconWidth(), entry.value);
+            assertEquals(ImageSizes.SMALLICON.getAdjustedHeight(), label.getIcon().getIconHeight(), entry.value);
+        }
+    }
+
     @Test
     void testColor() {
         final Combo combo = getInstance();
diff --git a/test/unit/org/openstreetmap/josm/tools/ImageResizeModeTest.java b/test/unit/org/openstreetmap/josm/tools/ImageResizeModeTest.java
index d67c040339..eb049e2938 100644
--- a/test/unit/org/openstreetmap/josm/tools/ImageResizeModeTest.java
+++ b/test/unit/org/openstreetmap/josm/tools/ImageResizeModeTest.java
@@ -6,6 +6,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 
 import java.awt.Dimension;
+import java.awt.image.BufferedImage;
 
 import org.junit.jupiter.api.Test;
 import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
@@ -67,6 +68,22 @@ class ImageResizeModeTest {
         assertEquals(new Dimension(24, 32), ImageResizeMode.PADDED.computeDimension(new Dimension(24, 32), image));
     }
 
+    /**
+     * Test method for {@link ImageResizeMode#createBufferedImage} using {@link ImageResizeMode#PADDED} on a raster image
+     */
+    @Test
+    void testCreateBufferedImagePaddedRaster() {
+        BufferedImage source = new BufferedImage(16, 4, BufferedImage.TYPE_INT_RGB); // opaque black
+        BufferedImage padded = ImageResizeMode.PADDED.createBufferedImage(new Dimension(32, 32), new Dimension(16, 4), null, source);
+        assertEquals(32, padded.getWidth());
+        assertEquals(32, padded.getHeight());
+        // aspect ratio is kept: a 32x8 bar centered vertically
+        assertEquals(0, padded.getRGB(16, 11) >>> 24);
+        assertEquals(0xff, padded.getRGB(16, 12) >>> 24);
+        assertEquals(0xff, padded.getRGB(16, 19) >>> 24);
+        assertEquals(0, padded.getRGB(16, 20) >>> 24);
+    }
+
     /**
      * Test method for {@link ImageResizeMode#cacheKey}
      */