Ignore:
Timestamp:
2020-08-28T20:16:25+02:00 (4 years ago)
Author:
simon04
Message:

fix #19706, fix #19725 - ImageProvider/ImageResource: extract ImageResizeMode, add HiDPI support to bounded/padded icons

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/tools/ImageResource.java

    r16926 r16946  
    2929
    3030    /**
    31      * Caches the image data for resized versions of the same image.
    32      */
    33     private final Map<Dimension, BufferedImage> imgCache = new ConcurrentHashMap<>(4);
     31     * Caches the image data for resized versions of the same image. The key is obtained using {@link ImageResizeMode#cacheKey(Dimension)}.
     32     */
     33    private final Map<Integer, BufferedImage> imgCache = new ConcurrentHashMap<>(4);
    3434    /**
    3535     * SVG diagram information in case of SVG vector image.
     
    138138     *         to set the width, but otherwise scale the image proportionally.
    139139     * @return ImageIcon object for the image of this resource, scaled according to dim
    140      * @see #getImageIconBounded(java.awt.Dimension, boolean)
     140     * @see #getImageIconBounded(java.awt.Dimension)
    141141     */
    142142    public ImageIcon getImageIcon(Dimension dim) {
    143         return getImageIcon(dim, true);
     143        return getImageIcon(dim, true, ImageResizeMode.AUTO);
    144144    }
    145145
     
    151151     * (java.awt.image.MultiResolutionImage in Java 9), otherwise a plain {@link BufferedImage}.
    152152     * When running Java 8, this flag has no effect and a plain image will be returned in any case.
     153     * @param resizeMode how to size/resize the image
    153154     * @return ImageIcon object for the image of this resource, scaled according to dim
    154155     * @since 12722
    155156     */
    156     ImageIcon getImageIcon(Dimension dim, boolean multiResolution) {
    157         return getImageIconAlreadyScaled(GuiSizesHelper.getDimensionDpiAdjusted(dim), multiResolution, false);
     157    ImageIcon getImageIcon(Dimension dim, boolean multiResolution, ImageResizeMode resizeMode) {
     158        return getImageIconAlreadyScaled(GuiSizesHelper.getDimensionDpiAdjusted(dim), multiResolution, false, resizeMode);
    158159    }
    159160
     
    167168     * When running Java 8, this flag has no effect and a plain image will be returned in any case.
    168169     * @param highResolution whether the high resolution variant should be used for overlays
     170     * @param resizeMode how to size/resize the image
    169171     * @return ImageIcon object for the image of this resource, scaled according to dim
    170172     */
    171     ImageIcon getImageIconAlreadyScaled(Dimension dim, boolean multiResolution, boolean highResolution) {
     173    ImageIcon getImageIconAlreadyScaled(Dimension dim, boolean multiResolution, boolean highResolution, ImageResizeMode resizeMode) {
    172174        CheckParameterUtil.ensureThat((dim.width > 0 || dim.width == -1) && (dim.height > 0 || dim.height == -1),
    173175                () -> dim + " is invalid");
    174176
    175         BufferedImage img = imgCache.get(dim);
     177        final int cacheKey = resizeMode.cacheKey(dim);
     178        BufferedImage img = imgCache.get(cacheKey);
    176179        if (img == null) {
    177180            if (svg != null) {
    178                 img = ImageProvider.createImageFromSvg(svg, dim);
     181                img = ImageProvider.createImageFromSvg(svg, dim, resizeMode);
    179182                if (img == null) {
    180183                    return null;
     
    182185            } else {
    183186                if (baseImage == null) throw new AssertionError();
    184 
    185187                ImageIcon icon = new ImageIcon(baseImage);
    186                 if (dim.width == -1 && dim.height == -1) {
    187                     dim.width = GuiSizesHelper.getSizeDpiAdjusted(icon.getIconWidth());
    188                     dim.height = GuiSizesHelper.getSizeDpiAdjusted(icon.getIconHeight());
    189                 } else if (dim.width == -1) {
    190                     dim.width = Math.max(1, icon.getIconWidth() * dim.height / icon.getIconHeight());
    191                 } else if (dim.height == -1) {
    192                     dim.height = Math.max(1, icon.getIconHeight() * dim.width / icon.getIconWidth());
    193                 }
    194                 Image i = icon.getImage().getScaledInstance(dim.width, dim.height, Image.SCALE_SMOOTH);
    195                 img = new BufferedImage(dim.width, dim.height, BufferedImage.TYPE_INT_ARGB);
    196                 img.getGraphics().drawImage(i, 0, 0, null);
     188                img = resizeMode.createBufferedImage(dim, new Dimension(icon.getIconWidth(), icon.getIconHeight()),
     189                        g -> g.drawImage(icon.getImage(), 0, 0, null));
    197190            }
    198191            if (overlayInfo != null) {
     
    212205                disabledIcon.paintIcon(new JPanel(), img.getGraphics(), 0, 0);
    213206            }
    214             imgCache.put(dim, img);
     207            imgCache.put(cacheKey, img);
    215208        }
    216209
     
    219212        else {
    220213            try {
    221                 Image mrImg = HiDPISupport.getMultiResolutionImage(img, this);
     214                Image mrImg = HiDPISupport.getMultiResolutionImage(img, this, resizeMode);
    222215                return new ImageIcon(mrImg);
    223216            } catch (NoClassDefFoundError e) {
     
    237230     * which means it is not bounded.
    238231     * @return ImageIcon object for the image of this resource, scaled down if needed, according to maxSize
    239      * @see #getImageIconBounded(java.awt.Dimension, boolean)
    240232     */
    241233    public ImageIcon getImageIconBounded(Dimension maxSize) {
    242         return getImageIconBounded(maxSize, true);
    243     }
    244 
    245     /**
    246      * Get image icon with a certain maximum size. The image is scaled down
    247      * to fit maximum dimensions. (Keeps aspect ratio)
    248      *
    249      * @param maxSize The maximum size. One of the dimensions (width or height) can be -1,
    250      * which means it is not bounded.
    251      * @param  multiResolution If true, return a multi-resolution image
    252      * (java.awt.image.MultiResolutionImage in Java 9), otherwise a plain {@link BufferedImage}.
    253      * When running Java 8, this flag has no effect and a plain image will be returned in any case.
    254      * @return ImageIcon object for the image of this resource, scaled down if needed, according to maxSize
    255      * @since 12722
    256      */
    257     public ImageIcon getImageIconBounded(Dimension maxSize, boolean multiResolution) {
    258         CheckParameterUtil.ensureThat((maxSize.width > 0 || maxSize.width == -1) && (maxSize.height > 0 || maxSize.height == -1),
    259                 () -> maxSize + " is invalid");
    260         float sourceWidth;
    261         float sourceHeight;
    262         int maxWidth = maxSize.width;
    263         int maxHeight = maxSize.height;
    264         if (svg != null) {
    265             sourceWidth = svg.getWidth();
    266             sourceHeight = svg.getHeight();
    267         } else {
    268             if (baseImage == null) throw new AssertionError();
    269             ImageIcon icon = new ImageIcon(baseImage);
    270             sourceWidth = icon.getIconWidth();
    271             sourceHeight = icon.getIconHeight();
    272             if (sourceWidth <= maxWidth) {
    273                 maxWidth = -1;
    274             }
    275             if (sourceHeight <= maxHeight) {
    276                 maxHeight = -1;
    277             }
    278         }
    279 
    280         if (maxWidth == -1 && maxHeight == -1)
    281             return getImageIcon(DEFAULT_DIMENSION, multiResolution);
    282         else if (maxWidth == -1)
    283             return getImageIcon(new Dimension(-1, maxHeight), multiResolution);
    284         else if (maxHeight == -1)
    285             return getImageIcon(new Dimension(maxWidth, -1), multiResolution);
    286         else if (sourceWidth / maxWidth > sourceHeight / maxHeight)
    287             return getImageIcon(new Dimension(maxWidth, -1), multiResolution);
    288         else
    289             return getImageIcon(new Dimension(-1, maxHeight), multiResolution);
     234        return getImageIcon(maxSize, true, ImageResizeMode.BOUNDED);
    290235    }
    291236
     
    297242     */
    298243    public ImageIcon getPaddedIcon(Dimension iconSize) {
    299         final ImageIcon imageIcon = getImageIcon(iconSize);
    300         if (imageIcon.getIconWidth() == iconSize.width && imageIcon.getIconHeight() == iconSize.height) {
    301             // fast path for square and svg icons
    302             return imageIcon;
    303         }
    304 
    305         final Dimension cacheKey = new Dimension(-iconSize.width, -iconSize.height); // use negative width/height for differentiation
    306         BufferedImage image = imgCache.get(cacheKey);
    307         if (image == null) {
    308             image = ImageProvider.createPaddedIcon(getImageIcon().getImage(), iconSize);
    309             imgCache.put(cacheKey, image);
    310         }
    311         return new ImageIcon(image);
     244        return getImageIcon(iconSize, true, ImageResizeMode.PADDED);
    312245    }
    313246
Note: See TracChangeset for help on using the changeset viewer.