Ignore:
Timestamp:
2020-11-26T22:24:27+01:00 (3 years ago)
Author:
simon04
Message:

see #20141 - ImageProvider: cache rendered SVG images using JCS

This experimental feature is disabled by default. Set the advanced preference jcs.cache.use_image_resource_cache=true to enable. No cache eviction for altered images is implemented at the moment.

File:
1 edited

Legend:

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

    r17144 r17364  
    55import java.awt.Image;
    66import java.awt.image.BufferedImage;
     7import java.io.IOException;
     8import java.io.UncheckedIOException;
    79import java.util.List;
    8 import java.util.Map;
    9 import java.util.concurrent.ConcurrentHashMap;
     10import java.util.Locale;
     11import java.util.Objects;
     12import java.util.function.Supplier;
    1013
    1114import javax.swing.AbstractAction;
     
    1518import javax.swing.JPanel;
    1619import javax.swing.UIManager;
     20
     21import org.apache.commons.jcs3.access.behavior.ICacheAccess;
     22import org.openstreetmap.josm.data.cache.BufferedImageCacheEntry;
     23import org.openstreetmap.josm.data.cache.JCSCacheManager;
    1724
    1825import com.kitfox.svg.SVGDiagram;
     
    2936
    3037    /**
    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);
     38     * Caches the image data for resized versions of the same image.
     39     * Depending on {@link JCSCacheManager#USE_IMAGE_RESOURCE_CACHE}, a combined memory/disk, or an in-memory-cache is used.
     40     */
     41    private static final ICacheAccess<String, BufferedImageCacheEntry> imgCache = JCSCacheManager.getImageResourceCache();
     42
     43    private final String cacheKey;
    3444    /**
    3545     * SVG diagram information in case of SVG vector image.
     
    3747    private SVGDiagram svg;
    3848    /**
     49     * Supplier for SVG diagram information in case of possibly cached SVG vector image.
     50     */
     51    private Supplier<SVGDiagram> svgSupplier;
     52    /**
    3953     * Use this dimension to request original file dimension.
    4054     */
     
    5569    /**
    5670     * Constructs a new {@code ImageResource} from an image.
     71     * @param cacheKey the caching identifier of the image
    5772     * @param img the image
    5873     */
    59     public ImageResource(Image img) {
    60         CheckParameterUtil.ensureParameterNotNull(img);
    61         baseImage = img;
     74    public ImageResource(String cacheKey, Image img) {
     75        this.cacheKey = Objects.requireNonNull(cacheKey);
     76        this.baseImage = Objects.requireNonNull(img);
    6277    }
    6378
    6479    /**
    6580     * Constructs a new {@code ImageResource} from SVG data.
     81     * @param cacheKey the caching identifier of the image
    6682     * @param svg SVG data
    6783     */
    68     public ImageResource(SVGDiagram svg) {
    69         CheckParameterUtil.ensureParameterNotNull(svg);
    70         this.svg = svg;
     84    public ImageResource(String cacheKey, SVGDiagram svg) {
     85        this.cacheKey = Objects.requireNonNull(cacheKey);
     86        this.svg = Objects.requireNonNull(svg);
     87    }
     88
     89    public ImageResource(String cacheKey, Supplier<SVGDiagram> svgSupplier) {
     90        this.cacheKey = Objects.requireNonNull(cacheKey);
     91        this.svgSupplier = Objects.requireNonNull(svgSupplier);
    7192    }
    7293
     
    7899     */
    79100    public ImageResource(ImageResource res, List<ImageOverlay> overlayInfo) {
     101        this.cacheKey = res.cacheKey;
    80102        this.svg = res.svg;
     103        this.svgSupplier = res.svgSupplier;
    81104        this.baseImage = res.baseImage;
    82105        this.overlayInfo = overlayInfo;
     
    157180    ImageIcon getImageIcon(Dimension dim, boolean multiResolution, ImageResizeMode resizeMode) {
    158181        return getImageIconAlreadyScaled(GuiSizesHelper.getDimensionDpiAdjusted(dim), multiResolution, false, resizeMode);
     182    }
     183
     184    private BufferedImage getImageFromCache(String cacheKey) {
     185        try {
     186            BufferedImageCacheEntry image = imgCache.get(cacheKey);
     187            if (image == null || image.getImage() == null) {
     188                return null;
     189            }
     190            Logging.trace("{0} is in cache :-)", cacheKey);
     191            return image.getImage();
     192        } catch (IOException e) {
     193            throw new UncheckedIOException(e);
     194        }
    159195    }
    160196
     
    181217            resizeMode = ImageResizeMode.BOUNDED;
    182218        }
    183         final int cacheKey = resizeMode.cacheKey(dim);
    184         BufferedImage img = imgCache.get(cacheKey);
     219        final String cacheKey = String.format(Locale.ROOT, "%s--%s--%d--%d",
     220                this.cacheKey, resizeMode.name(), dim.width, dim.height);
     221        BufferedImage img = getImageFromCache(cacheKey);
    185222        if (img == null) {
     223            if (svgSupplier != null) {
     224                svg = svgSupplier.get();
     225                Logging.trace("{0} is not in cache :-(", cacheKey);
     226                svgSupplier = null;
     227            }
    186228            if (svg != null) {
    187229                img = ImageProvider.createImageFromSvg(svg, dim, resizeMode);
     
    211253                disabledIcon.paintIcon(new JPanel(), img.getGraphics(), 0, 0);
    212254            }
    213             imgCache.put(cacheKey, img);
     255            if (img == null) {
     256                return null;
     257            }
     258            BufferedImageCacheEntry cacheEntry = BufferedImageCacheEntry.pngEncoded(img);
     259            Logging.trace("Storing {0} ({1} bytes) in cache...", cacheKey, cacheEntry.getContent().length);
     260            imgCache.put(cacheKey, cacheEntry);
    214261        }
    215262
     
    251298    }
    252299
     300    static String statistics() {
     301        return String.format("ImageResource cache: [%s]", imgCache.getStatistics());
     302    }
     303
    253304    @Override
    254305    public String toString() {
Note: See TracChangeset for help on using the changeset viewer.