Changeset 16060 in josm


Ignore:
Timestamp:
2020-03-07T20:20:26+01:00 (5 years ago)
Author:
simon04
Message:

see #18871 - ImageProvider.getPadded: fix/improve performance

Location:
trunk/src/org/openstreetmap/josm
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/mappaint/styleelement/MapImage.java

    r14302 r16060  
    2020import org.openstreetmap.josm.gui.util.GuiHelper;
    2121import org.openstreetmap.josm.tools.ImageProvider;
     22import org.openstreetmap.josm.tools.ImageResource;
    2223import org.openstreetmap.josm.tools.Utils;
    2324
     
    3334     */
    3435    private Image img;
     36    private ImageResource imageResource;
    3537
    3638    /**
     
    108110            return getImage();
    109111        }
     112    }
     113
     114    /**
     115     * Get the image resource associated with this MapImage object.
     116     * @return the image resource
     117     */
     118    public ImageResource getImageResource() {
     119        return imageResource;
    110120    }
    111121
     
    139149                .setHeight(height)
    140150                .setOptional(true)
    141                 .getAsync(result -> {
     151                .getResourceAsync(result -> {
    142152                    synchronized (this) {
     153                        imageResource = result;
    143154                        if (result == null) {
    144155                            source.logWarning(tr("Failed to locate image ''{0}''", name));
     
    146157                            img = noIcon == null ? null : noIcon.getImage();
    147158                        } else {
    148                             img = rescale(result.getImage());
     159                            img = rescale(result.getImageIcon().getImage());
    149160                        }
    150161                        if (temporary) {
  • trunk/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPreset.java

    r16041 r16060  
    6868import org.openstreetmap.josm.tools.GBC;
    6969import org.openstreetmap.josm.tools.ImageProvider;
     70import org.openstreetmap.josm.tools.ImageResource;
    7071import org.openstreetmap.josm.tools.Logging;
    7172import org.openstreetmap.josm.tools.Utils;
     
    206207        }
    207208        return null;
     209    }
     210
     211    public final ImageResource getImageResource() {
     212        return (ImageResource) getValue("ImageResource");
    208213    }
    209214
     
    229234                    GuiHelper.runInEDT(() -> {
    230235                        try {
    231                             result.attachImageIcon(this);
     236                            result.attachImageIcon(this, true);
    232237                        } catch (IllegalArgumentException e) {
    233238                            Logging.warn(toString() + ": " + PRESET_ICON_ERROR_MSG_PREFIX + iconName);
  • trunk/src/org/openstreetmap/josm/tools/ImageProvider.java

    r16055 r16060  
    308308    private static final Map<OsmPrimitiveType, ImageIcon> osmPrimitiveTypeCache = new EnumMap<>(OsmPrimitiveType.class);
    309309
    310     /** larger cache of critical padded image icons used in many parts of the application */
    311     private static final Map<Dimension, Map<Image, ImageIcon>> paddedImageCache = new HashMap<>();
    312 
    313310    private static final ExecutorService IMAGE_FETCHER =
    314311            Executors.newSingleThreadExecutor(Utils.newThreadFactory("image-fetcher-%d", Thread.NORM_PRIORITY));
     
    841838        synchronized (ROTATE_CACHE) {
    842839            ROTATE_CACHE.clear();
    843         }
    844         synchronized (paddedImageCache) {
    845             paddedImageCache.clear();
    846840        }
    847841        synchronized (osmPrimitiveTypeCache) {
     
    15561550            final Optional<ImageIcon> icon = TaggingPresets.getMatchingPresets(primitive).stream()
    15571551                    .sorted(Comparator.comparing(p -> p.types == null || p.types.isEmpty() ? Integer.MAX_VALUE : p.types.size()))
    1558                     .map(TaggingPreset::getIcon)
     1552                    .map(TaggingPreset::getImageResource)
    15591553                    .filter(Objects::nonNull)
    1560                     .map(imageIcon -> getPaddedIcon(imageIcon.getImage(), iconSize))
     1554                    .map(resource -> resource.getPaddedIcon(iconSize))
    15611555                    .findFirst();
    15621556            if (icon.isPresent()) {
     
    15681562        return options.contains(GetPaddedOptions.NO_DEFAULT)
    15691563                ? null
    1570                 : getPaddedIcon(get(primitive.getDisplayType()).getImage(), iconSize);
     1564                : new ImageProvider("data", primitive.getDisplayType().getAPIName()).getResource().getPaddedIcon(iconSize);
    15711565    }
    15721566
     
    15961590                NodeElement nodeStyle = (NodeElement) style;
    15971591                MapImage icon = nodeStyle.mapImage;
    1598                 if (icon != null &&
     1592                if (icon != null && icon.getImageResource() != null &&
    15991593                        (icon.name == null || !options.contains(GetPaddedOptions.NO_DEPRECATED) || !icon.name.contains("deprecated"))) {
    1600                     return getPaddedIcon(icon, iconSize);
     1594                    return icon.getImageResource().getPaddedIcon(iconSize);
    16011595                }
    16021596            }
     
    16051599    }
    16061600
    1607     /**
    1608      * Returns an {@link ImageIcon} for the given map image, at the specified size.
    1609      * Uses a cache to improve performance.
    1610      * @param mapImage map image
    1611      * @param iconSize size in pixels
    1612      * @return an {@code ImageIcon} for the given map image, at the specified size
    1613      * @see #clearCache
    1614      * @since 14284
    1615      */
    1616     public static ImageIcon getPaddedIcon(MapImage mapImage, Dimension iconSize) {
    1617         return getPaddedIcon(mapImage.getImage(false), iconSize);
    1618     }
    1619 
    1620     private static ImageIcon getPaddedIcon(Image mapImage, Dimension iconSize) {
    1621         synchronized (paddedImageCache) {
    1622             return paddedImageCache.computeIfAbsent(iconSize, x -> new HashMap<>()).computeIfAbsent(mapImage, icon -> {
    1623                 int backgroundRealWidth = GuiSizesHelper.getSizeDpiAdjusted(iconSize.width);
    1624                 int backgroundRealHeight = GuiSizesHelper.getSizeDpiAdjusted(iconSize.height);
    1625                 int iconRealWidth = icon.getWidth(null);
    1626                 int iconRealHeight = icon.getHeight(null);
    1627                 BufferedImage image = new BufferedImage(backgroundRealWidth, backgroundRealHeight, BufferedImage.TYPE_INT_ARGB);
    1628                 double scaleFactor = Math.min(
    1629                         backgroundRealWidth / (double) iconRealWidth,
    1630                         backgroundRealHeight / (double) iconRealHeight);
    1631                 Image scaledIcon;
    1632                 final int scaledWidth;
    1633                 final int scaledHeight;
    1634                 if (scaleFactor < 1) {
    1635                     // Scale icon such that it fits on background.
    1636                     scaledWidth = (int) (iconRealWidth * scaleFactor);
    1637                     scaledHeight = (int) (iconRealHeight * scaleFactor);
    1638                     scaledIcon = icon.getScaledInstance(scaledWidth, scaledHeight, Image.SCALE_SMOOTH);
    1639                 } else {
    1640                     // Use original size, don't upscale.
    1641                     scaledWidth = iconRealWidth;
    1642                     scaledHeight = iconRealHeight;
    1643                     scaledIcon = icon;
    1644                 }
    1645                 image.getGraphics().drawImage(scaledIcon,
    1646                         (backgroundRealWidth - scaledWidth) / 2,
    1647                         (backgroundRealHeight - scaledHeight) / 2, null);
    1648 
    1649                 return new ImageIcon(image);
    1650             });
    1651         }
     1601    static BufferedImage createPaddedIcon(Image icon, Dimension iconSize) {
     1602        int backgroundRealWidth = GuiSizesHelper.getSizeDpiAdjusted(iconSize.width);
     1603        int backgroundRealHeight = GuiSizesHelper.getSizeDpiAdjusted(iconSize.height);
     1604        int iconRealWidth = icon.getWidth(null);
     1605        int iconRealHeight = icon.getHeight(null);
     1606        BufferedImage image = new BufferedImage(backgroundRealWidth, backgroundRealHeight, BufferedImage.TYPE_INT_ARGB);
     1607        double scaleFactor = Math.min(
     1608                backgroundRealWidth / (double) iconRealWidth,
     1609                backgroundRealHeight / (double) iconRealHeight);
     1610        Image scaledIcon;
     1611        final int scaledWidth;
     1612        final int scaledHeight;
     1613        if (scaleFactor < 1) {
     1614            // Scale icon such that it fits on background.
     1615            scaledWidth = (int) (iconRealWidth * scaleFactor);
     1616            scaledHeight = (int) (iconRealHeight * scaleFactor);
     1617            scaledIcon = icon.getScaledInstance(scaledWidth, scaledHeight, Image.SCALE_SMOOTH);
     1618        } else {
     1619            // Use original size, don't upscale.
     1620            scaledWidth = iconRealWidth;
     1621            scaledHeight = iconRealHeight;
     1622            scaledIcon = icon;
     1623        }
     1624        image.getGraphics().drawImage(scaledIcon,
     1625                (backgroundRealWidth - scaledWidth) / 2,
     1626                (backgroundRealHeight - scaledHeight) / 2, null);
     1627
     1628        return image;
    16521629    }
    16531630
  • trunk/src/org/openstreetmap/josm/tools/ImageResource.java

    r16054 r16060  
    277277    }
    278278
     279    /**
     280     * Returns an {@link ImageIcon} for the given map image, at the specified size.
     281     * Uses a cache to improve performance.
     282     * @param iconSize size in pixels
     283     * @return an {@code ImageIcon} for the given map image, at the specified size
     284     */
     285    public ImageIcon getPaddedIcon(Dimension iconSize) {
     286        final Dimension cacheKey = new Dimension(-iconSize.width, -iconSize.height); // use negative width/height for differentiation
     287        final BufferedImage image = imgCache.computeIfAbsent(cacheKey, ignore ->
     288                ImageProvider.createPaddedIcon(getImageIcon().getImage(), iconSize));
     289        return new ImageIcon(image);
     290    }
     291
    279292    @Override
    280293    public String toString() {
Note: See TracChangeset for help on using the changeset viewer.